diff --git a/docs/spaces/images/edit-space-feature-visibility.png b/docs/spaces/images/edit-space-feature-visibility.png index 0132337f4a7c66..f1852d3cc03b50 100644 Binary files a/docs/spaces/images/edit-space-feature-visibility.png and b/docs/spaces/images/edit-space-feature-visibility.png differ diff --git a/docs/spaces/images/edit-space.png b/docs/spaces/images/edit-space.png index c78e0d14b0d4c8..9785dd9e77aba2 100644 Binary files a/docs/spaces/images/edit-space.png and b/docs/spaces/images/edit-space.png differ diff --git a/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/customize_space.test.tsx.snap b/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/customize_space.test.tsx.snap new file mode 100644 index 00000000000000..51943c7581273b --- /dev/null +++ b/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/customize_space.test.tsx.snap @@ -0,0 +1,164 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders correctly 1`] = ` + + +

+ +

+ + } + > + + + + + + + } + labelType="label" + > + + + + } + isInvalid={true} + label={ + + } + labelType="label" + > + + +
+ +

+ Choose how your space avatar appears across Kibana. +

+ } + > + + + + } + fullWidth={true} + title={ + +

+ +

+
+ } + > + +
+
+`; diff --git a/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/customize_space_avatar.test.tsx.snap b/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/customize_space_avatar.test.tsx.snap index 058b9ecdd0f8fb..3d709a5dca45a1 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/customize_space_avatar.test.tsx.snap +++ b/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/customize_space_avatar.test.tsx.snap @@ -7,58 +7,67 @@ exports[`renders without crashing 1`] = ` - - - - - diff --git a/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/space_identifier.test.tsx.snap b/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/space_identifier.test.tsx.snap deleted file mode 100644 index f1b4b956eca88f..00000000000000 --- a/x-pack/plugins/spaces/public/management/edit_space/customize_space/__snapshots__/space_identifier.test.tsx.snap +++ /dev/null @@ -1,63 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`renders without crashing 1`] = ` - - - - /s/ - - , - } - } - /> -

- } - isInvalid={false} - label={ -

- - - - -

- } - labelType="label" - > - -
-
-`; diff --git a/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space.test.tsx b/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space.test.tsx new file mode 100644 index 00000000000000..42195317e6731c --- /dev/null +++ b/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space.test.tsx @@ -0,0 +1,87 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { mountWithIntl, shallowWithIntl } from '@kbn/test/jest'; + +import { SpaceValidator } from '../../lib'; +import { CustomizeSpace } from './customize_space'; + +const validator = new SpaceValidator({ shouldValidate: true }); + +test('renders correctly', () => { + const wrapper = shallowWithIntl( + + ); + expect(wrapper).toMatchSnapshot(); +}); + +test('updates identifier, initials and color when name is changed', () => { + const space = { + id: 'space-1', + name: 'Space 1', + initials: 'S1', + color: '#ABCDEF', + }; + const changeHandler = jest.fn(); + + const wrapper = mountWithIntl( + + ); + + wrapper.find('input[name="name"]').simulate('change', { target: { value: 'Space 2' } }); + + expect(changeHandler).toHaveBeenCalledWith({ + ...space, + id: 'space-2', + name: 'Space 2', + initials: 'S2', + color: '#9170B8', + }); +}); + +test('does not update custom identifier, initials or color name is changed', () => { + const space = { + id: 'space-1', + name: 'Space 1', + initials: 'S1', + color: '#ABCDEF', + customAvatarInitials: true, + customAvatarColor: true, + }; + const changeHandler = jest.fn(); + + const wrapper = mountWithIntl( + + ); + + wrapper.find('input[name="name"]').simulate('change', { target: { value: 'Space 2' } }); + + expect(changeHandler).toHaveBeenCalledWith({ + ...space, + name: 'Space 2', + }); +}); diff --git a/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space.tsx b/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space.tsx index 4bbad58b5d139c..27de0e012faf94 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space.tsx @@ -5,31 +5,27 @@ * 2.0. */ -import type { EuiPopoverProps } from '@elastic/eui'; import { EuiDescribedFormGroup, EuiFieldText, EuiFormRow, EuiLoadingSpinner, - EuiPopover, - EuiSpacer, + EuiText, EuiTextArea, EuiTitle, } from '@elastic/eui'; import type { ChangeEvent } from 'react'; -import React, { Component, Fragment, lazy, Suspense } from 'react'; +import React, { Component, lazy, Suspense } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import type { Space } from 'src/plugins/spaces_oss/common'; -import { isReservedSpace } from '../../../../common'; -import { getSpaceAvatarComponent } from '../../../space_avatar'; +import { getSpaceAvatarComponent, getSpaceColor, getSpaceInitials } from '../../../space_avatar'; import type { SpaceValidator } from '../../lib'; import { toSpaceIdentifier } from '../../lib'; +import type { FormValues } from '../manage_space_page'; import { SectionPanel } from '../section_panel'; import { CustomizeSpaceAvatar } from './customize_space_avatar'; -import { SpaceIdentifier } from './space_identifier'; // No need to wrap LazySpaceAvatar in an error boundary, because it is one of the first chunks loaded when opening Kibana. const LazySpaceAvatar = lazy(() => @@ -38,9 +34,9 @@ const LazySpaceAvatar = lazy(() => interface Props { validator: SpaceValidator; - space: Partial; + space: FormValues; editingExistingSpace: boolean; - onChange: (space: Partial) => void; + onChange: (space: FormValues) => void; } interface State { @@ -55,33 +51,31 @@ export class CustomizeSpace extends Component { }; public render() { - const { validator, editingExistingSpace } = this.props; - const { name = '', description = '' } = this.props.space; - const panelTitle = i18n.translate( - 'xpack.spaces.management.manageSpacePage.customizeSpaceTitle', - { - defaultMessage: 'Customize your space', - } - ); - - const extraPopoverProps: Partial = { - initialFocus: 'input[name="spaceInitials"]', - }; + const { validator, editingExistingSpace, space } = this.props; + const { name = '', description = '' } = space; + const panelTitle = i18n.translate('xpack.spaces.management.manageSpacePage.generalTitle', { + defaultMessage: 'General', + }); return ( - +

} - description={this.getPanelDescription()} + description={i18n.translate( + 'xpack.spaces.management.manageSpacePage.describeSpaceDescription', + { + defaultMessage: "Give your space a name that's memorable.", + } + )} fullWidth > { - - - {this.props.space && isReservedSpace(this.props.space) ? null : ( - - - - )} - + + + } helpText={i18n.translate( 'xpack.spaces.management.manageSpacePage.spaceDescriptionHelpText', { - defaultMessage: 'The description appears on the Space selection screen.', + defaultMessage: 'The description appears on the space selection screen.', } )} {...validator.validateSpaceDescription(this.props.space)} @@ -139,80 +123,97 @@ export class CustomizeSpace extends Component { - - - }> - - - + {editingExistingSpace ? null : ( + + } + helpText={ + } - closePopover={this.closePopover} - {...extraPopoverProps} - ownFocus={true} - isOpen={this.state.customizingAvatar} + {...this.props.validator.validateURLIdentifier(this.props.space)} + fullWidth > -
- -
-
-
+ + + )} +
+ + +

+ +

+ + } + description={ + <> +

+ {i18n.translate('xpack.spaces.management.manageSpacePage.avatarDescription', { + defaultMessage: 'Choose how your space avatar appears across Kibana.', + })} +

+ {space.avatarType === 'image' ? ( + }> + + + ) : ( + }> + + + )} + + } + fullWidth + > +
); } - public togglePopover = () => { - this.setState({ - customizingAvatar: !this.state.customizingAvatar, - }); - }; - - public closePopover = () => { - this.setState({ - customizingAvatar: false, - }); - }; - - public getPanelDescription = () => { - return this.props.editingExistingSpace ? ( -

- -

- ) : ( -

- -

- ); - }; - public onNameChange = (e: ChangeEvent) => { if (!this.props.space) { return; @@ -230,6 +231,12 @@ export class CustomizeSpace extends Component { ...this.props.space, name: e.target.value, id, + initials: this.props.space.customAvatarInitials + ? this.props.space.initials + : getSpaceInitials({ name: e.target.value }), + color: this.props.space.customAvatarColor + ? this.props.space.color + : getSpaceColor({ name: e.target.value }), }); }; @@ -240,7 +247,8 @@ export class CustomizeSpace extends Component { }); }; - public onSpaceIdentifierChange = (updatedIdentifier: string) => { + public onSpaceIdentifierChange = (e: ChangeEvent) => { + const updatedIdentifier = e.target.value; const usingCustomIdentifier = updatedIdentifier !== toSpaceIdentifier(this.props.space.name); this.setState({ @@ -252,7 +260,7 @@ export class CustomizeSpace extends Component { }); }; - public onAvatarChange = (space: Partial) => { + public onAvatarChange = (space: FormValues) => { this.props.onChange(space); }; } diff --git a/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space_avatar.test.tsx b/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space_avatar.test.tsx index babd89f69c784e..578da9b96611c4 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space_avatar.test.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space_avatar.test.tsx @@ -10,6 +10,7 @@ import React from 'react'; import { mountWithIntl, shallowWithIntl } from '@kbn/test/jest'; +import { SpaceValidator } from '../../lib'; import { CustomizeSpaceAvatar } from './customize_space_avatar'; const space = { @@ -17,13 +18,19 @@ const space = { name: '', }; +const validator = new SpaceValidator({ shouldValidate: true }); + test('renders without crashing', () => { - const wrapper = shallowWithIntl(); + const wrapper = shallowWithIntl( + + ); expect(wrapper).toMatchSnapshot(); }); test('shows customization fields', () => { - const wrapper = mountWithIntl(); + const wrapper = mountWithIntl( + + ); expect(wrapper.find(EuiLink)).toHaveLength(0); expect(wrapper.find(EuiFieldText)).toHaveLength(2); // EuiColorPicker contains an EuiFieldText element @@ -41,17 +48,14 @@ test('invokes onChange callback when avatar is customized', () => { const changeHandler = jest.fn(); const wrapper = mountWithIntl( - + ); - wrapper - .find(EuiFieldText) - .first() - .find('input') - .simulate('change', { target: { value: 'NV' } }); + wrapper.find('input[name="spaceInitials"]').simulate('change', { target: { value: 'NV' } }); expect(changeHandler).toHaveBeenCalledWith({ ...customizedSpace, initials: 'NV', + customAvatarInitials: true, }); }); diff --git a/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space_avatar.tsx b/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space_avatar.tsx index 96cd094c146458..827ef592459f74 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space_avatar.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/customize_space/customize_space_avatar.tsx @@ -6,46 +6,30 @@ */ import { - EuiButton, + EuiButtonGroup, EuiColorPicker, EuiFieldText, EuiFilePicker, - EuiFlexItem, EuiFormRow, - EuiSpacer, - isValidHex, } from '@elastic/eui'; import type { ChangeEvent } from 'react'; import React, { Component } from 'react'; import { i18n } from '@kbn/i18n'; -import type { Space } from 'src/plugins/spaces_oss/common'; import { MAX_SPACE_INITIALS } from '../../../../common'; import { encode, imageTypes } from '../../../../common/lib/dataurl'; -import { getSpaceColor, getSpaceInitials } from '../../../space_avatar'; +import type { SpaceValidator } from '../../lib'; +import type { FormValues } from '../manage_space_page'; interface Props { - space: Partial; - onChange: (space: Partial) => void; + space: FormValues; + onChange: (space: FormValues) => void; + validator: SpaceValidator; } -interface State { - initialsHasFocus: boolean; - pendingInitials?: string | null; -} - -export class CustomizeSpaceAvatar extends Component { - private initialsRef: HTMLInputElement | null = null; - - constructor(props: Props) { - super(props); - this.state = { - initialsHasFocus: false, - }; - } - - private storeImageChanges(imageUrl: string) { +export class CustomizeSpaceAvatar extends Component { + private storeImageChanges(imageUrl: string | undefined) { this.props.onChange({ ...this.props.space, imageUrl, @@ -96,7 +80,10 @@ export class CustomizeSpaceAvatar extends Component { }; private onFileUpload = (files: FileList | null) => { - if (files == null) return; + if (files == null || files.length === 0) { + this.storeImageChanges(undefined); + return; + } const file = files[0]; if (imageTypes.indexOf(file.type) > -1) { encode(file).then((dataurl: string) => this.handleImageUpload(dataurl)); @@ -106,130 +93,117 @@ export class CustomizeSpaceAvatar extends Component { public render() { const { space } = this.props; - const { initialsHasFocus, pendingInitials } = this.state; - - const spaceColor = getSpaceColor(space); - const isInvalidSpaceColor = !isValidHex(spaceColor) && spaceColor !== ''; - return (
false}> - + this.props.onChange({ + ...space, + avatarType: avatarType as FormValues['avatarType'], + }) + } + buttonSize="m" /> - + {space.avatarType !== 'image' ? ( + + + + ) : ( + + + + )} - - {this.filePickerOrImage()} ); } - private removeImageUrl() { - this.props.onChange({ - ...this.props.space, - imageUrl: '', - }); - } - - public filePickerOrImage() { - if (!this.props.space.imageUrl) { - return ( - - - - ); - } else { - return ( - - this.removeImageUrl()} color="danger" iconType="trash"> - {i18n.translate('xpack.spaces.management.customizeSpaceAvatar.removeImage', { - defaultMessage: 'Remove custom image', - })} - - - ); - } - } - - public initialsInputRef = (ref: HTMLInputElement) => { - if (ref) { - this.initialsRef = ref; - this.initialsRef.addEventListener('focus', this.onInitialsFocus); - this.initialsRef.addEventListener('blur', this.onInitialsBlur); - } else { - if (this.initialsRef) { - this.initialsRef.removeEventListener('focus', this.onInitialsFocus); - this.initialsRef.removeEventListener('blur', this.onInitialsBlur); - this.initialsRef = null; - } - } - }; - - public onInitialsFocus = () => { - this.setState({ - initialsHasFocus: true, - pendingInitials: getSpaceInitials(this.props.space), - }); - }; - - public onInitialsBlur = () => { - this.setState({ - initialsHasFocus: false, - pendingInitials: null, - }); - }; - public onInitialsChange = (e: ChangeEvent) => { const initials = (e.target.value || '').substring(0, MAX_SPACE_INITIALS); - this.setState({ - pendingInitials: initials, - }); - this.props.onChange({ ...this.props.space, + customAvatarInitials: true, initials, }); }; @@ -237,6 +211,7 @@ export class CustomizeSpaceAvatar extends Component { public onColorChange = (color: string) => { this.props.onChange({ ...this.props.space, + customAvatarColor: true, color, }); }; diff --git a/x-pack/plugins/spaces/public/management/edit_space/customize_space/space_identifier.test.tsx b/x-pack/plugins/spaces/public/management/edit_space/customize_space/space_identifier.test.tsx deleted file mode 100644 index f28e17d0e1f034..00000000000000 --- a/x-pack/plugins/spaces/public/management/edit_space/customize_space/space_identifier.test.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -import { shallowWithIntl } from '@kbn/test/jest'; - -import { SpaceValidator } from '../../lib'; -import { SpaceIdentifier } from './space_identifier'; - -test('renders without crashing', () => { - const props = { - space: { - id: '', - name: '', - }, - editable: true, - onChange: jest.fn(), - validator: new SpaceValidator(), - }; - const wrapper = shallowWithIntl( - - ); - expect(wrapper).toMatchSnapshot(); -}); diff --git a/x-pack/plugins/spaces/public/management/edit_space/customize_space/space_identifier.tsx b/x-pack/plugins/spaces/public/management/edit_space/customize_space/space_identifier.tsx deleted file mode 100644 index bc863e4add2cc3..00000000000000 --- a/x-pack/plugins/spaces/public/management/edit_space/customize_space/space_identifier.tsx +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { EuiFieldText, EuiFormRow, EuiLink } from '@elastic/eui'; -import type { ChangeEvent } from 'react'; -import React, { Component, Fragment } from 'react'; - -import type { InjectedIntl } from '@kbn/i18n/react'; -import { FormattedMessage, injectI18n } from '@kbn/i18n/react'; -import type { Space } from 'src/plugins/spaces_oss/common'; - -import type { SpaceValidator } from '../../lib'; -import { toSpaceIdentifier } from '../../lib'; - -interface Props { - space: Partial; - editable: boolean; - validator: SpaceValidator; - intl: InjectedIntl; - onChange: (updatedIdentifier: string) => void; -} - -interface State { - editing: boolean; -} - -class SpaceIdentifierUI extends Component { - private textFieldRef: HTMLInputElement | null = null; - - constructor(props: Props) { - super(props); - this.state = { - editing: false, - }; - } - - public render() { - const { intl } = this.props; - const { id = '' } = this.props.space; - - return ( - - - (this.textFieldRef = ref)} - fullWidth - /> - - - ); - } - - public getLabel = () => { - if (!this.props.editable) { - return ( -

- -

- ); - } - - const editLinkText = this.state.editing ? ( - - ) : ( - - ); - - const editLinkLabel = this.state.editing - ? this.props.intl.formatMessage({ - id: 'xpack.spaces.management.spaceIdentifier.resetSpaceNameLinkLabel', - defaultMessage: 'Reset the URL identifier', - }) - : this.props.intl.formatMessage({ - id: 'xpack.spaces.management.spaceIdentifier.customizeSpaceNameLinkLabel', - defaultMessage: 'Customize the URL identifier', - }); - - return ( -

- - - {editLinkText} - -

- ); - }; - - public getHelpText = ( - identifier: string = this.props.intl.formatMessage({ - id: 'xpack.spaces.management.spaceIdentifier.emptySpaceIdentifierText', - defaultMessage: 'awesome-space', - }) - ) => { - return ( -

- /s/{identifier}, - }} - /> -

- ); - }; - - public onEditClick = () => { - const currentlyEditing = this.state.editing; - if (currentlyEditing) { - // "Reset" clicked. Create space identifier based on the space name. - const resetIdentifier = toSpaceIdentifier(this.props.space.name); - - this.setState({ - editing: false, - }); - this.props.onChange(resetIdentifier); - } else { - this.setState( - { - editing: true, - }, - () => { - if (this.textFieldRef) { - this.textFieldRef.focus(); - } - } - ); - } - }; - - public onChange = (e: ChangeEvent) => { - if (!this.state.editing) { - return; - } - this.props.onChange(e.target.value); - }; -} - -export const SpaceIdentifier = injectI18n(SpaceIdentifierUI); diff --git a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/__snapshots__/enabled_features.test.tsx.snap b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/__snapshots__/enabled_features.test.tsx.snap index c22a25ef60c313..b23b504bd0264a 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/__snapshots__/enabled_features.test.tsx.snap +++ b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/__snapshots__/enabled_features.test.tsx.snap @@ -3,34 +3,7 @@ exports[`EnabledFeatures renders as expected 1`] = ` - - - - - - - - - } + title="Features" > @@ -39,7 +12,7 @@ exports[`EnabledFeatures renders as expected 1`] = ` >

@@ -54,9 +27,17 @@ exports[`EnabledFeatures renders as expected 1`] = ` >

, + } + } />

diff --git a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.test.tsx b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.test.tsx index 7f1ea57a6b89c5..af6c546fcf56a7 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.test.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.test.tsx @@ -32,11 +32,9 @@ const features: KibanaFeatureConfig[] = [ ]; describe('EnabledFeatures', () => { - const getUrlForApp = (appId: string) => appId; - it(`renders as expected`, () => { expect( - shallowWithIntl( + shallowWithIntl( { disabledFeatures: ['feature-1', 'feature-2'], }} onChange={jest.fn()} - getUrlForApp={getUrlForApp} /> ) ).toMatchSnapshot(); @@ -63,7 +60,6 @@ describe('EnabledFeatures', () => { disabledFeatures: ['feature-1', 'feature-2'], }} onChange={changeHandler} - getUrlForApp={getUrlForApp} /> ); @@ -97,7 +93,6 @@ describe('EnabledFeatures', () => { disabledFeatures: [], }} onChange={changeHandler} - getUrlForApp={getUrlForApp} /> ); @@ -134,7 +129,6 @@ describe('EnabledFeatures', () => { disabledFeatures: [], }} onChange={changeHandler} - getUrlForApp={getUrlForApp} /> ); @@ -164,7 +158,6 @@ describe('EnabledFeatures', () => { disabledFeatures: ['feature-1', 'feature-2'], }} onChange={changeHandler} - getUrlForApp={getUrlForApp} /> ); @@ -192,7 +185,6 @@ describe('EnabledFeatures', () => { disabledFeatures: ['feature-1'], }} onChange={jest.fn()} - getUrlForApp={getUrlForApp} /> ); expect(findTestSubject(wrapper, 'hideAllFeaturesLink')).toHaveLength(1); @@ -211,7 +203,6 @@ describe('EnabledFeatures', () => { disabledFeatures: [], }} onChange={changeHandler} - getUrlForApp={getUrlForApp} /> ); @@ -239,7 +230,6 @@ describe('EnabledFeatures', () => { disabledFeatures: [], }} onChange={changeHandler} - getUrlForApp={getUrlForApp} /> ); diff --git a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.tsx b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.tsx index 667878df3254a5..7481676430307c 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/enabled_features.tsx @@ -5,17 +5,16 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; -import type { ReactNode } from 'react'; -import React, { Component, Fragment } from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiLink, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; +import type { FunctionComponent } from 'react'; +import React from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import type { ApplicationStart } from 'src/core/public'; import type { Space } from 'src/plugins/spaces_oss/common'; +import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; import type { KibanaFeatureConfig } from '../../../../../features/public'; -import { getEnabledFeatures } from '../../lib/feature_utils'; import { SectionPanel } from '../section_panel'; import { FeatureTable } from './feature_table'; @@ -23,117 +22,62 @@ interface Props { space: Partial; features: KibanaFeatureConfig[]; onChange: (space: Partial) => void; - getUrlForApp: ApplicationStart['getUrlForApp']; } -export class EnabledFeatures extends Component { - public render() { - const description = i18n.translate( - 'xpack.spaces.management.manageSpacePage.customizeVisibleFeatures', - { - defaultMessage: 'Customize visible features', - } - ); +export const EnabledFeatures: FunctionComponent = (props) => { + const { services } = useKibana(); + const canManageRoles = services.application?.capabilities.management?.security?.roles === true; - return ( - - - - -

- -

-
- - {this.getDescription()} -
- - - -
-
- ); - } - - private getPanelTitle = () => { - const featureCount = this.props.features.length; - const enabledCount = getEnabledFeatures(this.props.features, this.props.space).length; - - let details: null | ReactNode = null; - - if (enabledCount === featureCount) { - details = ( - - - - - - ); - } else if (enabledCount === 0) { - details = ( - - - - - - ); - } else { - details = ( - - - - - - ); - } - - return ( - - {' '} - {details} - - ); - }; - - private getDescription = () => { - return ( - - -

- -

-
-
- ); - }; -} + return ( + + + + +

+ +

+
+ + +

+ + + + ) : ( + + ), + }} + /> +

+
+
+ + + +
+
+ ); +}; diff --git a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/feature_table.scss b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/feature_table.scss deleted file mode 100644 index 35b9dc1d45661b..00000000000000 --- a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/feature_table.scss +++ /dev/null @@ -1,4 +0,0 @@ -.spcFeatureTableAccordionContent { - // Align accordion content with the feature category logo in the accordion's buttonContent - padding-left: $euiSizeXL; -} diff --git a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/feature_table.tsx b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/feature_table.tsx index 2c9eaf4563d05b..78ea73741a8adc 100644 --- a/x-pack/plugins/spaces/public/management/edit_space/enabled_features/feature_table.tsx +++ b/x-pack/plugins/spaces/public/management/edit_space/enabled_features/feature_table.tsx @@ -5,18 +5,16 @@ * 2.0. */ -import './feature_table.scss'; - import type { EuiCheckboxProps } from '@elastic/eui'; import { EuiAccordion, + EuiButtonEmpty, EuiCallOut, EuiCheckbox, EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiIcon, - EuiLink, EuiSpacer, EuiText, EuiTitle, @@ -88,9 +86,9 @@ export class FeatureTable extends Component { const buttonContent = ( { if (!canExpandCategory) { const isChecked = enabledCount > 0; @@ -101,31 +99,28 @@ export class FeatureTable extends Component { } }} > - - - {category.euiIconType ? ( ) : null} - -

{category.label}

+ +

{category.label}

); const label: string = i18n.translate('xpack.spaces.management.featureAccordionSwitchLabel', { - defaultMessage: '{enabledCount} / {featureCount} features visible', + defaultMessage: '{enabledCount}/{featureCount} features visible', values: { enabledCount, featureCount, }, }); const extraAction = ( -