mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
parent
531534659a
commit
edd671e631
35 changed files with 375 additions and 258 deletions
|
@ -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<HTMLButtonElement></code> | |
|
||||
| [text](./kibana-plugin-public.chromebreadcrumb.text.md) | <code>string</code> | |
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-public](./kibana-plugin-public.md) > [ChromeBreadcrumb](./kibana-plugin-public.chromebreadcrumb.md) > [onClick](./kibana-plugin-public.chromebreadcrumb.onclick.md)
|
||||
|
||||
## ChromeBreadcrumb.onClick property
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
onClick?: MouseEventHandler<HTMLButtonElement>;
|
||||
```
|
|
@ -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 */
|
||||
|
|
|
@ -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';
|
||||
|
@ -104,6 +105,8 @@ export interface ChromeBreadcrumb {
|
|||
// (undocumented)
|
||||
href?: string;
|
||||
// (undocumented)
|
||||
onClick?: MouseEventHandler<HTMLButtonElement>;
|
||||
// (undocumented)
|
||||
text: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 () {
|
||||
|
|
@ -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>
|
|
@ -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"
|
||||
/>
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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');
|
|
@ -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
|
||||
}
|
||||
];
|
||||
}
|
164
x-pack/legacy/plugins/graph/public/components/graph_listing.tsx
Normal file
164
x-pack/legacy/plugins/graph/public/components/graph_listing.tsx
Normal 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,
|
||||
},
|
||||
];
|
||||
}
|
|
@ -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,
|
||||
};
|
||||
});
|
|
@ -11,4 +11,4 @@
|
|||
// gphChart__legend-isLoading
|
||||
|
||||
@import './main';
|
||||
@import './templates/index';
|
||||
@import './angular/templates/index';
|
||||
|
|
69
x-pack/legacy/plugins/graph/public/services/url.ts
Normal file
69
x-pack/legacy/plugins/graph/public/services/url.ts
Normal 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',
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -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>
|
20
x-pack/legacy/plugins/graph/public/types/persistence.ts
Normal file
20
x-pack/legacy/plugins/graph/public/types/persistence.ts
Normal 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;
|
||||
}
|
|
@ -4655,23 +4655,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": "説明",
|
||||
|
|
|
@ -4799,23 +4799,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": "描述",
|
||||
|
|
|
@ -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 () => {
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue