[Graph] Listing page and folder restructuring (#44068)

This commit is contained in:
Joe Reuter 2019-08-29 17:19:56 +02:00 committed by GitHub
parent 0be4cf9e9a
commit 6fad639f25
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 375 additions and 258 deletions

View file

@ -17,5 +17,6 @@ export interface ChromeBreadcrumb
| --- | --- | --- |
| [data-test-subj](./kibana-plugin-public.chromebreadcrumb.data-test-subj.md) | <code>string</code> | |
| [href](./kibana-plugin-public.chromebreadcrumb.href.md) | <code>string</code> | |
| [onClick](./kibana-plugin-public.chromebreadcrumb.onclick.md) | <code>MouseEventHandler&lt;HTMLButtonElement&gt;</code> | |
| [text](./kibana-plugin-public.chromebreadcrumb.text.md) | <code>string</code> | |

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-public](./kibana-plugin-public.md) &gt; [ChromeBreadcrumb](./kibana-plugin-public.chromebreadcrumb.md) &gt; [onClick](./kibana-plugin-public.chromebreadcrumb.onclick.md)
## ChromeBreadcrumb.onClick property
<b>Signature:</b>
```typescript
onClick?: MouseEventHandler<HTMLButtonElement>;
```

View file

@ -17,7 +17,7 @@
* under the License.
*/
import React from 'react';
import React, { MouseEventHandler } from 'react';
import { BehaviorSubject, Observable, ReplaySubject } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import * as Url from 'url';
@ -63,6 +63,7 @@ export interface ChromeBreadcrumb {
text: string;
href?: string;
'data-test-subj'?: string;
onClick?: MouseEventHandler<HTMLButtonElement>;
}
/** @public */

View file

@ -5,6 +5,7 @@
```ts
import { IconType } from '@elastic/eui';
import { MouseEventHandler } from 'react';
import { Observable } from 'rxjs';
import React from 'react';
import * as Rx from 'rxjs';
@ -63,6 +64,8 @@ export interface ChromeBreadcrumb {
// (undocumented)
href?: string;
// (undocumented)
onClick?: MouseEventHandler<HTMLButtonElement>;
// (undocumented)
text: string;
}

View file

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
const gws = require('../graphClientWorkspace.js');
const gws = require('../graph_client_workspace.js');
const expect = require('@kbn/expect');
describe('graphui-workspace', function () {

View file

@ -3,8 +3,7 @@
<kbn-top-nav name="workspacesTopNav" config="topNavMenu">
</kbn-top-nav>
<div class="gphGraph__menus" ng-show="menus.showLoad || menus.showSave || menus.showSettings">
<graph-load ng-show="menus.showLoad"></graph-load>
<div class="gphGraph__menus" ng-show="menus.showSave || menus.showSettings">
<graph-save ng-show="menus.showSave"></graph-save>
<graph-settings ng-show="menus.showSettings"></graph-settings>
</div>

View file

@ -0,0 +1,10 @@
<graph-listing
create-item="create"
get-view-url="getViewUrl"
edit-item="editItem"
find-items="find"
delete-items="delete"
listing-limit="listingLimit"
capabilities="capabilities"
initial-filter="initialFilter"
/>

View file

@ -30,18 +30,22 @@ import { IndexPatternsProvider } from 'ui/index_patterns';
import { SavedObjectsClientProvider } from 'ui/saved_objects';
import { KibanaParsedUrl } from 'ui/url/kibana_parsed_url';
import { npStart } from 'ui/new_platform';
import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry';
import { capabilities } from 'ui/capabilities';
import { xpackInfo } from 'plugins/xpack_main/services/xpack_info';
import appTemplate from './templates/index.html';
import { getHomeBreadcrumbs, getWorkspaceBreadcrumbs } from './breadcrumbs';
import appTemplate from './angular/templates/index.html';
import listingTemplate from './angular/templates/listing_ng_wrapper.html';
import { getReadonlyBadge } from './badge';
import { FormattedMessage } from '@kbn/i18n/react';
import './angular-venn-simple.js';
import gws from './graphClientWorkspace.js';
import { GraphListing } from './components/graph_listing';
import './angular/angular_venn_simple.js';
import gws from './angular/graph_client_workspace.js';
import utils from './utils.js';
import { SavedWorkspacesProvider } from './services/saved_workspaces';
import { SavedWorkspacesProvider } from './angular/services/saved_workspaces';
import {
iconChoices,
colorChoices,
@ -51,16 +55,14 @@ import {
} from './style_choices';
import {
getOutlinkEncoders,
} from './services/outlink_encoders';
import { capabilities } from 'ui/capabilities';
} from './angular/services/outlink_encoders';
import { getEditUrl, getNewPath, getEditPath, setBreadcrumbs } from './services/url';
import saveTemplate from './templates/save_workspace.html';
import loadTemplate from './templates/load_workspace.html';
import settingsTemplate from './templates/settings.html';
import saveTemplate from './angular/templates/save_workspace.html';
import settingsTemplate from './angular/templates/settings.html';
import './directives/graph_load';
import './directives/graph_save';
import './directives/graph_settings';
import './angular/directives/graph_save';
import './angular/directives/graph_settings';
const app = uiModules.get('app/graph');
@ -85,42 +87,49 @@ app.directive('focusOn', function () {
};
});
app.directive('graphListing', function (reactDirective) {
return reactDirective(GraphListing);
});
if (uiRoutes.enable) {
uiRoutes.enable();
}
uiRoutes
.when('/home', {
template: appTemplate,
k7Breadcrumbs: getHomeBreadcrumbs,
template: listingTemplate,
badge: getReadonlyBadge,
resolve: {
//Copied from example found in wizard.js ( Kibana TODO - can't
// IndexPatternsProvider abstract these implementation details better?)
indexPatterns: function (Private) {
const savedObjectsClient = Private(SavedObjectsClientProvider);
controller($injector, $location, $scope, Private, config, Promise, kbnBaseUrl) {
checkLicense(Promise, kbnBaseUrl);
const services = Private(SavedObjectRegistryProvider).byLoaderPropertiesName;
const graphService = services['Graph workspace'];
const kbnUrl = $injector.get('kbnUrl');
return savedObjectsClient.find({
type: 'index-pattern',
fields: ['title', 'type'],
perPage: 10000
}).then(response => response.savedObjects);
},
GetIndexPatternProvider: function (Private) {
return Private(IndexPatternsProvider);
},
SavedWorkspacesProvider: function (Private) {
return Private(SavedWorkspacesProvider);
},
CheckLicense: checkLicense
$scope.listingLimit = config.get('savedObjects:listingLimit');
$scope.create = () => {
kbnUrl.redirect(getNewPath());
};
$scope.find = (search) => {
return graphService.find(search, $scope.listingLimit);
};
$scope.editItem = (workspace) => {
kbnUrl.redirect(getEditPath(workspace));
};
$scope.getViewUrl = (workspace) => getEditUrl(chrome, workspace);
$scope.delete = (workspaces) => {
return graphService.delete(workspaces.map(({ id }) => id));
};
$scope.capabilities = capabilities.get().graph;
$scope.initialFilter = ($location.search()).filter || '';
setBreadcrumbs({ chrome });
}
})
.when('/workspace/:id', {
.when('/workspace/:id?', {
template: appTemplate,
k7Breadcrumbs: getWorkspaceBreadcrumbs,
badge: getReadonlyBadge,
resolve: {
savedWorkspace: function (savedGraphWorkspaces, courier, $route) {
return savedGraphWorkspaces.get($route.current.params.id)
return $route.current.params.id && savedGraphWorkspaces.get($route.current.params.id)
.catch(
function () {
toastNotifications.addDanger(
@ -148,8 +157,7 @@ uiRoutes
},
SavedWorkspacesProvider: function (Private) {
return Private(SavedWorkspacesProvider);
},
CheckLicense: checkLicense
}
}
})
.otherwise({
@ -248,11 +256,6 @@ app.controller('graphuiPlugin', function (
urlTemplate.icon === icon ? urlTemplate.icon = null : urlTemplate.icon = icon;
};
$scope.openSavedWorkspace = function (savedWorkspace) {
kbnUrl.change('/workspace/{{id}}', { id: savedWorkspace.id });
};
$scope.nodeClick = function (n, $event) {
//Selection logic - shift key+click helps selects multiple nodes
@ -344,13 +347,16 @@ app.controller('graphuiPlugin', function (
}
const confirmModalOptions = {
onConfirm: yesFn,
onCancel: noFn,
onCancel: noFn || (() => {}),
confirmButtonText: i18n.translate('xpack.graph.clearWorkspace.confirmButtonLabel', {
defaultMessage: 'Clear workspace',
})
defaultMessage: 'Continue',
}),
title: i18n.translate('xpack.graph.clearWorkspace.modalTitle', {
defaultMessage: 'Discard changes to workspace?',
}),
};
confirmModal(i18n.translate('xpack.graph.clearWorkspace.confirmText', {
defaultMessage: 'This will clear the workspace - are you sure?',
defaultMessage: 'Once you discard changes made to a workspace, there is no getting them back.',
}), confirmModalOptions);
}
@ -841,7 +847,7 @@ app.controller('graphuiPlugin', function (
}),
run: function () {
canWipeWorkspace(function () {
kbnUrl.change('/home', {});
kbnUrl.change('/workspace/', {});
}); },
});
@ -882,92 +888,6 @@ app.controller('graphuiPlugin', function (
testId: 'graphSaveButton',
});
}
$scope.topNavMenu.push({
key: 'open',
label: i18n.translate('xpack.graph.topNavMenu.loadWorkspaceLabel', {
defaultMessage: 'Open',
}),
description: i18n.translate('xpack.graph.topNavMenu.loadWorkspaceAriaLabel', {
defaultMessage: 'Load Saved Workspace',
}),
tooltip: i18n.translate('xpack.graph.topNavMenu.loadWorkspaceTooltip', {
defaultMessage: 'Load a saved workspace',
}),
run: () => {
$scope.$evalAsync(() => {
const curState = $scope.menus.showLoad;
$scope.closeMenus();
$scope.menus.showLoad = !curState;
});
},
testId: 'graphOpenButton',
});
// if deleting is disabled using uiCapabilities, we don't want to render the delete
// button so it's consistent with all of the other applications
if (capabilities.get().graph.delete) {
// allSavingDisabled is based on the xpack.graph.savePolicy, we'll maintain this functionality
if (!$scope.allSavingDisabled) {
$scope.topNavMenu.push({
key: 'delete',
disableButton: function () {
return $route.current.locals === undefined || $route.current.locals.savedWorkspace === undefined;
},
label: i18n.translate('xpack.graph.topNavMenu.deleteWorkspace.enabledLabel', {
defaultMessage: 'Delete',
}),
description: i18n.translate('xpack.graph.topNavMenu.deleteWorkspace.enabledAriaLabel', {
defaultMessage: 'Delete Saved Workspace',
}),
tooltip: i18n.translate('xpack.graph.topNavMenu.deleteWorkspace.enabledAriaTooltip', {
defaultMessage: 'Delete this workspace',
}),
testId: 'graphDeleteButton',
run: function () {
const title = $route.current.locals.savedWorkspace.title;
function doDelete() {
$route.current.locals.SavedWorkspacesProvider.delete($route.current.locals.savedWorkspace.id);
kbnUrl.change('/home', {});
toastNotifications.addSuccess(
i18n.translate('xpack.graph.topNavMenu.deleteWorkspaceNotification', {
defaultMessage: `Deleted '{workspaceTitle}'`,
values: { workspaceTitle: title },
})
);
}
const confirmModalOptions = {
onConfirm: doDelete,
confirmButtonText: i18n.translate('xpack.graph.topNavMenu.deleteWorkspace.confirmButtonLabel', {
defaultMessage: 'Delete workspace',
}),
};
confirmModal(
i18n.translate('xpack.graph.topNavMenu.deleteWorkspace.confirmText', {
defaultMessage: 'Are you sure you want to delete the workspace {title} ?',
values: { title },
}),
confirmModalOptions
);
}
});
} else {
$scope.topNavMenu.push({
key: 'delete',
disableButton: true,
label: i18n.translate('xpack.graph.topNavMenu.deleteWorkspace.disabledLabel', {
defaultMessage: 'Delete',
}),
description: i18n.translate('xpack.graph.topNavMenu.deleteWorkspace.disabledAriaLabel', {
defaultMessage: 'Delete Saved Workspace',
}),
tooltip: i18n.translate('xpack.graph.topNavMenu.deleteWorkspace.disabledTooltip', {
defaultMessage: 'No changes to saved workspaces are permitted by the current save policy',
}),
testId: 'graphDeleteButton',
});
}
}
$scope.topNavMenu.push({
key: 'settings',
disableButton: function () { return $scope.selectedIndex === null; },
@ -986,9 +906,21 @@ app.controller('graphuiPlugin', function (
},
});
setBreadcrumbs({
chrome,
savedWorkspace: $route.current.locals.savedWorkspace,
navigateTo: () => {
// TODO this should be wrapped into canWipeWorkspace,
// but the check is too simple right now. Change this
// once actual state-diffing is in place.
$scope.$evalAsync(() => {
kbnUrl.changePath('/home/');
});
}
});
$scope.menus = {
showSave: false,
showLoad: false,
showSettings: false,
};
@ -1261,7 +1193,7 @@ app.controller('graphuiPlugin', function (
'data-test-subj': 'saveGraphSuccess',
});
if ($scope.savedWorkspace.id === $route.current.params.id) return;
$scope.openSavedWorkspace($scope.savedWorkspace);
kbnUrl.change(getEditPath($scope.savedWorkspace));
}
}, fatalError);

View file

@ -1,8 +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;
* you may not use this file except in compliance with the Elastic License.
*/
require('ui/autoload/all');
require('./app');

View file

@ -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;
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
export function getHomeBreadcrumbs() {
return [
{
text: i18n.translate('xpack.graph.home.breadcrumb', {
defaultMessage: 'Graph'
}),
href: '#/home'
}
];
}
export function getWorkspaceBreadcrumbs($route) {
const { savedWorkspace } = $route.current.locals;
return [
...getHomeBreadcrumbs(),
{
text: savedWorkspace.title
}
];
}

View file

@ -0,0 +1,164 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
import React, { Fragment } from 'react';
import { EuiEmptyPrompt, EuiLink, EuiButton } from '@elastic/eui';
// @ts-ignore
import { TableListView } from '../../../../../../src/legacy/core_plugins/kibana/public/table_list_view/table_list_view';
import { SavedGraphWorkspace } from '../types/persistence';
export interface GraphListingProps {
createItem: () => void;
findItems: (query: string, limit: number) => Promise<SavedGraphWorkspace[]>;
deleteItems: (ids: string[]) => Promise<void>;
editItem: (record: SavedGraphWorkspace) => void;
getViewUrl: (record: SavedGraphWorkspace) => string;
listingLimit: number;
hideWriteControls: boolean;
capabilities: { save: boolean; delete: boolean };
initialFilter: string;
}
export function GraphListing(props: GraphListingProps) {
return (
<I18nProvider>
<TableListView
createItem={props.capabilities.save ? props.createItem : null}
findItems={props.findItems}
deleteItems={props.capabilities.delete ? props.deleteItems : null}
editItem={props.capabilities.save ? props.editItem : null}
tableColumns={getTableColumns(props.getViewUrl)}
listingLimit={props.listingLimit}
initialFilter={props.initialFilter}
noItemsFragment={getNoItemsMessage(props.capabilities.save === false, props.createItem)}
entityName={i18n.translate('xpack.graph.listing.table.entityName', {
defaultMessage: 'workspace',
})}
entityNamePlural={i18n.translate('xpack.graph.listing.table.entityNamePlural', {
defaultMessage: 'workspaces',
})}
tableListTitle={i18n.translate('xpack.graph.listing.workspacesTitle', {
defaultMessage: 'Workspaces',
})}
/>
</I18nProvider>
);
}
function getNoItemsMessage(hideWriteControls: boolean, createItem: () => void) {
if (hideWriteControls) {
return (
<div>
<EuiEmptyPrompt
iconType="visualizeApp"
title={
<h2>
<FormattedMessage
id="xpack.graph.listing.noItemsMessage"
defaultMessage="Looks like you don't have any Graph workspaces."
/>
</h2>
}
/>
</div>
);
}
return (
<div>
<EuiEmptyPrompt
iconType="graphApp"
title={
<h2>
<FormattedMessage
id="xpack.graph.listing.createNewWorkspace.title"
defaultMessage="Create your first Graph workspace"
/>
</h2>
}
body={
<Fragment>
<p>
<FormattedMessage
id="xpack.graph.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
defaultMessage="You can discover patterns and relationships in your Kibana index patterns."
/>
</p>
<p>
<FormattedMessage
id="xpack.graph.listing.createNewDashboard.newToKibanaDescription"
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
values={{
sampleDataInstallLink: (
<EuiLink href="#/home/tutorial_directory/sampleData">
<FormattedMessage
id="xpack.graph.listing.createNewDashboard.sampleDataInstallLinkText"
defaultMessage="Install some sample data"
/>
</EuiLink>
),
}}
/>
</p>
</Fragment>
}
actions={
<EuiButton
onClick={createItem}
fill
iconType="plusInCircle"
data-test-subj="graphCreateWorkspacePromptButton"
>
<FormattedMessage
id="xpack.graph.listing.createNewWorkspace.createButtonLabel"
defaultMessage="Create new graph workspace"
/>
</EuiButton>
}
/>
</div>
);
}
// TODO this is an EUI type but EUI doesn't provide this typing yet
interface DataColumn {
field: string;
name: string;
sortable?: boolean;
render?: (value: string, item: SavedGraphWorkspace) => React.ReactNode;
dataType?: 'auto' | 'string' | 'number' | 'date' | 'boolean';
}
function getTableColumns(getViewUrl: (record: SavedGraphWorkspace) => string): DataColumn[] {
return [
{
field: 'title',
name: i18n.translate('xpack.graph.listing.table.titleColumnName', {
defaultMessage: 'Title',
}),
sortable: true,
render: (field, record) => (
<EuiLink
href={getViewUrl(record)}
data-test-subj={`graphListingTitleLink-${record.title.split(' ').join('-')}`}
>
{field}
</EuiLink>
),
},
{
field: 'description',
name: i18n.translate('xpack.graph.listing.table.descriptionColumnName', {
defaultMessage: 'Description',
}),
dataType: 'string',
sortable: true,
},
];
}

View file

@ -1,17 +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;
* you may not use this file except in compliance with the Elastic License.
*/
import { uiModules } from 'ui/modules';
import template from '../templates/load_workspace.html';
const app = uiModules.get('app/graph');
app.directive('graphLoad', function () {
return {
replace: true,
restrict: 'E',
template,
};
});

View file

@ -11,4 +11,4 @@
// gphChart__legend-isLoading
@import './main';
@import './templates/index';
@import './angular/templates/index';

View file

@ -0,0 +1,69 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { i18n } from '@kbn/i18n';
import { Chrome } from 'ui/chrome';
import { SavedGraphWorkspace } from '../types/persistence';
export function getHomePath() {
return '/home';
}
export function getNewPath() {
return '/workspace';
}
export function getEditPath({ id }: SavedGraphWorkspace) {
return `/workspace/${id}`;
}
export function getEditUrl(chrome: Chrome, workspace: SavedGraphWorkspace) {
return chrome.addBasePath(`#${getEditPath(workspace)}`);
}
export type SetBreadcrumbOptions =
| {
chrome: Chrome;
}
| {
chrome: Chrome;
savedWorkspace?: SavedGraphWorkspace;
navigateTo: (path: string) => void;
};
export function setBreadcrumbs(options: SetBreadcrumbOptions) {
if ('savedWorkspace' in options) {
options.chrome.breadcrumbs.set([
{
text: i18n.translate('xpack.graph.home.breadcrumb', {
defaultMessage: 'Graph',
}),
onClick: () => {
options.navigateTo(getHomePath());
},
'data-test-subj': 'graphHomeBreadcrumb',
},
{
text: options.savedWorkspace
? options.savedWorkspace.title
: i18n.translate('xpack.graph.newWorkspaceTitle', {
defaultMessage: 'Unsaved workspace',
}),
'data-test-subj': 'graphCurrentWorkspaceBreadcrumb',
},
]);
} else {
options.chrome.breadcrumbs.set([
{
text: i18n.translate('xpack.graph.home.breadcrumb', {
defaultMessage: 'Graph',
}),
href: `#${getHomePath()}`,
'data-test-subj': 'graphHomeBreadcrumb',
},
]);
}
}

View file

@ -1,15 +0,0 @@
<div>
<div
class="kuiLocalDropdownTitle"
i18n-id="xpack.graph.topNavMenu.open.openWorkspaceTitle"
i18n-default-message="Open Workspace"
></div>
<saved-object-finder
title="{{ ::'xpack.graph.topNavMenu.open.workspacesListTooltip' | i18n: { defaultMessage: 'Saved Workspaces' } }}"
type="Graph workspace"
use-local-management="true"
on-choose="openSavedWorkspace"
></saved-object-finder>
</div>

View file

@ -0,0 +1,20 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { SavedObject } from 'ui/saved_objects/saved_object';
/**
* Workspace fetched from server.
* This type is returned by `SavedWorkspacesProvider#get`.
*/
export interface SavedGraphWorkspace extends SavedObject {
title: string;
description: string;
numLinks: number;
numVertices: number;
version: number;
wsState: string;
}

View file

@ -4640,23 +4640,9 @@
"xpack.graph.topNavMenu.addedFieldTooltip": "検索が {fName} を返した場合、Shift を押しながらクリックすると切り替わります",
"xpack.graph.topNavMenu.addFieldButtonAriaLabel": "フィールドを追加",
"xpack.graph.topNavMenu.addFieldButtonTooltip": "頂点のフィールドソースを追加",
"xpack.graph.topNavMenu.deleteWorkspace.confirmButtonLabel": "ワークスペースを削除",
"xpack.graph.topNavMenu.deleteWorkspace.confirmText": "ワークスペース {title} を削除してよろしいですか?",
"xpack.graph.topNavMenu.deleteWorkspace.disabledAriaLabel": "保存されたワークスペースを削除",
"xpack.graph.topNavMenu.deleteWorkspace.disabledLabel": "削除",
"xpack.graph.topNavMenu.deleteWorkspace.disabledTooltip": "現在の保存ポリシーでは、保存されたワークスペースへの変更が許可されていません",
"xpack.graph.topNavMenu.deleteWorkspace.enabledAriaLabel": "保存されたワークスペースを削除",
"xpack.graph.topNavMenu.deleteWorkspace.enabledAriaTooltip": "このワークスペースを削除します",
"xpack.graph.topNavMenu.deleteWorkspace.enabledLabel": "削除",
"xpack.graph.topNavMenu.deleteWorkspaceNotification": "「{workspaceTitle}」が削除されました",
"xpack.graph.topNavMenu.loadWorkspaceAriaLabel": "保存されたワークスペースを読み込む",
"xpack.graph.topNavMenu.loadWorkspaceLabel": "開く",
"xpack.graph.topNavMenu.loadWorkspaceTooltip": "保存されたワークスペースを読み込みます",
"xpack.graph.topNavMenu.newWorkspaceAriaLabel": "新規ワークスペース",
"xpack.graph.topNavMenu.newWorkspaceLabel": "新規",
"xpack.graph.topNavMenu.newWorkspaceTooltip": "新規ワークスペースを作成します",
"xpack.graph.topNavMenu.open.openWorkspaceTitle": "ワークスペースを開く",
"xpack.graph.topNavMenu.open.workspacesListTooltip": "保存されたワークスペース",
"xpack.graph.topNavMenu.save.confirmButtonAriaLabel": "ワークスペースを保存",
"xpack.graph.topNavMenu.save.confirmButtonLabel": "保存",
"xpack.graph.topNavMenu.save.descriptionInputLabel": "説明",

View file

@ -4783,23 +4783,9 @@
"xpack.graph.topNavMenu.addedFieldTooltip": "如果搜索返回 {fName},则按住 Shift 并点击来进行切换",
"xpack.graph.topNavMenu.addFieldButtonAriaLabel": "添加字段",
"xpack.graph.topNavMenu.addFieldButtonTooltip": "为顶点添加字段源",
"xpack.graph.topNavMenu.deleteWorkspace.confirmButtonLabel": "删除工作空间",
"xpack.graph.topNavMenu.deleteWorkspace.confirmText": "是否确定要删除工作空间 {title}",
"xpack.graph.topNavMenu.deleteWorkspace.disabledAriaLabel": "删除已保存的工作空间",
"xpack.graph.topNavMenu.deleteWorkspace.disabledLabel": "删除",
"xpack.graph.topNavMenu.deleteWorkspace.disabledTooltip": "当前保存策略不允许对已保存的工作空间做任何更改",
"xpack.graph.topNavMenu.deleteWorkspace.enabledAriaLabel": "删除已保存的工作空间",
"xpack.graph.topNavMenu.deleteWorkspace.enabledAriaTooltip": "删除此工作空间",
"xpack.graph.topNavMenu.deleteWorkspace.enabledLabel": "删除",
"xpack.graph.topNavMenu.deleteWorkspaceNotification": "已删除“{workspaceTitle}”",
"xpack.graph.topNavMenu.loadWorkspaceAriaLabel": "加载已保存的工作空间",
"xpack.graph.topNavMenu.loadWorkspaceLabel": "打开",
"xpack.graph.topNavMenu.loadWorkspaceTooltip": "加载已保存的工作空间",
"xpack.graph.topNavMenu.newWorkspaceAriaLabel": "新建工作空间",
"xpack.graph.topNavMenu.newWorkspaceLabel": "新建",
"xpack.graph.topNavMenu.newWorkspaceTooltip": "新建工作空间",
"xpack.graph.topNavMenu.open.openWorkspaceTitle": "打开工作空间",
"xpack.graph.topNavMenu.open.workspacesListTooltip": "已保存的工作空间",
"xpack.graph.topNavMenu.save.confirmButtonAriaLabel": "保存工作空间",
"xpack.graph.topNavMenu.save.confirmButtonLabel": "保存",
"xpack.graph.topNavMenu.save.descriptionInputLabel": "描述",

View file

@ -71,19 +71,26 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
]);
});
it('shows save button', async () => {
it('landing page shows "Create new Workspace" button', async () => {
await PageObjects.common.navigateToApp('graph');
await testSubjects.existOrFail('graphSaveButton');
});
it('shows delete button', async () => {
await PageObjects.common.navigateToApp('graph');
await testSubjects.existOrFail('graphDeleteButton');
await testSubjects.existOrFail('workspaceLandingPage', { timeout: 10000 });
await testSubjects.existOrFail('graphCreateWorkspacePromptButton');
});
it(`doesn't show read-only badge`, async () => {
await globalNav.badgeMissingOrFail();
});
it('allows creating a new workspace', async () => {
await PageObjects.common.navigateToApp('graph');
await testSubjects.click('graphCreateWorkspacePromptButton');
const breadcrumb = await testSubjects.find('graphCurrentWorkspaceBreadcrumb');
expect(await breadcrumb.getVisibleText()).to.equal('Unsaved workspace');
});
it('shows save button', async () => {
await testSubjects.existOrFail('graphSaveButton');
});
});
describe('global graph read-only privileges', () => {
@ -129,16 +136,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
expect(navLinks).to.eql(['Graph', 'Management']);
});
it(`doesn't show save button`, async () => {
it('does not show a "Create new Workspace" button', async () => {
await PageObjects.common.navigateToApp('graph');
await testSubjects.existOrFail('graphOpenButton');
await testSubjects.missingOrFail('graphSaveButton');
});
it(`doesn't show delete button`, async () => {
await PageObjects.common.navigateToApp('graph');
await testSubjects.existOrFail('graphOpenButton');
await testSubjects.missingOrFail('graphDeleteButton');
await testSubjects.existOrFail('workspaceLandingPage', { timeout: 10000 });
await testSubjects.missingOrFail('newItemButton');
});
it(`shows read-only badge`, async () => {

View file

@ -41,18 +41,21 @@ export default function({ getPageObjects, getService }: FtrProviderContext) {
expect(navLinks).to.contain('Graph');
});
it('shows save button', async () => {
it('landing page shows "Create new Workspace" button', async () => {
await PageObjects.common.navigateToApp('graph', {
basePath: '/s/custom_space',
});
await testSubjects.existOrFail('graphSaveButton');
await testSubjects.existOrFail('workspaceLandingPage', { timeout: 10000 });
await testSubjects.existOrFail('graphCreateWorkspacePromptButton');
});
it('shows delete button', async () => {
it('allows creating a new workspace', async () => {
await PageObjects.common.navigateToApp('graph', {
basePath: '/s/custom_space',
});
await testSubjects.existOrFail('graphDeleteButton');
await testSubjects.click('graphCreateWorkspacePromptButton');
const breadcrumb = await testSubjects.find('graphCurrentWorkspaceBreadcrumb');
expect(await breadcrumb.getVisibleText()).to.equal('Unsaved workspace');
});
});