Skip to content

Commit

Permalink
Merge branch 'main' into new-ux-ds-creation
Browse files Browse the repository at this point in the history
  • Loading branch information
yibow98 authored Oct 10, 2022
2 parents 56d4bf8 + d6197a7 commit b799626
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 19 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* Add updated_at column to objects' tables ([#1218](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/1218))
* [Viz Builder] State validation before dispatching and loading ([#2351](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2351))
* [Viz Builder] Create a new wizard directly on a dashboard ([#2384](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2384))
* [Viz Builder] Edit wizard directly on dashboard ([#2508](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2508))
* [Multi DataSource] UX enhacement on index pattern management stack ([#2505](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2505))
* [Multi DataSource] UX enhancement on Data source management stack ([#2521](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2521))
* [Multi DataSource] UX enhancement on Update stored password modal for Data source management stack ([#2532](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2532))

### 🐛 Bug Fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
EuiButton,
EuiButtonEmpty,
EuiDescribedFormGroup,
EuiFieldPassword,
EuiFieldText,
EuiFlexGroup,
EuiFlexItem,
Expand Down Expand Up @@ -459,8 +460,9 @@ export class EditDataSourceForm extends React.Component<EditDataSourceProps, Edi
>
<EuiFlexGroup>
<EuiFlexItem>
<EuiFieldText
<EuiFieldPassword
placeholder={DATA_SOURCE_PASSWORD_PLACEHOLDER}
type={'dual'}
value={
this.props.existingDataSource.auth.type !== AuthType.NoAuth
? '********'
Expand All @@ -470,6 +472,7 @@ export class EditDataSourceForm extends React.Component<EditDataSourceProps, Edi
onChange={this.onChangePassword}
onBlur={this.validatePassword}
disabled={this.props.existingDataSource.auth.type !== AuthType.NoAuth}
data-test-subj="updateDataSourceFormPasswordField"
/>
</EuiFlexItem>
{this.props.existingDataSource.auth.type !== AuthType.NoAuth ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,18 @@ import {
EuiModalFooter,
EuiModalHeader,
EuiModalHeaderTitle,
EuiSpacer,
EuiText,
} from '@elastic/eui';
import { NEW_PASSWORD_TEXT, UPDATE_STORED_PASSWORD, USERNAME } from '../../../text_content';
import {
CANCEL_TEXT,
CONFIRM_NEW_PASSWORD_TEXT,
NEW_PASSWORD_TEXT,
PASSWORD_NO_MATCH,
UPDATE_STORED_PASSWORD,
UPDATE_STORED_PASSWORD_DESCRIPTION,
USERNAME,
} from '../../../text_content';

export interface UpdatePasswordModalProps {
username: string;
Expand All @@ -32,13 +41,34 @@ export const UpdatePasswordModal = ({
}: UpdatePasswordModalProps) => {
/* State Variables */
const [newPassword, setNewPassword] = useState<string>('');
const [confirmNewPassword, setConfirmNewPassword] = useState<string>('');
const [isNewPasswordValid, setIsNewPasswordValid] = useState<boolean>(true);
const [isConfirmNewPasswordValid, setIsConfirmNewPasswordValid] = useState<string[]>([]);

const onClickUpdatePassword = () => {
if (!!newPassword) {
if (isFormValid()) {
handleUpdatePassword(newPassword);
}
};

const isFormValid = () => {
return !!(newPassword && confirmNewPassword && confirmNewPassword === newPassword);
};

const validateNewPassword = () => {
setIsNewPasswordValid(!!newPassword);
};

const validateConfirmNewPassword = () => {
const invalidReason: string[] = [];
if (!confirmNewPassword) {
invalidReason.push('');
} else if (confirmNewPassword !== newPassword) {
invalidReason.push(PASSWORD_NO_MATCH);
}
setIsConfirmNewPasswordValid(invalidReason);
};

const renderUpdatePasswordModal = () => {
return (
<EuiModal onClose={closeUpdatePasswordModal}>
Expand All @@ -49,33 +79,59 @@ export const UpdatePasswordModal = ({
</EuiModalHeader>

<EuiModalBody>
<EuiFormRow>
<EuiText size="m" style={{ fontWeight: 300 }}>
{UPDATE_STORED_PASSWORD_DESCRIPTION}
</EuiText>
</EuiFormRow>
<EuiSpacer size="m" />

<EuiForm data-test-subj="data-source-update-password">
{/* Username */}
<EuiFormRow label={USERNAME}>
<EuiText size="s">{username}</EuiText>
</EuiFormRow>
{/* Password */}
<EuiFormRow label={NEW_PASSWORD_TEXT}>
{/* updated Password */}
<EuiFormRow label={NEW_PASSWORD_TEXT} isInvalid={!isNewPasswordValid}>
<EuiFieldPassword
name="updatedPassword"
placeholder={NEW_PASSWORD_TEXT}
type={'dual'}
value={newPassword}
isInvalid={!isNewPasswordValid}
onChange={(e) => setNewPassword(e.target.value)}
onBlur={validateNewPassword}
/>
</EuiFormRow>
{/* Password */}
<EuiFormRow
label={CONFIRM_NEW_PASSWORD_TEXT}
isInvalid={!!isConfirmNewPasswordValid.length}
error={isConfirmNewPasswordValid}
>
<EuiFieldPassword
name="confirmUpdatedPassword"
placeholder={CONFIRM_NEW_PASSWORD_TEXT}
type={'dual'}
value={confirmNewPassword}
isInvalid={!!isConfirmNewPasswordValid.length}
onChange={(e) => setConfirmNewPassword(e.target.value)}
onBlur={validateConfirmNewPassword}
/>
</EuiFormRow>
</EuiForm>
</EuiModalBody>

<EuiModalFooter>
<EuiButtonEmpty onClick={closeUpdatePasswordModal}>Cancel</EuiButtonEmpty>
<EuiButtonEmpty onClick={closeUpdatePasswordModal}>{CANCEL_TEXT}</EuiButtonEmpty>
<EuiButton
type="submit"
form="modalFormId"
onClick={onClickUpdatePassword}
fill={!!newPassword}
disabled={!newPassword}
fill={isFormValid()}
disabled={!isFormValid()}
>
Update
{UPDATE_STORED_PASSWORD}
</EuiButton>
</EuiModalFooter>
</EuiModal>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,19 @@ export const DELETE_THIS_DATA_SOURCE = i18n.translate(
export const NEW_PASSWORD_TEXT = i18n.translate(
'dataSourcesManagement.editDataSource.newPassword',
{
defaultMessage: 'New password',
defaultMessage: 'Updated password',
}
);
export const CONFIRM_NEW_PASSWORD_TEXT = i18n.translate(
'dataSourcesManagement.editDataSource.confirmNewPassword',
{
defaultMessage: 'Confirm Updated password',
}
);
export const PASSWORD_NO_MATCH = i18n.translate(
'dataSourcesManagement.editDataSource.passwordNoMatch',
{
defaultMessage: 'Passwords do not match',
}
);
export const UPDATE_STORED_PASSWORD = i18n.translate(
Expand All @@ -185,6 +197,13 @@ export const UPDATE_STORED_PASSWORD = i18n.translate(
defaultMessage: 'Update stored password',
}
);
export const UPDATE_STORED_PASSWORD_DESCRIPTION = i18n.translate(
'dataSourcesManagement.editDataSource.updateStoredPasswordDescription',
{
defaultMessage:
'Update credential password to reflect accurate password to gain access to the endpoint.',
}
);
export const CONNECTION_DETAILS_TITLE = i18n.translate(
'dataSourcesManagement.editDataSource.connectionDetailsText',
{
Expand Down
69 changes: 60 additions & 9 deletions src/plugins/wizard/public/application/utils/get_top_nav_config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ import React from 'react';
import { i18n } from '@osd/i18n';
import { TopNavMenuData } from '../../../../navigation/public';
import {
OnSaveProps,
SavedObjectSaveModalOrigin,
SavedObjectSaveOpts,
showSaveModal,
} from '../../../../saved_objects/public';
import { WizardServices } from '../..';
Expand All @@ -58,7 +58,7 @@ export const getTopNavConfig = (
scopedHistory,
} = services;

const { originatingApp } =
const { originatingApp, embeddableId } =
embeddable
.getStateTransfer(scopedHistory)
.getIncomingEditorState({ keysToRemoveAfterFetch: ['id', 'input'] }) || {};
Expand All @@ -67,15 +67,20 @@ export const getTopNavConfig = (
const topNavConfig: TopNavMenuData[] = [
{
id: 'save',
iconType: 'save',
iconType: savedWizardVis?.id && originatingApp ? undefined : ('save' as const),
emphasize: savedWizardVis && !savedWizardVis.id,
description: i18n.translate('wizard.topNavMenu.saveVisualizationButtonAriaLabel', {
defaultMessage: 'Save Visualization',
}),
className: 'saveButton',
label: i18n.translate('wizard.topNavMenu.saveVisualizationButtonLabel', {
defaultMessage: 'save',
}),
className: savedWizardVis?.id && originatingApp ? 'saveAsButton' : '',
label:
savedWizardVis?.id && originatingApp
? i18n.translate('wizard.topNavMenu.saveVisualizationAsButtonLabel', {
defaultMessage: 'save as',
})
: i18n.translate('wizard.topNavMenu.saveVisualizationButtonLabel', {
defaultMessage: 'save',
}),
testId: 'wizardSaveButton',
disableButton: !!saveDisabledReason,
tooltip: saveDisabledReason,
Expand All @@ -100,6 +105,46 @@ export const getTopNavConfig = (
showSaveModal(saveModal, I18nContext);
},
},
...(originatingApp && ((savedWizardVis && savedWizardVis.id) || embeddableId)
? [
{
id: 'saveAndReturn',
label: i18n.translate('visualize.topNavMenu.saveAndReturnVisualizationButtonLabel', {
defaultMessage: 'Save and return',
}),
emphasize: true,
iconType: 'checkInCircleFilled' as const,
description: i18n.translate(
'wizard.topNavMenu.saveAndReturnVisualizationButtonAriaLabel',
{
defaultMessage: 'Finish editing wizard and return to the last app',
}
),
testId: 'wizardsaveAndReturnButton',
disableButton: !!saveDisabledReason,
tooltip: saveDisabledReason,
run: async () => {
const saveOptions = {
newTitle: savedWizardVis.title,
newCopyOnSave: false,
isTitleDuplicateConfirmed: false,
newDescription: savedWizardVis.description,
returnToOrigin: true,
};

const onSave = getOnSave(
savedWizardVis,
originatingApp,
visualizationIdFromUrl,
dispatch,
services
);

return onSave(saveOptions);
},
},
]
: []),
];

return topNavConfig;
Expand All @@ -119,18 +164,24 @@ export const getOnSave = (
onTitleDuplicate,
newDescription,
returnToOrigin,
}: OnSaveProps & { returnToOrigin: boolean }) => {
}: SavedObjectSaveOpts & {
newTitle: string;
newCopyOnSave: boolean;
returnToOrigin: boolean;
newDescription?: string;
}) => {
const { embeddable, toastNotifications, application, history } = services;
const stateTransfer = embeddable.getStateTransfer();

if (!savedWizardVis) {
return;
}
const newlyCreated = !savedWizardVis.id || savedWizardVis.copyOnSave;

const currentTitle = savedWizardVis.title;
savedWizardVis.title = newTitle;
savedWizardVis.description = newDescription;
savedWizardVis.copyOnSave = newCopyOnSave;
const newlyCreated = !savedWizardVis.id || savedWizardVis.copyOnSave;

try {
const id = await savedWizardVis.save({
Expand Down

0 comments on commit b799626

Please sign in to comment.