Convert security management pages to new layout (#101660)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Larry Gregory 2021-06-29 14:38:56 -04:00 committed by GitHub
parent 770aa79121
commit 6c172ead19
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 796 additions and 838 deletions

View file

@ -17,11 +17,9 @@ import {
EuiInMemoryTable,
EuiPageContent,
EuiPageContentBody,
EuiPageContentHeader,
EuiPageContentHeaderSection,
EuiPageHeader,
EuiSpacer,
EuiText,
EuiTitle,
EuiToolTip,
} from '@elastic/eui';
import type { History } from 'history';
@ -126,7 +124,7 @@ export class APIKeysGridPage extends Component<Props, State> {
if (!apiKeys) {
if (isLoadingApp) {
return (
<EuiPageContent>
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="subdued">
<SectionLoading>
<FormattedMessage
id="xpack.security.management.apiKeys.table.loadingApiKeysDescription"
@ -143,7 +141,7 @@ export class APIKeysGridPage extends Component<Props, State> {
if (error) {
return (
<EuiPageContent>
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="danger">
<ApiKeysEmptyPrompt error={error}>
<EuiButton iconType="refresh" onClick={this.reloadApiKeys}>
<FormattedMessage
@ -167,9 +165,13 @@ export class APIKeysGridPage extends Component<Props, State> {
if (!isLoadingTable && apiKeys && apiKeys.length === 0) {
return (
<EuiPageContent>
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="subdued">
<ApiKeysEmptyPrompt>
<EuiButton {...reactRouterNavigate(this.props.history, '/create')} fill>
<EuiButton
{...reactRouterNavigate(this.props.history, '/create')}
fill
iconType="plusInCircleFilled"
>
<FormattedMessage
id="xpack.security.management.apiKeys.table.createButton"
defaultMessage="Create API key"
@ -183,42 +185,45 @@ export class APIKeysGridPage extends Component<Props, State> {
const concatenated = `${this.state.createdApiKey?.id}:${this.state.createdApiKey?.api_key}`;
return (
<EuiPageContent>
<EuiPageContentHeader>
<EuiPageContentHeaderSection>
<EuiTitle>
<h1>
<>
<EuiPageHeader
bottomBorder
pageTitle={
<FormattedMessage
id="xpack.security.management.apiKeys.table.apiKeysTitle"
defaultMessage="API Keys"
/>
}
description={
<>
{isAdmin ? (
<FormattedMessage
id="xpack.security.management.apiKeys.table.apiKeysTitle"
defaultMessage="API Keys"
id="xpack.security.management.apiKeys.table.apiKeysAllDescription"
defaultMessage="View and delete API keys. An API key sends requests on behalf of a user."
/>
</h1>
</EuiTitle>
<EuiText color="subdued" size="s" data-test-subj="apiKeysDescriptionText">
<p>
{isAdmin ? (
<FormattedMessage
id="xpack.security.management.apiKeys.table.apiKeysAllDescription"
defaultMessage="View and delete API keys. An API key sends requests on behalf of a user."
/>
) : (
<FormattedMessage
id="xpack.security.management.apiKeys.table.apiKeysOwnDescription"
defaultMessage="View and delete your API keys. An API key sends requests on your behalf."
/>
)}
</p>
</EuiText>
</EuiPageContentHeaderSection>
<EuiPageContentHeaderSection>
<EuiButton {...reactRouterNavigate(this.props.history, '/create')}>
) : (
<FormattedMessage
id="xpack.security.management.apiKeys.table.apiKeysOwnDescription"
defaultMessage="View and delete your API keys. An API key sends requests on your behalf."
/>
)}
</>
}
rightSideItems={[
<EuiButton
{...reactRouterNavigate(this.props.history, '/create')}
fill
iconType="plusInCircleFilled"
>
<FormattedMessage
id="xpack.security.management.apiKeys.table.createButton"
defaultMessage="Create API key"
/>
</EuiButton>
</EuiPageContentHeaderSection>
</EuiPageContentHeader>
</EuiButton>,
]}
/>
<EuiSpacer size="l" />
{this.state.createdApiKey && !this.state.isLoadingTable && (
<>
@ -302,7 +307,7 @@ export class APIKeysGridPage extends Component<Props, State> {
)}
<EuiPageContentBody>{this.renderTable()}</EuiPageContentBody>
</EuiPageContent>
</>
);
}

View file

@ -5,33 +5,31 @@
* 2.0.
*/
import { EuiEmptyPrompt, EuiFlexGroup, EuiPageContent } from '@elastic/eui';
import { EuiEmptyPrompt, EuiPageContent } from '@elastic/eui';
import React from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
export const PermissionDenied = () => (
<EuiFlexGroup gutterSize="none">
<EuiPageContent horizontalPosition="center">
<EuiEmptyPrompt
iconType="securityApp"
title={
<h2 data-test-subj="apiKeysPermissionDeniedMessage">
<FormattedMessage
id="xpack.security.management.apiKeys.deniedPermissionTitle"
defaultMessage="You need permission to manage API keys"
/>
</h2>
}
body={
<p data-test-subj="permissionDeniedMessage">
<FormattedMessage
id="xpack.security.management.apiKeys.noPermissionToManageRolesDescription"
defaultMessage="Contact your system administrator."
/>
</p>
}
/>
</EuiPageContent>
</EuiFlexGroup>
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="danger">
<EuiEmptyPrompt
iconType="securityApp"
title={
<h2 data-test-subj="apiKeysPermissionDeniedMessage">
<FormattedMessage
id="xpack.security.management.apiKeys.deniedPermissionTitle"
defaultMessage="You need permission to manage API keys"
/>
</h2>
}
body={
<p data-test-subj="permissionDeniedMessage">
<FormattedMessage
id="xpack.security.management.apiKeys.noPermissionToManageRolesDescription"
defaultMessage="Contact your system administrator."
/>
</p>
}
/>
</EuiPageContent>
);

View file

@ -19,7 +19,7 @@ export const NoCompatibleRealms: React.FunctionComponent = () => {
title={
<FormattedMessage
id="xpack.security.management.roleMappings.noCompatibleRealmsErrorTitle"
defaultMessage="No compatible realms are enabled in Elasticsearch"
defaultMessage="No compatible realms appear to be enabled in Elasticsearch"
/>
}
color="warning"
@ -27,7 +27,7 @@ export const NoCompatibleRealms: React.FunctionComponent = () => {
>
<FormattedMessage
id="xpack.security.management.roleMappings.noCompatibleRealmsErrorDescription"
defaultMessage="Role mappings will not be applied to any users. Contact your system administrator and refer to the {link} for more information."
defaultMessage="Role mappings may not be applied to users. Contact your system administrator and refer to the {link} for more information."
values={{
link: (
<EuiLink href={docLinks.links.security.mappingRoles} external target="_blank">

View file

@ -5,33 +5,31 @@
* 2.0.
*/
import { EuiEmptyPrompt, EuiFlexGroup, EuiPageContent } from '@elastic/eui';
import { EuiEmptyPrompt, EuiPageContent } from '@elastic/eui';
import React from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
export const PermissionDenied = () => (
<EuiFlexGroup gutterSize="none">
<EuiPageContent horizontalPosition="center">
<EuiEmptyPrompt
iconType="securityApp"
title={
<h2>
<FormattedMessage
id="xpack.security.management.roleMappings.deniedPermissionTitle"
defaultMessage="You need permission to manage role mappings"
/>
</h2>
}
body={
<p data-test-subj="permissionDeniedMessage">
<FormattedMessage
id="xpack.security.management.roleMappings.deniedPermissionDescription"
defaultMessage="Contact your system administrator."
/>
</p>
}
/>
</EuiPageContent>
</EuiFlexGroup>
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="subdued">
<EuiEmptyPrompt
iconType="securityApp"
title={
<h2>
<FormattedMessage
id="xpack.security.management.roleMappings.deniedPermissionTitle"
defaultMessage="You need permission to manage role mappings"
/>
</h2>
}
body={
<p data-test-subj="permissionDeniedMessage">
<FormattedMessage
id="xpack.security.management.roleMappings.deniedPermissionDescription"
defaultMessage="Contact your system administrator."
/>
</p>
}
/>
</EuiPageContent>
);

View file

@ -13,11 +13,10 @@ import {
EuiForm,
EuiLink,
EuiPageContent,
EuiPageHeader,
EuiSpacer,
EuiText,
EuiTitle,
} from '@elastic/eui';
import React, { Component, Fragment } from 'react';
import React, { Component } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
@ -96,17 +95,50 @@ export class EditRoleMappingPage extends Component<Props, State> {
if (loadState === 'loading') {
return (
<EuiPageContent>
<EuiPageContent horizontalPosition="center" verticalPosition="center" color="subdued">
<SectionLoading />
</EuiPageContent>
);
}
return (
<div>
<>
<EuiPageHeader
bottomBorder
pageTitle={this.getFormTitle()}
description={
<>
<FormattedMessage
id="xpack.security.management.editRoleMapping.roleMappingDescription"
defaultMessage="Use role mappings to control which roles are assigned to your users. {learnMoreLink}"
values={{
learnMoreLink: (
<EuiLink
href={this.props.docLinks.links.security.mappingRoles}
external={true}
target="_blank"
>
<FormattedMessage
id="xpack.security.management.editRoleMapping.learnMoreLinkText"
defaultMessage="Learn more about role mappings."
/>
</EuiLink>
),
}}
/>
{!this.state.hasCompatibleRealms && (
<>
<EuiSpacer size="s" />
<NoCompatibleRealms />
</>
)}
</>
}
/>
<EuiSpacer size="l" />
<EuiForm isInvalid={this.state.formError.isInvalid} error={this.state.formError.error}>
{this.getFormTitle()}
<EuiSpacer />
<MappingInfoPanel
roleMapping={this.state.roleMapping!}
onChange={(roleMapping) => this.setState({ roleMapping })}
@ -135,57 +167,24 @@ export class EditRoleMappingPage extends Component<Props, State> {
<EuiSpacer />
{this.getFormButtons()}
</EuiForm>
</div>
</>
);
}
private getFormTitle = () => {
if (this.editingExistingRoleMapping()) {
return (
<FormattedMessage
id="xpack.security.management.editRoleMapping.editRoleMappingTitle"
defaultMessage="Edit role mapping"
/>
);
}
return (
<Fragment>
<EuiTitle size="l">
<h1>
{this.editingExistingRoleMapping() ? (
<FormattedMessage
id="xpack.security.management.editRoleMapping.editRoleMappingTitle"
defaultMessage="Edit role mapping"
/>
) : (
<FormattedMessage
id="xpack.security.management.editRoleMapping.createRoleMappingTitle"
defaultMessage="Create role mapping"
/>
)}
</h1>
</EuiTitle>
<EuiText color="subdued" size="s">
<p>
<FormattedMessage
id="xpack.security.management.editRoleMapping.roleMappingDescription"
defaultMessage="Use role mappings to control which roles are assigned to your users. {learnMoreLink}"
values={{
learnMoreLink: (
<EuiLink
href={this.props.docLinks.links.security.mappingRoles}
external={true}
target="_blank"
>
<FormattedMessage
id="xpack.security.management.editRoleMapping.learnMoreLinkText"
defaultMessage="Learn more."
/>
</EuiLink>
),
}}
/>
</p>
</EuiText>
{!this.state.hasCompatibleRealms && (
<>
<EuiSpacer size="s" />
<NoCompatibleRealms />
</>
)}
</Fragment>
<FormattedMessage
id="xpack.security.management.editRoleMapping.createRoleMappingTitle"
defaultMessage="Create role mapping"
/>
);
};

View file

@ -61,7 +61,7 @@ export class MappingInfoPanel extends Component<Props, State> {
}
public render() {
return (
<EuiPanel>
<EuiPanel hasShadow={false} hasBorder={true}>
<EuiTitle>
<h2>
<FormattedMessage

View file

@ -76,7 +76,7 @@ export class RuleEditorPanel extends Component<Props, State> {
}
return (
<EuiPanel>
<EuiPanel hasShadow={false} hasBorder={true}>
<EuiTitle>
<h2>
<FormattedMessage

View file

@ -37,6 +37,8 @@ export class RuleGroupEditor extends Component<Props, {}> {
return (
<EuiPanel
className={`secRoleMapping__ruleEditorGroup--${this.props.ruleDepth % 2 ? 'odd' : 'even'}`}
hasBorder={true}
hasShadow={false}
>
<EuiFlexGroup direction="column">
<EuiFlexItem>

View file

@ -88,7 +88,7 @@ export class RoleMappingsGridPage extends Component<Props, State> {
if (loadState === 'loadingApp') {
return (
<EuiPageContent>
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="subdued">
<SectionLoading>
<FormattedMessage
id="xpack.security.management.roleMappings.loadingRoleMappingsDescription"
@ -105,7 +105,7 @@ export class RoleMappingsGridPage extends Component<Props, State> {
} = error;
return (
<EuiPageContent>
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="danger">
<EuiCallOut
title={
<FormattedMessage

View file

@ -1,7 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`it renders without blowing up 1`] = `
<EuiPanel>
<EuiPanel
hasBorder={true}
hasShadow={false}
>
<EuiFlexGroup
alignItems="baseline"
gutterSize="s"

View file

@ -46,7 +46,7 @@ export class CollapsiblePanel extends Component<Props, State> {
public render() {
return (
<EuiPanel>
<EuiPanel hasShadow={false} hasBorder={true}>
{this.getTitle()}
{this.getForm()}
</EuiPanel>

View file

@ -374,7 +374,7 @@ export const EditRolePage: FunctionComponent<Props> = ({
const getRoleName = () => {
return (
<EuiPanel>
<EuiPanel hasShadow={false} hasBorder={true}>
<EuiFormRow
label={
<FormattedMessage

View file

@ -208,7 +208,7 @@ exports[`it renders without crashing 1`] = `
/>
<EuiHorizontalRule />
<EuiButton
iconType="plusInCircleFilled"
iconType="plusInCircle"
onClick={[Function]}
>
<FormattedMessage

View file

@ -176,7 +176,7 @@ export class ElasticsearchPrivileges extends Component<Props, {}> {
<EuiHorizontalRule />
{this.props.editable && (
<EuiButton iconType={'plusInCircleFilled'} onClick={this.addIndexPrivilege}>
<EuiButton iconType={'plusInCircle'} onClick={this.addIndexPrivilege}>
<FormattedMessage
id="xpack.security.management.editRole.elasticSearchPrivileges.addIndexPrivilegesButtonLabel"
defaultMessage="Add index privilege"

View file

@ -199,7 +199,7 @@ export class SpaceAwarePrivilegeSection extends Component<Props, State> {
<EuiButton
color="primary"
onClick={this.addSpacePrivilege}
iconType={'plusInCircleFilled'}
iconType={'plusInCircle'}
data-test-subj={'addSpacePrivilegeButton'}
isDisabled={!hasAvailableSpaces || !this.props.editable}
>

View file

@ -2,61 +2,86 @@
exports[`<RolesGridPage /> renders permission denied if required 1`] = `
<PermissionDenied>
<EuiFlexGroup
gutterSize="none"
<EuiPageContent
color="danger"
horizontalPosition="center"
verticalPosition="center"
>
<div
className="euiFlexGroup euiFlexGroup--directionRow euiFlexGroup--responsive"
<EuiPanel
className="euiPageContent euiPageContent--verticalCenter euiPageContent--horizontalCenter"
color="danger"
paddingSize="l"
role="main"
>
<EuiPageContent
horizontalPosition="center"
<div
className="euiPanel euiPanel--paddingLarge euiPanel--borderRadiusMedium euiPanel--danger euiPanel--noShadow euiPanel--noBorder euiPageContent euiPageContent--verticalCenter euiPageContent--horizontalCenter"
role="main"
>
<EuiPanel
className="euiPageContent euiPageContent--horizontalCenter"
paddingSize="l"
role="main"
<EuiEmptyPrompt
body={
<p
data-test-subj="permissionDeniedMessage"
>
<FormattedMessage
defaultMessage="Contact your system administrator."
id="xpack.security.management.roles.noPermissionToManageRolesDescription"
values={Object {}}
/>
</p>
}
iconType="securityApp"
title={
<h2>
<FormattedMessage
defaultMessage="You need permission to manage roles"
id="xpack.security.management.roles.deniedPermissionTitle"
values={Object {}}
/>
</h2>
}
>
<div
className="euiPanel euiPanel--paddingLarge euiPanel--borderRadiusMedium euiPanel--plain euiPanel--hasShadow euiPageContent euiPageContent--horizontalCenter"
role="main"
className="euiEmptyPrompt"
>
<EuiEmptyPrompt
body={
<p
data-test-subj="permissionDeniedMessage"
>
<FormattedMessage
defaultMessage="Contact your system administrator."
id="xpack.security.management.roles.noPermissionToManageRolesDescription"
values={Object {}}
/>
</p>
}
iconType="securityApp"
title={
<h2>
<FormattedMessage
defaultMessage="You need permission to manage roles"
id="xpack.security.management.roles.deniedPermissionTitle"
values={Object {}}
/>
</h2>
}
<EuiIcon
color="subdued"
size="xxl"
type="securityApp"
>
<span
color="subdued"
data-euiicon-type="securityApp"
size="xxl"
/>
</EuiIcon>
<EuiSpacer
size="m"
>
<div
className="euiEmptyPrompt"
className="euiSpacer euiSpacer--m"
/>
</EuiSpacer>
<EuiTitle
size="m"
>
<h2
className="euiTitle euiTitle--medium"
>
<EuiIcon
color="subdued"
size="xxl"
type="securityApp"
<FormattedMessage
defaultMessage="You need permission to manage roles"
id="xpack.security.management.roles.deniedPermissionTitle"
values={Object {}}
>
<span
color="subdued"
data-euiicon-type="securityApp"
size="xxl"
/>
</EuiIcon>
You need permission to manage roles
</FormattedMessage>
</h2>
</EuiTitle>
<EuiTextColor
color="subdued"
>
<span
className="euiTextColor euiTextColor--subdued"
>
<EuiSpacer
size="m"
>
@ -64,59 +89,29 @@ exports[`<RolesGridPage /> renders permission denied if required 1`] = `
className="euiSpacer euiSpacer--m"
/>
</EuiSpacer>
<EuiTitle
size="m"
>
<h2
className="euiTitle euiTitle--medium"
<EuiText>
<div
className="euiText euiText--medium"
>
<FormattedMessage
defaultMessage="You need permission to manage roles"
id="xpack.security.management.roles.deniedPermissionTitle"
values={Object {}}
<p
data-test-subj="permissionDeniedMessage"
>
You need permission to manage roles
</FormattedMessage>
</h2>
</EuiTitle>
<EuiTextColor
color="subdued"
>
<span
className="euiTextColor euiTextColor--subdued"
>
<EuiSpacer
size="m"
>
<div
className="euiSpacer euiSpacer--m"
/>
</EuiSpacer>
<EuiText>
<div
className="euiText euiText--medium"
<FormattedMessage
defaultMessage="Contact your system administrator."
id="xpack.security.management.roles.noPermissionToManageRolesDescription"
values={Object {}}
>
<p
data-test-subj="permissionDeniedMessage"
>
<FormattedMessage
defaultMessage="Contact your system administrator."
id="xpack.security.management.roles.noPermissionToManageRolesDescription"
values={Object {}}
>
Contact your system administrator.
</FormattedMessage>
</p>
</div>
</EuiText>
</span>
</EuiTextColor>
</div>
</EuiEmptyPrompt>
Contact your system administrator.
</FormattedMessage>
</p>
</div>
</EuiText>
</span>
</EuiTextColor>
</div>
</EuiPanel>
</EuiPageContent>
</div>
</EuiFlexGroup>
</EuiEmptyPrompt>
</div>
</EuiPanel>
</EuiPageContent>
</PermissionDenied>
`;

View file

@ -5,33 +5,31 @@
* 2.0.
*/
import { EuiEmptyPrompt, EuiFlexGroup, EuiPageContent } from '@elastic/eui';
import { EuiEmptyPrompt, EuiPageContent } from '@elastic/eui';
import React from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
export const PermissionDenied = () => (
<EuiFlexGroup gutterSize="none">
<EuiPageContent horizontalPosition="center">
<EuiEmptyPrompt
iconType="securityApp"
title={
<h2>
<FormattedMessage
id="xpack.security.management.roles.deniedPermissionTitle"
defaultMessage="You need permission to manage roles"
/>
</h2>
}
body={
<p data-test-subj="permissionDeniedMessage">
<FormattedMessage
id="xpack.security.management.roles.noPermissionToManageRolesDescription"
defaultMessage="Contact your system administrator."
/>
</p>
}
/>
</EuiPageContent>
</EuiFlexGroup>
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="danger">
<EuiEmptyPrompt
iconType="securityApp"
title={
<h2>
<FormattedMessage
id="xpack.security.management.roles.deniedPermissionTitle"
defaultMessage="You need permission to manage roles"
/>
</h2>
}
body={
<p data-test-subj="permissionDeniedMessage">
<FormattedMessage
id="xpack.security.management.roles.noPermissionToManageRolesDescription"
defaultMessage="Contact your system administrator."
/>
</p>
}
/>
</EuiPageContent>
);

View file

@ -13,13 +13,10 @@ import {
EuiFlexItem,
EuiInMemoryTable,
EuiLink,
EuiPageContent,
EuiPageContentBody,
EuiPageContentHeader,
EuiPageContentHeaderSection,
EuiPageHeader,
EuiSpacer,
EuiSwitch,
EuiText,
EuiTitle,
} from '@elastic/eui';
import _ from 'lodash';
import React, { Component } from 'react';
@ -90,100 +87,96 @@ export class RolesGridPage extends Component<Props, State> {
private getPageContent = () => {
const { roles } = this.state;
return (
<EuiPageContent>
<EuiPageContentHeader>
<EuiPageContentHeaderSection>
<EuiTitle>
<h1>
<FormattedMessage
id="xpack.security.management.roles.roleTitle"
defaultMessage="Roles"
/>
</h1>
</EuiTitle>
<EuiText color="subdued" size="s">
<p>
<FormattedMessage
id="xpack.security.management.roles.subtitle"
defaultMessage="Apply roles to groups of users and manage permissions across the stack."
/>
</p>
</EuiText>
</EuiPageContentHeaderSection>
<EuiPageContentHeaderSection>
<>
<EuiPageHeader
bottomBorder
pageTitle={
<FormattedMessage
id="xpack.security.management.roles.roleTitle"
defaultMessage="Roles"
/>
}
description={
<FormattedMessage
id="xpack.security.management.roles.subtitle"
defaultMessage="Apply roles to groups of users and manage permissions across the stack."
/>
}
rightSideItems={[
<EuiButton
data-test-subj="createRoleButton"
{...reactRouterNavigate(this.props.history, getRoleManagementHref('edit'))}
fill
iconType="plusInCircleFilled"
>
<FormattedMessage
id="xpack.security.management.roles.createRoleButtonLabel"
defaultMessage="Create role"
/>
</EuiButton>
</EuiPageContentHeaderSection>
</EuiPageContentHeader>
<EuiPageContentBody>
{this.state.showDeleteConfirmation ? (
<ConfirmDelete
onCancel={this.onCancelDelete}
rolesToDelete={this.state.selection.map((role) => role.name)}
callback={this.handleDelete}
notifications={this.props.notifications}
rolesAPIClient={this.props.rolesAPIClient}
/>
) : null}
</EuiButton>,
]}
/>
{
<EuiInMemoryTable
itemId="name"
responsive={false}
columns={this.getColumnConfig()}
hasActions={true}
selection={{
selectable: (role: Role) => !role.metadata || !role.metadata._reserved,
selectableMessage: (selectable: boolean) => (!selectable ? 'Role is reserved' : ''),
onSelectionChange: (selection: Role[]) => this.setState({ selection }),
}}
pagination={{
initialPageSize: 20,
pageSizeOptions: [10, 20, 30, 50, 100],
}}
items={this.state.visibleRoles}
loading={roles.length === 0}
search={{
toolsLeft: this.renderToolsLeft(),
toolsRight: this.renderToolsRight(),
box: {
incremental: true,
'data-test-subj': 'searchRoles',
},
onChange: (query: Record<string, any>) => {
this.setState({
filter: query.queryText,
visibleRoles: this.getVisibleRoles(
this.state.roles,
query.queryText,
this.state.includeReservedRoles
),
});
},
}}
sorting={{
sort: {
field: 'name',
direction: 'asc',
},
}}
rowProps={() => {
return {
'data-test-subj': 'roleRow',
};
}}
isSelectable
/>
}
</EuiPageContentBody>
</EuiPageContent>
<EuiSpacer size="l" />
{this.state.showDeleteConfirmation ? (
<ConfirmDelete
onCancel={this.onCancelDelete}
rolesToDelete={this.state.selection.map((role) => role.name)}
callback={this.handleDelete}
notifications={this.props.notifications}
rolesAPIClient={this.props.rolesAPIClient}
/>
) : null}
<EuiInMemoryTable
itemId="name"
responsive={false}
columns={this.getColumnConfig()}
hasActions={true}
selection={{
selectable: (role: Role) => !role.metadata || !role.metadata._reserved,
selectableMessage: (selectable: boolean) => (!selectable ? 'Role is reserved' : ''),
onSelectionChange: (selection: Role[]) => this.setState({ selection }),
}}
pagination={{
initialPageSize: 20,
pageSizeOptions: [10, 20, 30, 50, 100],
}}
items={this.state.visibleRoles}
loading={roles.length === 0}
search={{
toolsLeft: this.renderToolsLeft(),
toolsRight: this.renderToolsRight(),
box: {
incremental: true,
'data-test-subj': 'searchRoles',
},
onChange: (query: Record<string, any>) => {
this.setState({
filter: query.queryText,
visibleRoles: this.getVisibleRoles(
this.state.roles,
query.queryText,
this.state.includeReservedRoles
),
});
},
}}
sorting={{
sort: {
field: 'name',
direction: 'asc',
},
}}
rowProps={() => {
return {
'data-test-subj': 'roleRow',
};
}}
isSelectable
/>
</>
);
};

View file

@ -5,14 +5,7 @@
* 2.0.
*/
import {
EuiHorizontalRule,
EuiPageContent,
EuiPageContentBody,
EuiPageContentHeader,
EuiPageContentHeaderSection,
EuiTitle,
} from '@elastic/eui';
import { EuiPageHeader, EuiSpacer } from '@elastic/eui';
import type { FunctionComponent } from 'react';
import React from 'react';
import { useHistory } from 'react-router-dom';
@ -26,23 +19,20 @@ export const CreateUserPage: FunctionComponent = () => {
const backToUsers = () => history.push('/');
return (
<EuiPageContent>
<EuiPageContentHeader>
<EuiPageContentHeaderSection>
<EuiTitle>
<h1>
<FormattedMessage
id="xpack.security.management.users.createUserPage.title"
defaultMessage="Create user"
/>
</h1>
</EuiTitle>
</EuiPageContentHeaderSection>
</EuiPageContentHeader>
<EuiPageContentBody>
<EuiHorizontalRule />
<UserForm isNewUser onCancel={backToUsers} onSuccess={backToUsers} />
</EuiPageContentBody>
</EuiPageContent>
<>
<EuiPageHeader
bottomBorder
pageTitle={
<FormattedMessage
id="xpack.security.management.users.createUserPage.title"
defaultMessage="Create user"
/>
}
/>
<EuiSpacer size="l" />
<UserForm isNewUser onCancel={backToUsers} onSuccess={backToUsers} />
</>
);
};

View file

@ -15,10 +15,7 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiHorizontalRule,
EuiPageContent,
EuiPageContentBody,
EuiPageContentHeader,
EuiPageContentHeaderSection,
EuiPageHeader,
EuiPanel,
EuiSpacer,
EuiText,
@ -82,9 +79,10 @@ export const EditUserPage: FunctionComponent<EditUserPageProps> = ({ username })
const displayName = getUserDisplayName(user);
return (
<EuiPageContent>
<EuiPageContentHeader>
<EuiPageContentHeaderSection>
<>
<EuiPageHeader
bottomBorder
pageTitle={
<EuiFlexGroup alignItems="center" responsive={false}>
<EuiFlexItem grow={false}>
<EuiAvatar name={displayName!} size="xl" />
@ -96,227 +94,227 @@ export const EditUserPage: FunctionComponent<EditUserPageProps> = ({ username })
<EuiText>{user.email}</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageContentHeaderSection>
</EuiPageContentHeader>
<EuiPageContentBody>
<EuiHorizontalRule />
{isDeprecatedUser ? (
<>
<EuiCallOut
title={
}
/>
<EuiSpacer size="l" />
{isDeprecatedUser ? (
<>
<EuiCallOut
title={
<FormattedMessage
id="xpack.security.management.users.editUserPage.deprecatedUserWarning"
defaultMessage="This user is deprecated."
/>
}
iconType="alert"
color="warning"
>
{user.metadata?._deprecated_reason?.replace(/\[(.+)\]/, "'$1'")}
</EuiCallOut>
<EuiSpacer />
</>
) : isReservedUser ? (
<>
<EuiCallOut
title={
<FormattedMessage
id="xpack.security.management.users.editUserPage.reservedUserWarning"
defaultMessage="This user is built in and can't be updated or deleted."
/>
}
iconType="lock"
/>
<EuiSpacer />
</>
) : user.enabled === false ? (
<>
<EuiCallOut
title={
<FormattedMessage
id="xpack.security.management.users.editUserPage.disabledUserWarning"
defaultMessage="This user has been deactivated and can't access Elastic."
/>
}
>
<EuiButton onClick={() => setAction('enableUser')} size="s">
<FormattedMessage
id="xpack.security.management.users.editUserPage.enableUserButton"
defaultMessage="Activate user"
/>
</EuiButton>
</EuiCallOut>
<EuiSpacer />
</>
) : undefined}
<UserForm
isReservedUser={isReservedUser}
defaultValues={user}
onCancel={backToUsers}
onSuccess={backToUsers}
/>
{action === 'changePassword' ? (
<ChangePasswordFlyout
username={username!}
onCancel={() => setAction('none')}
onSuccess={() => setAction('none')}
/>
) : action === 'disableUser' ? (
<ConfirmDisableUsers
usernames={[username!]}
onCancel={() => setAction('none')}
onSuccess={() => {
setAction('none');
getUser();
}}
/>
) : action === 'enableUser' ? (
<ConfirmEnableUsers
usernames={[username!]}
onCancel={() => setAction('none')}
onSuccess={() => {
setAction('none');
getUser();
}}
/>
) : action === 'deleteUser' ? (
<ConfirmDeleteUsers
usernames={[username!]}
onCancel={() => setAction('none')}
onSuccess={backToUsers}
/>
) : undefined}
<EuiSpacer />
<EuiHorizontalRule />
<EuiPanel color="subdued" hasShadow={false} grow={false}>
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexItem>
<EuiDescriptionList>
<EuiDescriptionListTitle>
<FormattedMessage
id="xpack.security.management.users.editUserPage.deprecatedUserWarning"
defaultMessage="This user is deprecated."
id="xpack.security.management.users.editUserPage.changePasswordTitle"
defaultMessage="Change password"
/>
}
iconType="alert"
color="warning"
>
{user.metadata?._deprecated_reason?.replace(/\[(.+)\]/, "'$1'")}
</EuiCallOut>
<EuiSpacer />
</>
) : isReservedUser ? (
<>
<EuiCallOut
title={
</EuiDescriptionListTitle>
<EuiDescriptionListDescription>
<FormattedMessage
id="xpack.security.management.users.editUserPage.reservedUserWarning"
defaultMessage="This user is built in and can't be updated or deleted."
id="xpack.security.management.users.editUserPage.changePasswordDescription"
defaultMessage="The user will not be able to log in using their previous
password."
/>
}
iconType="lock"
/>
<EuiSpacer />
</>
) : user.enabled === false ? (
<>
<EuiCallOut
title={
<FormattedMessage
id="xpack.security.management.users.editUserPage.disabledUserWarning"
defaultMessage="This user has been deactivated and can't access Elastic."
/>
}
>
</EuiDescriptionListDescription>
</EuiDescriptionList>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={() => setAction('changePassword')} size="s">
<FormattedMessage
id="xpack.security.management.users.editUserPage.changePasswordButton"
defaultMessage="Change password"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
<EuiSpacer />
{user.enabled === false ? (
<EuiPanel color="subdued" hasShadow={false} grow={false}>
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexItem>
<EuiDescriptionList>
<EuiDescriptionListTitle>
<FormattedMessage
id="xpack.security.management.users.editUserPage.enableUserTitle"
defaultMessage="Activate user"
/>
</EuiDescriptionListTitle>
<EuiDescriptionListDescription>
<FormattedMessage
id="xpack.security.management.users.editUserPage.enableUserDescription"
defaultMessage="Allow the user to access Elastic."
/>
</EuiDescriptionListDescription>
</EuiDescriptionList>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={() => setAction('enableUser')} size="s">
<FormattedMessage
id="xpack.security.management.users.editUserPage.enableUserButton"
defaultMessage="Activate user"
/>
</EuiButton>
</EuiCallOut>
<EuiSpacer />
</>
) : undefined}
<UserForm
isReservedUser={isReservedUser}
defaultValues={user}
onCancel={backToUsers}
onSuccess={backToUsers}
/>
{action === 'changePassword' ? (
<ChangePasswordFlyout
username={username!}
onCancel={() => setAction('none')}
onSuccess={() => setAction('none')}
/>
) : action === 'disableUser' ? (
<ConfirmDisableUsers
usernames={[username!]}
onCancel={() => setAction('none')}
onSuccess={() => {
setAction('none');
getUser();
}}
/>
) : action === 'enableUser' ? (
<ConfirmEnableUsers
usernames={[username!]}
onCancel={() => setAction('none')}
onSuccess={() => {
setAction('none');
getUser();
}}
/>
) : action === 'deleteUser' ? (
<ConfirmDeleteUsers
usernames={[username!]}
onCancel={() => setAction('none')}
onSuccess={backToUsers}
/>
) : undefined}
<EuiSpacer />
<EuiHorizontalRule />
<EuiPanel color="subdued" hasShadow={false}>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
) : (
<EuiPanel color="subdued" hasShadow={false} grow={false}>
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexItem>
<EuiDescriptionList>
<EuiDescriptionListTitle>
<FormattedMessage
id="xpack.security.management.users.editUserPage.changePasswordTitle"
defaultMessage="Change password"
id="xpack.security.management.users.editUserPage.disableUserTitle"
defaultMessage="Deactivate user"
/>
</EuiDescriptionListTitle>
<EuiDescriptionListDescription>
<FormattedMessage
id="xpack.security.management.users.editUserPage.changePasswordDescription"
defaultMessage="The user will not be able to log in using their previous
password."
id="xpack.security.management.users.editUserPage.disableUserDescription"
defaultMessage="Prevent the user from accessing Elastic."
/>
</EuiDescriptionListDescription>
</EuiDescriptionList>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={() => setAction('changePassword')} size="s">
<EuiButton onClick={() => setAction('disableUser')} size="s">
<FormattedMessage
id="xpack.security.management.users.editUserPage.changePasswordButton"
defaultMessage="Change password"
id="xpack.security.management.users.editUserPage.disableUserButton"
defaultMessage="Deactivate user"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
)}
<EuiSpacer />
{user.enabled === false ? (
<EuiPanel color="subdued" hasShadow={false}>
{!isReservedUser && (
<>
<EuiSpacer />
<EuiPanel color="subdued" hasShadow={false} grow={false}>
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexItem>
<EuiDescriptionList>
<EuiDescriptionListTitle>
<FormattedMessage
id="xpack.security.management.users.editUserPage.enableUserTitle"
defaultMessage="Activate user"
/>
</EuiDescriptionListTitle>
<EuiDescriptionListDescription>
<FormattedMessage
id="xpack.security.management.users.editUserPage.enableUserDescription"
defaultMessage="Allow the user to access Elastic."
/>
</EuiDescriptionListDescription>
</EuiDescriptionList>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={() => setAction('enableUser')} size="s">
<FormattedMessage
id="xpack.security.management.users.editUserPage.enableUserButton"
defaultMessage="Activate user"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
) : (
<EuiPanel color="subdued" hasShadow={false}>
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexItem>
<EuiDescriptionList>
<EuiDescriptionListTitle>
<FormattedMessage
id="xpack.security.management.users.editUserPage.disableUserTitle"
defaultMessage="Deactivate user"
/>
</EuiDescriptionListTitle>
<EuiDescriptionListDescription>
<FormattedMessage
id="xpack.security.management.users.editUserPage.disableUserDescription"
defaultMessage="Prevent the user from accessing Elastic."
/>
</EuiDescriptionListDescription>
</EuiDescriptionList>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={() => setAction('disableUser')} size="s">
<FormattedMessage
id="xpack.security.management.users.editUserPage.disableUserButton"
defaultMessage="Deactivate user"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
)}
{!isReservedUser && (
<>
<EuiSpacer />
<EuiPanel color="subdued" hasShadow={false}>
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexItem>
<EuiDescriptionList>
<EuiDescriptionListTitle>
<FormattedMessage
id="xpack.security.management.users.editUserPage.deleteUserTitle"
defaultMessage="Delete user"
/>
</EuiDescriptionListTitle>
<EuiDescriptionListDescription>
<FormattedMessage
id="xpack.security.management.users.editUserPage.deleteUserDescription"
defaultMessage="Permanently delete the user and remove access to Elastic."
/>
</EuiDescriptionListDescription>
</EuiDescriptionList>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={() => setAction('deleteUser')} size="s" color="danger">
<FormattedMessage
id="xpack.security.management.users.editUserPage.deleteUserButton"
id="xpack.security.management.users.editUserPage.deleteUserTitle"
defaultMessage="Delete user"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
</>
)}
</EuiPageContentBody>
</EuiPageContent>
</EuiDescriptionListTitle>
<EuiDescriptionListDescription>
<FormattedMessage
id="xpack.security.management.users.editUserPage.deleteUserDescription"
defaultMessage="Permanently delete the user and remove access to Elastic."
/>
</EuiDescriptionListDescription>
</EuiDescriptionList>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton onClick={() => setAction('deleteUser')} size="s" color="danger">
<FormattedMessage
id="xpack.security.management.users.editUserPage.deleteUserButton"
defaultMessage="Delete user"
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
</>
)}
</>
);
};

View file

@ -14,11 +14,9 @@ import {
EuiInMemoryTable,
EuiLink,
EuiPageContent,
EuiPageContentBody,
EuiPageContentHeader,
EuiPageContentHeaderSection,
EuiPageHeader,
EuiSpacer,
EuiSwitch,
EuiTitle,
} from '@elastic/eui';
import React, { Component } from 'react';
@ -80,7 +78,7 @@ export class UsersGridPage extends Component<Props, State> {
if (permissionDenied) {
return (
<EuiFlexGroup gutterSize="none">
<EuiPageContent horizontalPosition="center">
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="danger">
<EuiEmptyPrompt
iconType="securityApp"
title={
@ -223,63 +221,61 @@ export class UsersGridPage extends Component<Props, State> {
};
return (
<div className="secUsersListingPage">
<EuiPageContent className="secUsersListingPage__content">
<EuiPageContentHeader>
<EuiPageContentHeaderSection>
<EuiTitle>
<h1>
<FormattedMessage
id="xpack.security.management.users.usersTitle"
defaultMessage="Users"
/>
</h1>
</EuiTitle>
</EuiPageContentHeaderSection>
<EuiPageContentHeaderSection>
<EuiButton
data-test-subj="createUserButton"
{...reactRouterNavigate(this.props.history, `/create`)}
>
<FormattedMessage
id="xpack.security.management.users.createNewUserButtonLabel"
defaultMessage="Create user"
/>
</EuiButton>
</EuiPageContentHeaderSection>
</EuiPageContentHeader>
<EuiPageContentBody>
{showDeleteConfirmation ? (
<ConfirmDeleteUsers
onCancel={this.onCancelDelete}
usersToDelete={selection.map((user) => user.username)}
callback={this.handleDelete}
userAPIClient={this.props.userAPIClient}
notifications={this.props.notifications}
<>
<EuiPageHeader
bottomBorder
pageTitle={
<FormattedMessage
id="xpack.security.management.users.usersTitle"
defaultMessage="Users"
/>
}
rightSideItems={[
<EuiButton
data-test-subj="createUserButton"
{...reactRouterNavigate(this.props.history, `/create`)}
fill
iconType="plusInCircleFilled"
>
<FormattedMessage
id="xpack.security.management.users.createNewUserButtonLabel"
defaultMessage="Create user"
/>
) : null}
</EuiButton>,
]}
/>
{
<EuiInMemoryTable
itemId="username"
tableCaption={i18n.translate('xpack.security.management.users.tableCaption', {
defaultMessage: 'Users',
})}
rowHeader="username"
columns={columns}
selection={selectionConfig}
pagination={pagination}
items={this.state.visibleUsers}
loading={users.length === 0}
search={search}
sorting={sorting}
rowProps={rowProps}
isSelectable
/>
}
</EuiPageContentBody>
</EuiPageContent>
</div>
<EuiSpacer size="l" />
{showDeleteConfirmation ? (
<ConfirmDeleteUsers
onCancel={this.onCancelDelete}
usersToDelete={selection.map((user) => user.username)}
callback={this.handleDelete}
userAPIClient={this.props.userAPIClient}
notifications={this.props.notifications}
/>
) : null}
{
<EuiInMemoryTable
itemId="username"
tableCaption={i18n.translate('xpack.security.management.users.tableCaption', {
defaultMessage: 'Users',
})}
rowHeader="username"
columns={columns}
selection={selectionConfig}
pagination={pagination}
items={this.state.visibleUsers}
loading={users.length === 0}
search={search}
sorting={sorting}
rowProps={rowProps}
isSelectable
/>
}
</>
);
}

View file

@ -20,6 +20,7 @@
"ui": true,
"extraPublicDirs": ["common"],
"requiredBundles": [
"esUiShared",
"kibanaReact",
"savedObjectsManagement",
"home"

View file

@ -10,10 +10,9 @@ import {
EuiButtonEmpty,
EuiFlexGroup,
EuiFlexItem,
EuiLoadingSpinner,
EuiPageContentBody,
EuiPageContent,
EuiPageHeader,
EuiSpacer,
EuiText,
EuiTitle,
} from '@elastic/eui';
import _ from 'lodash';
@ -29,8 +28,10 @@ import type {
} from 'src/core/public';
import type { Space } from 'src/plugins/spaces_oss/common';
import { SectionLoading } from '../../../../../../src/plugins/es_ui_shared/public';
import type { FeaturesPluginStart, KibanaFeature } from '../../../../features/public';
import { isReservedSpace } from '../../../common';
import { getSpacesFeatureDescription } from '../../constants';
import type { SpacesManager } from '../../spaces_manager';
import { UnauthorizedPrompt } from '../components';
import { toSpaceIdentifier } from '../lib';
@ -110,46 +111,48 @@ export class ManageSpacePage extends Component<Props, State> {
}
public render() {
const content = this.state.isLoading ? this.getLoadingIndicator() : this.getForm();
if (!this.props.capabilities.spaces.manage) {
return (
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="danger">
<UnauthorizedPrompt />
</EuiPageContent>
);
}
if (this.state.isLoading) {
return this.getLoadingIndicator();
}
return (
<Fragment>
<EuiPageContentBody>{content}</EuiPageContentBody>
<EuiPageHeader
bottomBorder
pageTitle={this.getTitle()}
description={getSpacesFeatureDescription()}
/>
<EuiSpacer size="l" />
{this.getForm()}
</Fragment>
);
}
public getLoadingIndicator = () => (
<div>
<EuiLoadingSpinner size={'xl'} />{' '}
<EuiTitle>
<h1>Loading...</h1>
</EuiTitle>
</div>
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="subdued">
<SectionLoading>
<FormattedMessage
id="xpack.spaces.management.manageSpacePage.loadingMessage"
defaultMessage="Loading…"
/>
</SectionLoading>
</EuiPageContent>
);
public getForm = () => {
if (!this.props.capabilities.spaces.manage) {
return <UnauthorizedPrompt />;
}
const { showAlteringActiveSpaceDialog } = this.state;
return (
<div data-test-subj="spaces-edit-page">
{this.getFormHeading()}
<EuiSpacer size={'s'} />
<EuiText size="s">
<FormattedMessage
id="xpack.spaces.management.manageSpacePage.manageDescription"
defaultMessage="Organize your saved objects into meaningful categories."
/>
</EuiText>
<EuiSpacer />
<CustomizeSpace
space={this.state.space}
onChange={this.onSpaceChange}

View file

@ -1,7 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`it renders without blowing up 1`] = `
<EuiPanel>
<EuiPanel
hasBorder={true}
hasShadow={false}
>
<EuiFlexGroup
alignItems="baseline"
gutterSize="s"

View file

@ -19,7 +19,7 @@ interface Props {
export class SectionPanel extends Component<Props, {}> {
public render() {
return (
<EuiPanel>
<EuiPanel hasShadow={false} hasBorder={true}>
{this.getTitle()}
{this.getForm()}
</EuiPanel>

View file

@ -5,41 +5,22 @@ exports[`SpacesGridPage renders as expected 1`] = `
className="spcGridPage"
data-test-subj="spaces-grid-page"
>
<EuiPageContent
horizontalPosition="center"
>
<EuiFlexGroup
justifyContent="spaceBetween"
>
<EuiFlexItem
grow={false}
>
<EuiTitle
size="m"
>
<h1>
<FormattedMessage
defaultMessage="Spaces"
id="xpack.spaces.management.spacesGridPage.spacesTitle"
values={Object {}}
/>
</h1>
</EuiTitle>
<EuiText
color="subdued"
size="s"
>
<p>
Organize your dashboards and other saved objects into meaningful categories.
</p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem
grow={false}
>
<EuiPageHeader
bottomBorder={true}
description="Organize your dashboards and other saved objects into meaningful categories."
pageTitle={
<FormattedMessage
defaultMessage="Spaces"
id="xpack.spaces.management.spacesGridPage.spacesTitle"
values={Object {}}
/>
}
rightSideItems={
Array [
<EuiButton
data-test-subj="createSpace"
fill={true}
iconType="plusInCircleFilled"
onClick={[Function]}
>
<FormattedMessage
@ -47,84 +28,84 @@ exports[`SpacesGridPage renders as expected 1`] = `
id="xpack.spaces.management.spacesGridPage.createSpaceButtonLabel"
values={Object {}}
/>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer
size="l"
/>
<EuiInMemoryTable
columns={
Array [
Object {
"field": "initials",
"name": "",
"render": [Function],
"width": "50px",
},
Object {
"field": "name",
"name": "Space",
"render": [Function],
"sortable": true,
},
Object {
"field": "description",
"name": "Description",
"sortable": true,
},
Object {
"field": "disabledFeatures",
"name": "Features",
"render": [Function],
"sortable": [Function],
},
Object {
"field": "id",
"name": "Identifier",
"render": [Function],
"sortable": true,
},
Object {
"actions": Array [
Object {
"render": [Function],
},
Object {
"available": [Function],
"render": [Function],
},
],
"name": "Actions",
},
]
}
hasActions={true}
itemId="id"
items={Array []}
loading={true}
message={
<FormattedMessage
defaultMessage="loading…"
id="xpack.spaces.management.spacesGridPage.loadingTitle"
values={Object {}}
/>
}
pagination={true}
responsive={true}
rowHeader="name"
search={
</EuiButton>,
]
}
/>
<EuiSpacer
size="l"
/>
<EuiInMemoryTable
columns={
Array [
Object {
"box": Object {
"placeholder": "Search",
},
}
"field": "initials",
"name": "",
"render": [Function],
"width": "50px",
},
Object {
"field": "name",
"name": "Space",
"render": [Function],
"sortable": true,
},
Object {
"field": "description",
"name": "Description",
"sortable": true,
},
Object {
"field": "disabledFeatures",
"name": "Features",
"render": [Function],
"sortable": [Function],
},
Object {
"field": "id",
"name": "Identifier",
"render": [Function],
"sortable": true,
},
Object {
"actions": Array [
Object {
"render": [Function],
},
Object {
"available": [Function],
"render": [Function],
},
],
"name": "Actions",
},
]
}
hasActions={true}
itemId="id"
items={Array []}
loading={true}
message={
<FormattedMessage
defaultMessage="loading…"
id="xpack.spaces.management.spacesGridPage.loadingTitle"
values={Object {}}
/>
}
pagination={true}
responsive={true}
rowHeader="name"
search={
Object {
"box": Object {
"placeholder": "Search",
},
}
sorting={true}
tableCaption="Kibana spaces"
tableLayout="fixed"
/>
</EuiPageContent>
}
sorting={true}
tableCaption="Kibana spaces"
tableLayout="fixed"
/>
</div>
`;

View file

@ -8,17 +8,15 @@
import {
EuiButton,
EuiButtonIcon,
EuiFlexGroup,
EuiFlexItem,
EuiInMemoryTable,
EuiLink,
EuiLoadingSpinner,
EuiPageContent,
EuiPageHeader,
EuiSpacer,
EuiText,
EuiTitle,
} from '@elastic/eui';
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';
@ -83,7 +81,19 @@ export class SpacesGridPage extends Component<Props, State> {
public render() {
return (
<div className="spcGridPage" data-test-subj="spaces-grid-page">
<EuiPageContent horizontalPosition="center">{this.getPageContent()}</EuiPageContent>
<EuiPageHeader
bottomBorder
pageTitle={
<FormattedMessage
id="xpack.spaces.management.spacesGridPage.spacesTitle"
defaultMessage="Spaces"
/>
}
description={getSpacesFeatureDescription()}
rightSideItems={[this.getPrimaryActionButton()]}
/>
<EuiSpacer size="l" />
{this.getPageContent()}
{this.getConfirmDeleteModal()}
</div>
);
@ -91,61 +101,45 @@ export class SpacesGridPage extends Component<Props, State> {
public getPageContent() {
if (!this.props.capabilities.spaces.manage) {
return <UnauthorizedPrompt />;
return (
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="danger">
<UnauthorizedPrompt />
</EuiPageContent>
);
}
return (
<Fragment>
<EuiFlexGroup justifyContent={'spaceBetween'}>
<EuiFlexItem grow={false}>
<EuiTitle size="m">
<h1>
<FormattedMessage
id="xpack.spaces.management.spacesGridPage.spacesTitle"
defaultMessage="Spaces"
/>
</h1>
</EuiTitle>
<EuiText color="subdued" size="s">
<p>{getSpacesFeatureDescription()}</p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>{this.getPrimaryActionButton()}</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="l" />
<EuiInMemoryTable
itemId={'id'}
items={this.state.spaces}
tableCaption={i18n.translate('xpack.spaces.management.spacesGridPage.tableCaption', {
defaultMessage: 'Kibana spaces',
})}
rowHeader="name"
columns={this.getColumnConfig()}
hasActions
pagination={true}
sorting={true}
search={{
box: {
placeholder: i18n.translate(
'xpack.spaces.management.spacesGridPage.searchPlaceholder',
{
defaultMessage: 'Search',
}
),
},
}}
loading={this.state.loading}
message={
this.state.loading ? (
<FormattedMessage
id="xpack.spaces.management.spacesGridPage.loadingTitle"
defaultMessage="loading…"
/>
) : undefined
}
/>
</Fragment>
<EuiInMemoryTable
itemId={'id'}
items={this.state.spaces}
tableCaption={i18n.translate('xpack.spaces.management.spacesGridPage.tableCaption', {
defaultMessage: 'Kibana spaces',
})}
rowHeader="name"
columns={this.getColumnConfig()}
hasActions
pagination={true}
sorting={true}
search={{
box: {
placeholder: i18n.translate(
'xpack.spaces.management.spacesGridPage.searchPlaceholder',
{
defaultMessage: 'Search',
}
),
},
}}
loading={this.state.loading}
message={
this.state.loading ? (
<FormattedMessage
id="xpack.spaces.management.spacesGridPage.loadingTitle"
defaultMessage="loading…"
/>
) : undefined
}
/>
);
}
@ -153,6 +147,7 @@ export class SpacesGridPage extends Component<Props, State> {
return (
<EuiButton
fill
iconType="plusInCircleFilled"
{...reactRouterNavigate(this.props.history, '/create')}
data-test-subj="createSpace"
>

View file

@ -83,7 +83,7 @@ describe('spacesManagementApp', () => {
expect(container).toMatchInlineSnapshot(`
<div>
<div
class="kbnRedirectCrossAppLinks"
class="kbnAppWrapper kbnRedirectCrossAppLinks"
>
Spaces Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{"_isScalar":false}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}}}
</div>
@ -109,7 +109,7 @@ describe('spacesManagementApp', () => {
expect(container).toMatchInlineSnapshot(`
<div>
<div
class="kbnRedirectCrossAppLinks"
class="kbnAppWrapper kbnRedirectCrossAppLinks"
>
Spaces Edit Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{"_isScalar":false}},"history":{"action":"PUSH","length":1,"location":{"pathname":"/create","search":"","hash":""}}}
</div>
@ -141,7 +141,7 @@ describe('spacesManagementApp', () => {
expect(container).toMatchInlineSnapshot(`
<div>
<div
class="kbnRedirectCrossAppLinks"
class="kbnAppWrapper kbnRedirectCrossAppLinks"
>
Spaces Edit Page: {"capabilities":{"catalogue":{},"management":{},"navLinks":{}},"notifications":{"toasts":{}},"spacesManager":{"onActiveSpaceChange$":{"_isScalar":false}},"spaceId":"some-space","history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/some-space","search":"","hash":""}}}
</div>

View file

@ -14,6 +14,7 @@ import type { StartServicesAccessor } from 'src/core/public';
import type { RegisterManagementAppArgs } from 'src/plugins/management/public';
import type { Space } from 'src/plugins/spaces_oss/common';
import { APP_WRAPPER_CLASS } from '../../../../../src/core/public';
import {
KibanaContextProvider,
RedirectAppLinks,
@ -125,7 +126,7 @@ export const spacesManagementApp = Object.freeze({
render(
<KibanaContextProvider services={coreStart}>
<i18nStart.Context>
<RedirectAppLinks application={application}>
<RedirectAppLinks application={application} className={APP_WRAPPER_CLASS}>
<Router history={history}>
<Switch>
<Route path={['', '/']} exact>

View file

@ -11,6 +11,7 @@
"references": [
{ "path": "../features/tsconfig.json" },
{ "path": "../licensing/tsconfig.json" },
{ "path": "../../../src/plugins/es_ui_shared/tsconfig.json" },
{ "path": "../../../src/plugins/advanced_settings/tsconfig.json" },
{ "path": "../../../src/plugins/home/tsconfig.json" },
{ "path": "../../../src/plugins/kibana_react/tsconfig.json" },

View file

@ -22017,7 +22017,6 @@
"xpack.spaces.management.manageSpacePage.errorLoadingSpaceTitle": "スペースの読み込み中にエラーが発生:{message}",
"xpack.spaces.management.manageSpacePage.errorSavingSpaceTitle": "スペースの保存中にエラーが発生:{message}",
"xpack.spaces.management.manageSpacePage.loadErrorTitle": "利用可能な機能の読み込みエラー",
"xpack.spaces.management.manageSpacePage.manageDescription": "保存済みオブジェクトをわかりやすいカテゴリー別に整理します。",
"xpack.spaces.management.manageSpacePage.nameFormRowLabel": "名前",
"xpack.spaces.management.manageSpacePage.spaceDescriptionFormRowLabel": "説明 (オプション) ",
"xpack.spaces.management.manageSpacePage.spaceDescriptionHelpText": "説明はスペース選択画面に表示されます。",

View file

@ -22371,7 +22371,6 @@
"xpack.spaces.management.manageSpacePage.errorLoadingSpaceTitle": "加载空间时出错:{message}",
"xpack.spaces.management.manageSpacePage.errorSavingSpaceTitle": "保存空间时出错:{message}",
"xpack.spaces.management.manageSpacePage.loadErrorTitle": "加载可用功能时出错",
"xpack.spaces.management.manageSpacePage.manageDescription": "将已保存对象组织到有意义的类别中。",
"xpack.spaces.management.manageSpacePage.nameFormRowLabel": "名称",
"xpack.spaces.management.manageSpacePage.spaceDescriptionFormRowLabel": "描述 (可选) ",
"xpack.spaces.management.manageSpacePage.spaceDescriptionHelpText": "描述显示在”工作区选择“屏幕上。",