[Enterprise Search] Refactor Role mappings landing pages for both products (#101534) (#101588)

* Add constants and type

* Add RoleMappingsHeading component

I toyed with trying to make a shared component between the Role mappings and Users sections since they both have the same layout, but the need to have all of the conditional copy and button text just seemed too messy, so I opted to share this component between the two products and will make a UsersHeading component in a future PR

* Remove action from table

This is now in the RoleMappingsHeading component from the previous commit

* Remove empty states

Also removed the add mapping button since it is in the heading component

* Remove page headings in favor of table headings

* Remove a bunch of constants and translations

* Update placeholder to match mockup

Co-authored-by: Scotty Bollinger <scotty.bollinger@elastic.co>
This commit is contained in:
Kibana Machine 2021-06-08 11:12:00 -04:00 committed by GitHub
parent d8abad0f47
commit 4f71f1fbad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 158 additions and 179 deletions

View file

@ -9,14 +9,6 @@ import { i18n } from '@kbn/i18n';
import { AdvanceRoleType } from '../../types';
export const EMPTY_ROLE_MAPPINGS_BODY = i18n.translate(
'xpack.enterpriseSearch.appSearch.roleMapping.emptyRoleMappingsBody',
{
defaultMessage:
'All users who successfully authenticate will be assigned the Owner role and have access to all engines. Add a new role to override the default.',
}
);
export const DELETE_ROLE_MAPPING_MESSAGE = i18n.translate(
'xpack.enterpriseSearch.appSearch.deleteRoleMappingMessage',
{

View file

@ -12,10 +12,8 @@ import React from 'react';
import { shallow } from 'enzyme';
import { EuiButton, EuiEmptyPrompt } from '@elastic/eui';
import { Loading } from '../../../shared/loading';
import { RoleMappingsTable } from '../../../shared/role_mapping';
import { RoleMappingsTable, RoleMappingsHeading } from '../../../shared/role_mapping';
import { wsRoleMapping } from '../../../shared/role_mapping/__mocks__/roles';
import { RoleMapping } from './role_mapping';
@ -53,13 +51,6 @@ describe('RoleMappings', () => {
expect(wrapper.find(Loading)).toHaveLength(1);
});
it('renders empty state', () => {
setMockValues({ ...mockValues, roleMappings: [] });
const wrapper = shallow(<RoleMappings />);
expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1);
});
it('renders RoleMapping flyout', () => {
setMockValues({ ...mockValues, roleMappingFlyoutOpen: true });
const wrapper = shallow(<RoleMappings />);
@ -67,10 +58,9 @@ describe('RoleMappings', () => {
expect(wrapper.find(RoleMapping)).toHaveLength(1);
});
it('handles button click', () => {
setMockValues({ ...mockValues, roleMappings: [] });
it('handles onClick', () => {
const wrapper = shallow(<RoleMappings />);
wrapper.find(EuiEmptyPrompt).dive().find(EuiButton).simulate('click');
wrapper.find(RoleMappingsHeading).prop('onClick')();
expect(initializeRoleMapping).toHaveBeenCalled();
});

View file

@ -9,27 +9,13 @@ import React, { useEffect } from 'react';
import { useActions, useValues } from 'kea';
import {
EuiButton,
EuiEmptyPrompt,
EuiPageContent,
EuiPageContentBody,
EuiPageHeader,
EuiPanel,
} from '@elastic/eui';
import { FlashMessages } from '../../../shared/flash_messages';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { Loading } from '../../../shared/loading';
import { RoleMappingsTable } from '../../../shared/role_mapping';
import {
EMPTY_ROLE_MAPPINGS_TITLE,
ROLE_MAPPING_ADD_BUTTON,
ROLE_MAPPINGS_TITLE,
ROLE_MAPPINGS_DESCRIPTION,
} from '../../../shared/role_mapping/constants';
import { RoleMappingsTable, RoleMappingsHeading } from '../../../shared/role_mapping';
import { ROLE_MAPPINGS_TITLE } from '../../../shared/role_mapping/constants';
import { ROLE_MAPPINGS_ENGINE_ACCESS_HEADING, EMPTY_ROLE_MAPPINGS_BODY } from './constants';
import { ROLE_MAPPINGS_ENGINE_ACCESS_HEADING } from './constants';
import { RoleMapping } from './role_mapping';
import { RoleMappingsLogic } from './role_mappings_logic';
@ -54,47 +40,26 @@ export const RoleMappings: React.FC = () => {
if (dataLoading) return <Loading />;
const addMappingButton = (
<EuiButton fill onClick={() => initializeRoleMapping()}>
{ROLE_MAPPING_ADD_BUTTON}
</EuiButton>
);
const roleMappingEmptyState = (
<EuiPanel paddingSize="l" color="subdued" hasBorder={false}>
<EuiEmptyPrompt
iconType="usersRolesApp"
title={<h2>{EMPTY_ROLE_MAPPINGS_TITLE}</h2>}
body={<p>{EMPTY_ROLE_MAPPINGS_BODY}</p>}
actions={addMappingButton}
const roleMappingsSection = (
<>
<RoleMappingsHeading productName="App Search" onClick={() => initializeRoleMapping()} />
<RoleMappingsTable
roleMappings={roleMappings}
accessItemKey="engines"
accessHeader={ROLE_MAPPINGS_ENGINE_ACCESS_HEADING}
initializeRoleMapping={initializeRoleMapping}
shouldShowAuthProvider={multipleAuthProvidersConfig}
handleDeleteMapping={handleDeleteMapping}
/>
</EuiPanel>
);
const roleMappingsTable = (
<RoleMappingsTable
roleMappings={roleMappings}
accessItemKey="engines"
accessHeader={ROLE_MAPPINGS_ENGINE_ACCESS_HEADING}
addMappingButton={addMappingButton}
initializeRoleMapping={initializeRoleMapping}
shouldShowAuthProvider={multipleAuthProvidersConfig}
handleDeleteMapping={handleDeleteMapping}
/>
</>
);
return (
<>
<SetPageChrome trail={[ROLE_MAPPINGS_TITLE]} />
<EuiPageHeader pageTitle={ROLE_MAPPINGS_TITLE} description={ROLE_MAPPINGS_DESCRIPTION} />
{roleMappingFlyoutOpen && <RoleMapping />}
<EuiPageContent hasShadow={false} hasBorder={roleMappings.length > 0}>
<EuiPageContentBody>
<FlashMessages />
{roleMappings.length === 0 ? roleMappingEmptyState : roleMappingsTable}
</EuiPageContentBody>
</EuiPageContent>
<FlashMessages />
{roleMappingsSection}
</>
);
};

View file

@ -7,6 +7,8 @@
import { i18n } from '@kbn/i18n';
import { ProductName } from '../types';
export const ANY_AUTH_PROVIDER = '*';
export const ANY_AUTH_PROVIDER_OPTION_LABEL = i18n.translate(
@ -104,7 +106,7 @@ export const DELETE_ROLE_MAPPING_BUTTON = i18n.translate(
export const FILTER_ROLE_MAPPINGS_PLACEHOLDER = i18n.translate(
'xpack.enterpriseSearch.roleMapping.filterRoleMappingsPlaceholder',
{
defaultMessage: 'Filter roles...',
defaultMessage: 'Filter role mappings',
}
);
@ -125,21 +127,6 @@ export const MANAGE_ROLE_MAPPING_TITLE = i18n.translate(
{ defaultMessage: 'Manage role mapping' }
);
export const EMPTY_ROLE_MAPPINGS_TITLE = i18n.translate(
'xpack.enterpriseSearch.roleMapping.emptyRoleMappingsTitle',
{
defaultMessage: 'No role mappings yet',
}
);
export const ROLE_MAPPINGS_DESCRIPTION = i18n.translate(
'xpack.enterpriseSearch.roleMapping.roleMappingsDescription',
{
defaultMessage:
'Define role mappings for elasticsearch-native and elasticsearch-saml authentication.',
}
);
export const ROLE_MAPPING_NOT_FOUND = i18n.translate(
'xpack.enterpriseSearch.roleMapping.notFoundMessage',
{
@ -168,13 +155,6 @@ export const ROLE_MAPPING_FLYOUT_DESCRIPTION = i18n.translate(
}
);
export const ROLE_MAPPING_ADD_BUTTON = i18n.translate(
'xpack.enterpriseSearch.roleMapping.roleMappingAddButton',
{
defaultMessage: 'Add mapping',
}
);
export const ROLE_MAPPING_FLYOUT_CREATE_BUTTON = i18n.translate(
'xpack.enterpriseSearch.roleMapping.roleMappingFlyoutCreateButton',
{
@ -198,3 +178,25 @@ export const UPDATE_ROLE_MAPPING = i18n.translate(
'xpack.enterpriseSearch.roleMapping.updateRoleMappingButtonLabel',
{ defaultMessage: 'Update role mapping' }
);
export const ROLE_MAPPINGS_HEADING_TITLE = i18n.translate(
'xpack.enterpriseSearch.roleMapping.roleMappingsHeadingTitle',
{ defaultMessage: 'Role mappings' }
);
export const ROLE_MAPPINGS_HEADING_DESCRIPTION = (productName: ProductName) =>
i18n.translate('xpack.enterpriseSearch.roleMapping.roleMappingsHeadingDescription', {
defaultMessage:
'Role mappings provide an interface to associate native or SAML-governed role attributes with {productName} permissions.',
values: { productName },
});
export const ROLE_MAPPINGS_HEADING_DOCS_LINK = i18n.translate(
'xpack.enterpriseSearch.roleMapping.roleMappingsHeadingDocsLink',
{ defaultMessage: 'Learn more about role mappings' }
);
export const ROLE_MAPPINGS_HEADING_BUTTON = i18n.translate(
'xpack.enterpriseSearch.roleMapping.roleMappingsHeadingButton',
{ defaultMessage: 'Create a new role mapping' }
);

View file

@ -10,3 +10,4 @@ export { RoleMappingsTable } from './role_mappings_table';
export { RoleOptionLabel } from './role_option_label';
export { RoleSelector } from './role_selector';
export { RoleMappingFlyout } from './role_mapping_flyout';
export { RoleMappingsHeading } from './role_mappings_heading';

View file

@ -0,0 +1,25 @@
/*
* 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 { shallow } from 'enzyme';
import { EuiTitle, EuiLink, EuiButton, EuiText } from '@elastic/eui';
import { RoleMappingsHeading } from './role_mappings_heading';
describe('RoleMappingsHeading', () => {
it('renders ', () => {
const wrapper = shallow(<RoleMappingsHeading productName="App Search" onClick={jest.fn()} />);
expect(wrapper.find(EuiTitle)).toHaveLength(1);
expect(wrapper.find(EuiText)).toHaveLength(1);
expect(wrapper.find(EuiLink)).toHaveLength(1);
expect(wrapper.find(EuiButton)).toHaveLength(1);
});
});

View file

@ -0,0 +1,62 @@
/*
* 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 {
EuiButton,
EuiFlexGroup,
EuiFlexItem,
EuiLink,
EuiSpacer,
EuiText,
EuiTitle,
} from '@elastic/eui';
import { ProductName } from '../types';
import {
ROLE_MAPPINGS_HEADING_TITLE,
ROLE_MAPPINGS_HEADING_DESCRIPTION,
ROLE_MAPPINGS_HEADING_DOCS_LINK,
ROLE_MAPPINGS_HEADING_BUTTON,
} from './constants';
interface Props {
productName: ProductName;
onClick(): void;
}
// TODO: Replace EuiLink href with acutal docs link when available
const ROLE_MAPPINGS_DOCS_HREF = '#TODO';
export const RoleMappingsHeading: React.FC<Props> = ({ productName, onClick }) => (
<>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem>
<EuiTitle>
<h2>{ROLE_MAPPINGS_HEADING_TITLE}</h2>
</EuiTitle>
<EuiSpacer size="xs" />
<EuiText color="subdued">
<p>
{ROLE_MAPPINGS_HEADING_DESCRIPTION(productName)}{' '}
<EuiLink external href={ROLE_MAPPINGS_DOCS_HREF} target="_blank">
{ROLE_MAPPINGS_HEADING_DOCS_LINK}
</EuiLink>
</p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton fill onClick={onClick}>
{ROLE_MAPPINGS_HEADING_BUTTON}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer />
</>
);

View file

@ -10,8 +10,6 @@ import React, { Fragment, useState } from 'react';
import {
EuiButtonIcon,
EuiFieldSearch,
EuiFlexGroup,
EuiFlexItem,
EuiIconTip,
EuiSpacer,
EuiTable,
@ -54,7 +52,6 @@ interface Props {
accessItemKey: 'groups' | 'engines';
accessHeader: string;
roleMappings: Array<ASRoleMapping | WSRoleMapping>;
addMappingButton: React.ReactNode;
accessAllEngines?: boolean;
shouldShowAuthProvider?: boolean;
initializeRoleMapping(roleMappingId: string): void;
@ -72,7 +69,6 @@ export const RoleMappingsTable: React.FC<Props> = ({
accessItemKey,
accessHeader,
roleMappings,
addMappingButton,
shouldShowAuthProvider,
initializeRoleMapping,
handleDeleteMapping,
@ -117,16 +113,11 @@ export const RoleMappingsTable: React.FC<Props> = ({
return (
<>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem>
<EuiFieldSearch
value={filterValue}
placeholder={FILTER_ROLE_MAPPINGS_PLACEHOLDER}
onChange={(e) => updateValue(e.target.value)}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>{addMappingButton}</EuiFlexItem>
</EuiFlexGroup>
<EuiFieldSearch
value={filterValue}
placeholder={FILTER_ROLE_MAPPINGS_PLACEHOLDER}
onChange={(e) => updateValue(e.target.value)}
/>
<EuiSpacer />
{filteredResults.length > 0 ? (
<EuiTable className="roleMappingsTable">

View file

@ -35,3 +35,5 @@ export interface RoleMapping {
content: string;
};
}
export type ProductName = 'App Search' | 'Workplace Search';

View file

@ -73,14 +73,6 @@ export const GROUP_ASSIGNMENT_LABEL = i18n.translate(
}
);
export const EMPTY_ROLE_MAPPINGS_BODY = i18n.translate(
'xpack.enterpriseSearch.workplaceSearch.roleMapping.emptyRoleMappingsBody',
{
defaultMessage:
'New team members are assigned the admin role by default. An admin can access everything. Create a new role to override the default.',
}
);
export const ROLE_MAPPINGS_TABLE_HEADER = i18n.translate(
'xpack.enterpriseSearch.workplaceSearch.roleMapping.roleMappingsTableHeader',
{

View file

@ -12,10 +12,8 @@ import React from 'react';
import { shallow } from 'enzyme';
import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';
import { Loading } from '../../../shared/loading';
import { RoleMappingsTable } from '../../../shared/role_mapping';
import { RoleMappingsTable, RoleMappingsHeading } from '../../../shared/role_mapping';
import { wsRoleMapping } from '../../../shared/role_mapping/__mocks__/roles';
import { RoleMapping } from './role_mapping';
@ -53,13 +51,6 @@ describe('RoleMappings', () => {
expect(wrapper.find(Loading)).toHaveLength(1);
});
it('renders empty state', () => {
setMockValues({ ...mockValues, roleMappings: [] });
const wrapper = shallow(<RoleMappings />);
expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1);
});
it('renders RoleMapping flyout', () => {
setMockValues({ ...mockValues, roleMappingFlyoutOpen: true });
const wrapper = shallow(<RoleMappings />);
@ -67,10 +58,9 @@ describe('RoleMappings', () => {
expect(wrapper.find(RoleMapping)).toHaveLength(1);
});
it('handles button click', () => {
setMockValues({ ...mockValues, roleMappings: [] });
it('handles onClick', () => {
const wrapper = shallow(<RoleMappings />);
wrapper.find(EuiEmptyPrompt).dive().find(EuiButton).simulate('click');
wrapper.find(RoleMappingsHeading).prop('onClick')();
expect(initializeRoleMapping).toHaveBeenCalled();
});

View file

@ -9,21 +9,13 @@ import React, { useEffect } from 'react';
import { useActions, useValues } from 'kea';
import { EuiButton, EuiEmptyPrompt, EuiPanel } from '@elastic/eui';
import { FlashMessages } from '../../../shared/flash_messages';
import { SetWorkplaceSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { Loading } from '../../../shared/loading';
import { RoleMappingsTable } from '../../../shared/role_mapping';
import {
EMPTY_ROLE_MAPPINGS_TITLE,
ROLE_MAPPING_ADD_BUTTON,
ROLE_MAPPINGS_TITLE,
ROLE_MAPPINGS_DESCRIPTION,
} from '../../../shared/role_mapping/constants';
import { ViewContentHeader } from '../../components/shared/view_content_header';
import { RoleMappingsTable, RoleMappingsHeading } from '../../../shared/role_mapping';
import { ROLE_MAPPINGS_TITLE } from '../../../shared/role_mapping/constants';
import { EMPTY_ROLE_MAPPINGS_BODY, ROLE_MAPPINGS_TABLE_HEADER } from './constants';
import { ROLE_MAPPINGS_TABLE_HEADER } from './constants';
import { RoleMapping } from './role_mapping';
import { RoleMappingsLogic } from './role_mappings_logic';
@ -46,43 +38,26 @@ export const RoleMappings: React.FC = () => {
if (dataLoading) return <Loading />;
const addMappingButton = (
<EuiButton fill onClick={() => initializeRoleMapping()}>
{ROLE_MAPPING_ADD_BUTTON}
</EuiButton>
);
const emptyPrompt = (
<EuiPanel paddingSize="l" color="subdued" hasBorder={false}>
<EuiEmptyPrompt
iconType="usersRolesApp"
title={<h2>{EMPTY_ROLE_MAPPINGS_TITLE}</h2>}
body={<p>{EMPTY_ROLE_MAPPINGS_BODY}</p>}
actions={addMappingButton}
const roleMappingsSection = (
<>
<RoleMappingsHeading productName="Workplace Search" onClick={() => initializeRoleMapping()} />
<RoleMappingsTable
roleMappings={roleMappings}
accessItemKey="groups"
accessHeader={ROLE_MAPPINGS_TABLE_HEADER}
shouldShowAuthProvider={multipleAuthProvidersConfig}
initializeRoleMapping={initializeRoleMapping}
handleDeleteMapping={handleDeleteMapping}
/>
</EuiPanel>
);
const roleMappingsTable = (
<RoleMappingsTable
roleMappings={roleMappings}
accessItemKey="groups"
accessHeader={ROLE_MAPPINGS_TABLE_HEADER}
addMappingButton={addMappingButton}
shouldShowAuthProvider={multipleAuthProvidersConfig}
initializeRoleMapping={initializeRoleMapping}
handleDeleteMapping={handleDeleteMapping}
/>
</>
);
return (
<>
<SetPageChrome trail={[ROLE_MAPPINGS_TITLE]} />
<ViewContentHeader title={ROLE_MAPPINGS_TITLE} description={ROLE_MAPPINGS_DESCRIPTION} />
{roleMappingFlyoutOpen && <RoleMapping />}
<div>
<FlashMessages />
{roleMappings.length === 0 ? emptyPrompt : roleMappingsTable}
</div>
<FlashMessages />
{roleMappingsSection}
</>
);
};

View file

@ -7908,7 +7908,6 @@
"xpack.enterpriseSearch.appSearch.result.documentDetailLink": "ドキュメントの詳細を表示",
"xpack.enterpriseSearch.appSearch.result.hideAdditionalFields": "追加フィールドを非表示",
"xpack.enterpriseSearch.appSearch.result.title": "ドキュメント{id}",
"xpack.enterpriseSearch.appSearch.roleMapping.emptyRoleMappingsBody": "認証が成功したすべてのユーザーには所有者ロールが割り当てられ、すべてのエンジンにアクセスできます。デフォルト設定を無効にするには、新しいロールを追加します。",
"xpack.enterpriseSearch.appSearch.roleMappingCreatedMessage": "ロールマッピングが正常に作成されました。",
"xpack.enterpriseSearch.appSearch.roleMappingDeletedMessage": "ロールマッピングが正常に削除されました",
"xpack.enterpriseSearch.appSearch.roleMappingsEngineAccessHeading": "エンジンアクセス",
@ -7998,7 +7997,6 @@
"xpack.enterpriseSearch.roleMapping.deleteRoleMappingButton": "マッピングを削除",
"xpack.enterpriseSearch.roleMapping.deleteRoleMappingDescription": "マッピングの削除は永久的であり、元に戻すことはできません",
"xpack.enterpriseSearch.roleMapping.deleteRoleMappingTitle": "このロールマッピングを削除",
"xpack.enterpriseSearch.roleMapping.emptyRoleMappingsTitle": "ロールマッピングがありません",
"xpack.enterpriseSearch.roleMapping.externalAttributeLabel": "外部属性",
"xpack.enterpriseSearch.roleMapping.filterRoleMappingsPlaceholder": "ロールをフィルタリング...",
"xpack.enterpriseSearch.roleMapping.individualAuthProviderLabel": "個別の認証プロバイダーを選択",
@ -8006,7 +8004,6 @@
"xpack.enterpriseSearch.roleMapping.moResults.message": "'{filterValue}'の結果が見つかりません。",
"xpack.enterpriseSearch.roleMapping.newRoleMappingTitle": "ロールマッピングを追加",
"xpack.enterpriseSearch.roleMapping.roleLabel": "ロール",
"xpack.enterpriseSearch.roleMapping.roleMappingsDescription": "elasticsearch-nativeおよびelasticsearch-saml認証のロールマッピングを定義します。",
"xpack.enterpriseSearch.roleMapping.roleMappingsTitle": "ユーザーとロール",
"xpack.enterpriseSearch.roleMapping.saveRoleMappingButtonLabel": "ロールマッピングの保存",
"xpack.enterpriseSearch.roleMapping.updateRoleMappingButtonLabel": "ロールマッピングを更新",
@ -8314,7 +8311,6 @@
"xpack.enterpriseSearch.workplaceSearch.roleMapping.adminRoleTypeDescription": "管理者は、コンテンツソース、グループ、ユーザー管理機能など、すべての組織レベルの設定に無制限にアクセスできます。",
"xpack.enterpriseSearch.workplaceSearch.roleMapping.defaultGroupName": "デフォルト",
"xpack.enterpriseSearch.workplaceSearch.roleMapping.deleteRoleMappingButtonMessage": "このマッピングを完全に削除しますか?このアクションは元に戻せません。一部のユーザーがアクセスを失う可能性があります。",
"xpack.enterpriseSearch.workplaceSearch.roleMapping.emptyRoleMappingsBody": "新しいチームメンバーにはデフォルトで管理者ロールが割り当てられます。管理者はすべてにアクセスできます。デフォルト設定を無効にするには、新しいロールを作成します。",
"xpack.enterpriseSearch.workplaceSearch.roleMapping.groupAssignmentInvalidError": "1つ以上の割り当てられたグループが必要です。",
"xpack.enterpriseSearch.workplaceSearch.roleMapping.roleMappingsTableHeader": "グループアクセス",
"xpack.enterpriseSearch.workplaceSearch.roleMapping.userRoleTypeDescription": "ユーザーの機能アクセスは検索インターフェースと個人設定管理に制限されます。",

View file

@ -7976,7 +7976,6 @@
"xpack.enterpriseSearch.appSearch.result.hideAdditionalFields": "隐藏其他字段",
"xpack.enterpriseSearch.appSearch.result.showAdditionalFields": "显示其他 {numberOfAdditionalFields, number} 个{numberOfAdditionalFields, plural, other {字段}}",
"xpack.enterpriseSearch.appSearch.result.title": "文档 {id}",
"xpack.enterpriseSearch.appSearch.roleMapping.emptyRoleMappingsBody": "成功验证的所有用户将被分配所有者角色,可访问所有引擎。添加新角色以覆盖默认值。",
"xpack.enterpriseSearch.appSearch.roleMappingCreatedMessage": "角色映射已成功创建。",
"xpack.enterpriseSearch.appSearch.roleMappingDeletedMessage": "已成功删除角色映射",
"xpack.enterpriseSearch.appSearch.roleMappingsEngineAccessHeading": "引擎访问",
@ -8066,7 +8065,6 @@
"xpack.enterpriseSearch.roleMapping.deleteRoleMappingButton": "删除映射",
"xpack.enterpriseSearch.roleMapping.deleteRoleMappingDescription": "请注意,删除映射是永久性的,无法撤消",
"xpack.enterpriseSearch.roleMapping.deleteRoleMappingTitle": "移除此角色映射",
"xpack.enterpriseSearch.roleMapping.emptyRoleMappingsTitle": "尚未有角色映射",
"xpack.enterpriseSearch.roleMapping.externalAttributeLabel": "外部属性",
"xpack.enterpriseSearch.roleMapping.filterRoleMappingsPlaceholder": "筛选角色......",
"xpack.enterpriseSearch.roleMapping.individualAuthProviderLabel": "选择单个身份验证提供程序",
@ -8074,7 +8072,6 @@
"xpack.enterpriseSearch.roleMapping.moResults.message": "找不到“{filterValue}”的结果",
"xpack.enterpriseSearch.roleMapping.newRoleMappingTitle": "添加角色映射",
"xpack.enterpriseSearch.roleMapping.roleLabel": "角色",
"xpack.enterpriseSearch.roleMapping.roleMappingsDescription": "为 elasticsearch-native 和 elasticsearch-saml 身份验证定义角色映射。",
"xpack.enterpriseSearch.roleMapping.roleMappingsTitle": "用户和角色",
"xpack.enterpriseSearch.roleMapping.saveRoleMappingButtonLabel": "保存角色映射",
"xpack.enterpriseSearch.roleMapping.updateRoleMappingButtonLabel": "更新角色映射",
@ -8382,7 +8379,6 @@
"xpack.enterpriseSearch.workplaceSearch.roleMapping.adminRoleTypeDescription": "管理员对所有组织范围设置 (包括内容源、组和用户管理功能) 具有完全权限。",
"xpack.enterpriseSearch.workplaceSearch.roleMapping.defaultGroupName": "默认",
"xpack.enterpriseSearch.workplaceSearch.roleMapping.deleteRoleMappingButtonMessage": "确定要永久删除此映射?此操作不可逆转,且某些用户可能会失去访问权限。",
"xpack.enterpriseSearch.workplaceSearch.roleMapping.emptyRoleMappingsBody": "默认情况下,会为新团队成员分配管理员角色。管理员可以访问任何内容。超级新角色以覆盖默认值。",
"xpack.enterpriseSearch.workplaceSearch.roleMapping.groupAssignmentInvalidError": "至少需要一个分配的组。",
"xpack.enterpriseSearch.workplaceSearch.roleMapping.roleMappingsTableHeader": "组访问权限",
"xpack.enterpriseSearch.workplaceSearch.roleMapping.userRoleTypeDescription": "用户的功能访问权限仅限于搜索界面和个人设置管理。",