Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/fragments/8375.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
feat:
- [Workspace]Update details panel UI in workspace create page ([#8375](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8375))
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import {
EuiColorPicker,
EuiDescribedFormGroup,
EuiFieldText,
EuiFlexGroup,
EuiFlexItem,
EuiFormControlLayout,
EuiFormRow,
EuiPanel,
EuiText,
} from '@elastic/eui';
import { EuiColorPickerOutput } from '@elastic/eui/src/components/color_picker/color_picker';
import { i18n } from '@osd/i18n';
import { WorkspaceDescriptionField, WorkspaceNameField } from '../workspace_form';
import { generateRightSidebarScrollProps, RightSidebarScrollField } from './utils';

interface CreatorDetailsPanelProps {
color?: string;
name?: string;
description?: string;
onColorChange: (text: string, output: EuiColorPickerOutput) => void;
onNameChange: (name: string) => void;
onDescriptionChange: (description: string) => void;
}

export const CreatorDetailsPanel = ({
color,
name,
description,
onColorChange,
onNameChange,
onDescriptionChange,
}: CreatorDetailsPanelProps) => {
return (
<EuiPanel>
<EuiText size="s">
<h2>
{i18n.translate('workspace.creator.details.panel.title', {
defaultMessage: 'Workspace details',
})}
</h2>
</EuiText>
<EuiDescribedFormGroup
title={
<h4 {...generateRightSidebarScrollProps(RightSidebarScrollField.Name)}>
{i18n.translate('workspace.creator.details.panel.fields.name.title', {
defaultMessage: 'Workspace name',
})}
</h4>
}
description={i18n.translate('workspace.creator.details.panel.fields.name.description', {
defaultMessage:
'Use a unique name for the workspace. Valid characters are a-z, A-Z, 0-9, (), [], _ (underscore), - (hyphen) and (space). You can also select a color for the workspace icon.',
})}
>
<EuiFlexGroup gutterSize="s">
<EuiFlexItem style={{ maxWidth: 64 }} grow={false}>
<EuiFormRow
label={i18n.translate('workspace.creator.details.panel.fields.color.label', {
defaultMessage: 'Color',
})}
{...generateRightSidebarScrollProps(RightSidebarScrollField.Color)}
>
<EuiColorPicker
color={color}
onChange={onColorChange}
compressed
button={
<EuiFormControlLayout
icon={{
type: 'arrowDown',
side: 'right',
}}
style={{ color }}
compressed
>
{/** Add empty value here to keep the same UI with name input. Use read only will render a different background */}
<EuiFieldText icon={{ type: 'swatchInput', size: 'm' }} value="" compressed />
</EuiFormControlLayout>
}
/>
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem>
<WorkspaceNameField
onChange={onNameChange}
value={name}
placeholder={i18n.translate(
'workspace.creator.details.panel.fields.name.placeholder',
{
defaultMessage: 'Enter the name for the workspace',
}
)}
showDescription={false}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiDescribedFormGroup>
<EuiDescribedFormGroup
title={
<h4 {...generateRightSidebarScrollProps(RightSidebarScrollField.Description)}>
{i18n.translate('workspace.creator.details.panel.fields.description.title', {
defaultMessage: 'Workspace description',
})}
</h4>
}
>
<WorkspaceDescriptionField value={description} onChange={onDescriptionChange} />
</EuiDescribedFormGroup>
</EuiPanel>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ describe('WorkspaceCreator', () => {
});

it('create workspace with detailed information', async () => {
const { getByTestId } = render(<WorkspaceCreator />);
const { getByTestId, getByRole } = render(<WorkspaceCreator />);

// Ensure workspace create form rendered
await waitFor(() => {
Expand All @@ -246,18 +246,15 @@ describe('WorkspaceCreator', () => {
fireEvent.input(descriptionInput, {
target: { value: 'test workspace description' },
});
const colorSelector = getByTestId(
'euiColorPickerAnchor workspaceForm-workspaceDetails-colorPicker'
);
fireEvent.input(colorSelector, {
target: { value: '#000000' },
});
const colorSelector = getByTestId('euiColorPickerAnchor');
fireEvent.click(colorSelector);
fireEvent.click(getByRole('option', { name: 'Select #54B399 as the color' }));
fireEvent.click(getByTestId('workspaceUseCase-observability'));
fireEvent.click(getByTestId('workspaceForm-bottomBar-createButton'));
expect(workspaceClientCreate).toHaveBeenCalledWith(
expect.objectContaining({
name: 'test workspace name',
color: '#000000',
color: '#54B399',
description: 'test workspace description',
features: expect.arrayContaining(['use-case-observability']),
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,7 @@
*/

import React, { useCallback, useRef } from 'react';
import {
EuiSpacer,
EuiTitle,
EuiForm,
EuiText,
EuiCompressedFormRow,
EuiColorPicker,
EuiFlexItem,
EuiFlexGroup,
} from '@elastic/eui';
import { EuiSpacer, EuiTitle, EuiForm, EuiText, EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
import { i18n } from '@osd/i18n';
import {
useWorkspaceForm,
Expand All @@ -23,12 +14,11 @@ import {
SelectDataSourcePanel,
usersAndPermissionsCreatePageTitle,
WorkspaceFormProps,
WorkspaceNameField,
WorkspaceDescriptionField,
} from '../workspace_form';

import { WorkspaceFormSummaryPanel } from './workspace_form_summary_panel';
import { generateRightSidebarScrollProps, RightSidebarScrollField } from './utils';
import { CreatorDetailsPanel } from './creator_details_panel';

import './workspace_creator_form.scss';

Expand Down Expand Up @@ -84,7 +74,7 @@ export const WorkspaceCreatorForm = (props: WorkspaceCreatorFormProps) => {

return (
<EuiFlexGroup className="workspaceCreateFormContainer">
<EuiFlexItem style={{ maxWidth: 768 }}>
<EuiFlexItem style={{ maxWidth: 848 }}>
<EuiForm
id={formId}
onSubmit={handleFormSubmit}
Expand All @@ -97,13 +87,15 @@ export const WorkspaceCreatorForm = (props: WorkspaceCreatorFormProps) => {
<EuiSpacer />
</>
)}
<EuiTitle size="xs">
<h3>
{i18n.translate('workspace.creator.form.customizeTitle', {
defaultMessage: 'Customize the workspace',
})}
</h3>
</EuiTitle>
<CreatorDetailsPanel
name={formData.name}
color={formData.color}
description={formData.description}
onNameChange={handleNameInputChange}
onColorChange={handleColorChange}
onDescriptionChange={setDescription}
/>
<EuiSpacer size="m" />
<div {...generateRightSidebarScrollProps(RightSidebarScrollField.UseCase)}>
<WorkspaceUseCase
value={formData.useCase}
Expand All @@ -113,40 +105,6 @@ export const WorkspaceCreatorForm = (props: WorkspaceCreatorFormProps) => {
/>
</div>
<EuiSpacer size="m" />
<div {...generateRightSidebarScrollProps(RightSidebarScrollField.Name)} />
<WorkspaceNameField
value={formData.name}
onChange={handleNameInputChange}
error={formErrors.name?.message}
/>
<EuiSpacer size="m" />
<div {...generateRightSidebarScrollProps(RightSidebarScrollField.Description)} />
<WorkspaceDescriptionField value={formData.description} onChange={setDescription} />
<EuiSpacer size="m" />
<EuiCompressedFormRow
label={i18n.translate('workspace.form.workspaceDetails.color.label', {
defaultMessage: 'Workspace icon color',
})}
isInvalid={!!formErrors.color}
error={formErrors.color?.message}
{...generateRightSidebarScrollProps(RightSidebarScrollField.Color)}
>
<div>
<EuiText size="xs" color="subdued">
{i18n.translate('workspace.form.workspaceDetails.color.description', {
defaultMessage:
'Select a background color for the icon representing this workspace.',
})}
</EuiText>
<EuiSpacer size={'s'} />
<EuiColorPicker
color={formData.color}
onChange={handleColorChange}
data-test-subj="workspaceForm-workspaceDetails-colorPicker"
/>
</div>
</EuiCompressedFormRow>
<EuiSpacer />
{/* SelectDataSourcePanel is only visible for dashboard admin and when data source is enabled*/}
{isDashboardAdmin && isDataSourceEnabled && (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@ export interface WorkspaceNameFieldProps {
onChange: (newValue: string) => void;
error?: string;
readOnly?: boolean;
placeholder?: string;
showDescription?: boolean;
}

export const WorkspaceNameField = ({
value,
error,
readOnly,
onChange,
placeholder,
showDescription = true,
}: WorkspaceNameFieldProps) => {
const handleChange = useCallback(
(e) => {
Expand All @@ -46,11 +50,15 @@ export const WorkspaceNameField = ({
},
})}
</EuiTextColor>
<br />
{i18n.translate('workspace.form.workspaceDetails.name.helpText', {
defaultMessage:
'Use a unique name for the workspace. Valid characters are a-z, A-Z, 0-9, (), [], _ (underscore), - (hyphen) and (space).',
})}
{showDescription && (
<>
<br />
{i18n.translate('workspace.form.workspaceDetails.name.helpText', {
defaultMessage:
'Use a unique name for the workspace. Valid characters are a-z, A-Z, 0-9, (), [], _ (underscore), - (hyphen) and (space).',
})}
</>
)}
</>
}
isInvalid={!!error || charactersOverflow}
Expand All @@ -61,9 +69,12 @@ export const WorkspaceNameField = ({
onChange={handleChange}
readOnly={readOnly}
data-test-subj="workspaceForm-workspaceDetails-nameInputText"
placeholder={i18n.translate('workspace.form.workspaceDetails.name.placeholder', {
defaultMessage: 'Enter a name',
})}
placeholder={
placeholder ||
i18n.translate('workspace.form.workspaceDetails.name.placeholder', {
defaultMessage: 'Enter a name',
})
}
/>
</EuiCompressedFormRow>
);
Expand Down