mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Spaces] Enhancement in create space UI (#191586)
This commit is contained in:
parent
a156e6726f
commit
3a5747803b
4 changed files with 124 additions and 4 deletions
|
@ -98,6 +98,8 @@ describe('ManageSpacePage', () => {
|
|||
nameInput.simulate('change', { target: { value: 'New Space Name' } });
|
||||
descriptionInput.simulate('change', { target: { value: 'some description' } });
|
||||
|
||||
updateSpace(wrapper, false, 'oblt');
|
||||
|
||||
const createButton = wrapper.find('button[data-test-subj="save-space-button"]');
|
||||
createButton.simulate('click');
|
||||
await Promise.resolve();
|
||||
|
@ -110,9 +112,78 @@ describe('ManageSpacePage', () => {
|
|||
color: '#AA6556',
|
||||
imageUrl: '',
|
||||
disabledFeatures: [],
|
||||
solution: 'oblt',
|
||||
});
|
||||
});
|
||||
|
||||
it('validates the form (name, initials, solution view...)', async () => {
|
||||
const spacesManager = spacesManagerMock.create();
|
||||
spacesManager.createSpace = jest.fn(spacesManager.createSpace);
|
||||
spacesManager.getActiveSpace = jest.fn().mockResolvedValue(space);
|
||||
|
||||
const wrapper = mountWithIntl(
|
||||
<ManageSpacePage
|
||||
spacesManager={spacesManager as unknown as SpacesManager}
|
||||
getFeatures={featuresStart.getFeatures}
|
||||
notifications={notificationServiceMock.createStartContract()}
|
||||
history={history}
|
||||
capabilities={{
|
||||
navLinks: {},
|
||||
management: {},
|
||||
catalogue: {},
|
||||
spaces: { manage: true },
|
||||
}}
|
||||
eventTracker={eventTracker}
|
||||
allowFeatureVisibility
|
||||
allowSolutionVisibility
|
||||
/>
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
wrapper.update();
|
||||
expect(wrapper.find('input[name="name"]')).toHaveLength(1);
|
||||
});
|
||||
|
||||
const createButton = wrapper.find('button[data-test-subj="save-space-button"]');
|
||||
createButton.simulate('click');
|
||||
await Promise.resolve();
|
||||
|
||||
{
|
||||
const errors = wrapper.find('.euiFormErrorText').map((node) => node.text());
|
||||
expect(errors).toEqual([
|
||||
'Enter a name.',
|
||||
'Enter a URL identifier.',
|
||||
'Enter initials.',
|
||||
'Select one solution.',
|
||||
]);
|
||||
|
||||
expect(spacesManager.createSpace).not.toHaveBeenCalled();
|
||||
|
||||
const nameInput = wrapper.find('input[name="name"]');
|
||||
nameInput.simulate('change', { target: { value: 'New Space Name' } });
|
||||
}
|
||||
|
||||
createButton.simulate('click');
|
||||
await Promise.resolve();
|
||||
|
||||
{
|
||||
const errors = wrapper.find('.euiFormErrorText').map((node) => node.text());
|
||||
expect(errors).toEqual(['Select one solution.']); // requires solution view to be set
|
||||
}
|
||||
|
||||
updateSpace(wrapper, false, 'oblt');
|
||||
|
||||
createButton.simulate('click');
|
||||
await Promise.resolve();
|
||||
|
||||
{
|
||||
const errors = wrapper.find('.euiFormErrorText').map((node) => node.text());
|
||||
expect(errors).toEqual([]); // no more errors
|
||||
}
|
||||
|
||||
expect(spacesManager.createSpace).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('shows solution view select when visible', async () => {
|
||||
const spacesManager = spacesManagerMock.create();
|
||||
spacesManager.createSpace = jest.fn(spacesManager.createSpace);
|
||||
|
|
|
@ -206,6 +206,8 @@ export class ManageSpacePage extends Component<Props, State> {
|
|||
<SolutionView
|
||||
space={this.state.space}
|
||||
onChange={this.onSolutionViewChange}
|
||||
validator={this.validator}
|
||||
isEditing={this.editingExistingSpace()}
|
||||
sectionTitle={i18n.translate(
|
||||
'xpack.spaces.management.manageSpacePage.navigationTitle',
|
||||
{ defaultMessage: 'Navigation' }
|
||||
|
@ -373,7 +375,11 @@ export class ManageSpacePage extends Component<Props, State> {
|
|||
const originalSpace: Space = this.state.originalSpace as Space;
|
||||
const space: Space = this.state.space as Space;
|
||||
const { haveDisabledFeaturesChanged, hasSolutionViewChanged } = this.state;
|
||||
const result = this.validator.validateForSave(space);
|
||||
const result = this.validator.validateForSave(
|
||||
space,
|
||||
this.editingExistingSpace(),
|
||||
this.props.allowSolutionVisibility
|
||||
);
|
||||
if (result.isInvalid) {
|
||||
this.setState({
|
||||
formError: result,
|
||||
|
|
|
@ -24,6 +24,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
import type { Space } from '../../../../common';
|
||||
import type { SpaceValidator } from '../../lib';
|
||||
import { SectionPanel } from '../section_panel';
|
||||
|
||||
type SolutionView = Space['solution'];
|
||||
|
@ -98,10 +99,18 @@ const getOptions = ({ size }: EuiThemeComputed): Array<EuiSuperSelectOption<Solu
|
|||
interface Props {
|
||||
space: Partial<Space>;
|
||||
onChange: (space: Partial<Space>) => void;
|
||||
isEditing: boolean;
|
||||
validator: SpaceValidator;
|
||||
sectionTitle?: string;
|
||||
}
|
||||
|
||||
export const SolutionView: FunctionComponent<Props> = ({ space, onChange, sectionTitle }) => {
|
||||
export const SolutionView: FunctionComponent<Props> = ({
|
||||
space,
|
||||
onChange,
|
||||
validator,
|
||||
isEditing,
|
||||
sectionTitle,
|
||||
}) => {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
|
||||
return (
|
||||
|
@ -132,6 +141,7 @@ export const SolutionView: FunctionComponent<Props> = ({ space, onChange, sectio
|
|||
defaultMessage: 'Solution view',
|
||||
})}
|
||||
fullWidth
|
||||
{...validator.validateSolutionView(space, isEditing)}
|
||||
>
|
||||
<EuiSuperSelect
|
||||
options={getOptions(euiTheme)}
|
||||
|
@ -140,6 +150,13 @@ export const SolutionView: FunctionComponent<Props> = ({ space, onChange, sectio
|
|||
onChange={(solution) => {
|
||||
onChange({ ...space, solution });
|
||||
}}
|
||||
placeholder={i18n.translate(
|
||||
'xpack.spaces.management.navigation.solutionViewDefaultValue',
|
||||
{
|
||||
defaultMessage: 'Classic (Default)',
|
||||
}
|
||||
)}
|
||||
isInvalid={validator.validateSolutionView(space, isEditing).isInvalid}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -169,11 +169,31 @@ export class SpaceValidator {
|
|||
return valid();
|
||||
}
|
||||
|
||||
public validateSolutionView(
|
||||
space: FormValues,
|
||||
isEditing: boolean,
|
||||
allowSolutionVisibility = true
|
||||
) {
|
||||
if (!this.shouldValidate || isEditing || !allowSolutionVisibility) {
|
||||
return valid();
|
||||
}
|
||||
|
||||
if (!space.solution) {
|
||||
return invalid(
|
||||
i18n.translate('xpack.spaces.management.validateSpace.requiredSolutionViewErrorMessage', {
|
||||
defaultMessage: 'Select one solution.',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return valid();
|
||||
}
|
||||
|
||||
public validateEnabledFeatures(space: FormValues) {
|
||||
return valid();
|
||||
}
|
||||
|
||||
public validateForSave(space: FormValues) {
|
||||
public validateForSave(space: FormValues, isEditing: boolean, allowSolutionVisibility: boolean) {
|
||||
const { isInvalid: isNameInvalid } = this.validateSpaceName(space);
|
||||
const { isInvalid: isDescriptionInvalid } = this.validateSpaceDescription(space);
|
||||
const { isInvalid: isIdentifierInvalid } = this.validateURLIdentifier(space);
|
||||
|
@ -181,6 +201,11 @@ export class SpaceValidator {
|
|||
const { isInvalid: isAvatarColorInvalid } = this.validateAvatarColor(space);
|
||||
const { isInvalid: isAvatarImageInvalid } = this.validateAvatarImage(space);
|
||||
const { isInvalid: areFeaturesInvalid } = this.validateEnabledFeatures(space);
|
||||
const { isInvalid: isSolutionViewInvalid } = this.validateSolutionView(
|
||||
space,
|
||||
isEditing,
|
||||
allowSolutionVisibility
|
||||
);
|
||||
|
||||
if (
|
||||
isNameInvalid ||
|
||||
|
@ -189,7 +214,8 @@ export class SpaceValidator {
|
|||
isAvatarInitialsInvalid ||
|
||||
isAvatarColorInvalid ||
|
||||
isAvatarImageInvalid ||
|
||||
areFeaturesInvalid
|
||||
areFeaturesInvalid ||
|
||||
isSolutionViewInvalid
|
||||
) {
|
||||
return invalid();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue