From 067158a8db90a6c929b493222af4f920da8a0e74 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Mon, 26 Aug 2019 17:56:11 +0200 Subject: [PATCH 01/31] create graph listing page --- x-pack/legacy/plugins/graph/public/app.js | 183 +++++++----------- .../plugins/graph/public/breadcrumbs.js | 29 --- .../graph/public/components/graph_listing.tsx | 164 ++++++++++++++++ .../public/templates/listing_ng_wrapper.html | 10 + .../plugins/graph/public/types/workspace.ts | 14 ++ 5 files changed, 253 insertions(+), 147 deletions(-) delete mode 100644 x-pack/legacy/plugins/graph/public/breadcrumbs.js create mode 100644 x-pack/legacy/plugins/graph/public/components/graph_listing.tsx create mode 100644 x-pack/legacy/plugins/graph/public/templates/listing_ng_wrapper.html create mode 100644 x-pack/legacy/plugins/graph/public/types/workspace.ts diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index 2f65077226a10..ae0c000e8f955 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -30,14 +30,17 @@ 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 { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; import appTemplate from './templates/index.html'; -import { getHomeBreadcrumbs, getWorkspaceBreadcrumbs } from './breadcrumbs'; +import listingTemplate from './templates/listing_ng_wrapper.html'; import { getReadonlyBadge } from './badge'; import { FormattedMessage } from '@kbn/i18n/react'; +import { GraphListing } from './components/graph_listing'; + import './angular-venn-simple.js'; import gws from './graphClientWorkspace.js'; import utils from './utils.js'; @@ -85,42 +88,53 @@ 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); - - 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 + controller($injector, $location, $scope, $route, Private, config, Promise, kbnBaseUrl) { + checkLicense(Promise, kbnBaseUrl); + const services = Private(SavedObjectRegistryProvider).byLoaderPropertiesName; + const kbnUrl = $injector.get('kbnUrl'); + + $scope.listingLimit = config.get('savedObjects:listingLimit'); + $scope.create = () => { + kbnUrl.redirect('/workspace/'); + }; + $scope.find = (search) => { + return services['Graph workspace'].find(search, $scope.listingLimit); + }; + $scope.editItem = ({ id }) => { + kbnUrl.redirect(`/workspace/${id}`); + }; + $scope.getViewUrl = ({ id }) => { + return chrome.addBasePath(`#/workspace/${id}`); + }; + $scope.delete = (ids) => { + return services.dashboards.delete(ids); + }; + $scope.capabilities = capabilities.get().graph; + $scope.initialFilter = ($location.search()).filter || ''; + chrome.breadcrumbs.set([{ + text: i18n.translate('xpack.graph.graphBreadcrumbsTitle', { + defaultMessage: 'Graph', + }), + }]); } }) - .when('/workspace/:id', { + .when('/workspace/:id?', { template: appTemplate, - k7Breadcrumbs: getWorkspaceBreadcrumbs, 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 +162,7 @@ uiRoutes }, SavedWorkspacesProvider: function (Private) { return Private(SavedWorkspacesProvider); - }, - CheckLicense: checkLicense + } } }) .otherwise({ @@ -344,13 +357,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 +857,7 @@ app.controller('graphuiPlugin', function ( }), run: function () { canWipeWorkspace(function () { - kbnUrl.change('/home', {}); + kbnUrl.change('/workspace/', {}); }); }, }); @@ -882,92 +898,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,6 +916,23 @@ app.controller('graphuiPlugin', function ( }, }); + chrome.breadcrumbs.set([{ + text: i18n.translate('xpack.graph.graphBreadcrumbsTitle', { + defaultMessage: 'Graph', + }), + onClick: () => { + canWipeWorkspace(function () { + $scope.$evalAsync(() => { + kbnUrl.changePath('/home/'); + }); + }); + } + }, { + text: $route.current.locals.savedWorkspace + ? $route.current.locals.savedWorkspace.title + : i18n.translate('xpack.graph.newWorkspaceTitle', { defaultMessage: 'Unsaved workspace' }), + }]); + $scope.menus = { showSave: false, showLoad: false, diff --git a/x-pack/legacy/plugins/graph/public/breadcrumbs.js b/x-pack/legacy/plugins/graph/public/breadcrumbs.js deleted file mode 100644 index 63887e23288f2..0000000000000 --- a/x-pack/legacy/plugins/graph/public/breadcrumbs.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * 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 - } - ]; -} diff --git a/x-pack/legacy/plugins/graph/public/components/graph_listing.tsx b/x-pack/legacy/plugins/graph/public/components/graph_listing.tsx new file mode 100644 index 0000000000000..77e6649d06fee --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/components/graph_listing.tsx @@ -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/workspace'; + +export interface GraphListingProps { + createItem: () => void; + findItems: (query: string, limit: number) => Promise; + deleteItems: (ids: string[]) => Promise; + 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 ( + + + + ); +} + +function getNoItemsMessage(hideWriteControls: boolean, createItem: () => void) { + if (hideWriteControls) { + return ( +
+ + + + } + /> +
+ ); + } + + return ( +
+ + + + } + body={ + +

+ +

+

+ + + + ), + }} + /> +

+
+ } + actions={ + + + + } + /> +
+ ); +} + +// 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) => ( + + {field} + + ), + }, + { + field: 'description', + name: i18n.translate('xpack.graph.listing.table.descriptionColumnName', { + defaultMessage: 'Description', + }), + dataType: 'string', + sortable: true, + }, + ]; +} diff --git a/x-pack/legacy/plugins/graph/public/templates/listing_ng_wrapper.html b/x-pack/legacy/plugins/graph/public/templates/listing_ng_wrapper.html new file mode 100644 index 0000000000000..09899453dd351 --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/templates/listing_ng_wrapper.html @@ -0,0 +1,10 @@ + diff --git a/x-pack/legacy/plugins/graph/public/types/workspace.ts b/x-pack/legacy/plugins/graph/public/types/workspace.ts new file mode 100644 index 0000000000000..646163664ddf9 --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/types/workspace.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +export interface SavedGraphWorkspace { + title: string; + description: string; + numLinks: number; + numVertices: number; + version: number; + wsState: string; +} From 5fddc108c599126e14f7576b7f5196f712a26f7e Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Mon, 26 Aug 2019 19:34:37 +0200 Subject: [PATCH 02/31] clean up app folder --- src/core/public/chrome/chrome_service.tsx | 1 + .../{ => angular}/__tests__/workspace.js | 0 .../angular_venn_simple.js} | 0 .../{ => angular}/directives/graph_load.js | 0 .../{ => angular}/directives/graph_save.js | 0 .../directives/graph_settings.js | 0 .../graph_client_workspace.js} | 0 .../services/outlink_encoders.js | 0 .../{ => angular}/services/saved_workspace.js | 0 .../services/saved_workspace_references.js | 0 .../saved_workspace_references.test.js | 0 .../services/saved_workspaces.js | 0 .../{ => angular}/templates/_graph.scss | 0 .../{ => angular}/templates/_index.scss | 0 .../{ => angular}/templates/_settings.scss | 0 .../{ => angular}/templates/_sidebar.scss | 0 .../public/{ => angular}/templates/index.html | 0 .../templates/listing_ng_wrapper.html | 0 .../templates/load_workspace.html | 0 .../templates/save_workspace.html | 0 .../{ => angular}/templates/settings.html | 0 x-pack/legacy/plugins/graph/public/app.js | 63 ++++++++---------- .../graph/public/components/graph_listing.tsx | 4 +- x-pack/legacy/plugins/graph/public/index.scss | 2 +- .../plugins/graph/public/services/url.ts | 66 +++++++++++++++++++ .../types/{workspace.ts => persistence.ts} | 8 ++- 26 files changed, 104 insertions(+), 40 deletions(-) rename x-pack/legacy/plugins/graph/public/{ => angular}/__tests__/workspace.js (100%) rename x-pack/legacy/plugins/graph/public/{angular-venn-simple.js => angular/angular_venn_simple.js} (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/directives/graph_load.js (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/directives/graph_save.js (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/directives/graph_settings.js (100%) rename x-pack/legacy/plugins/graph/public/{graphClientWorkspace.js => angular/graph_client_workspace.js} (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/services/outlink_encoders.js (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/services/saved_workspace.js (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/services/saved_workspace_references.js (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/services/saved_workspace_references.test.js (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/services/saved_workspaces.js (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/templates/_graph.scss (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/templates/_index.scss (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/templates/_settings.scss (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/templates/_sidebar.scss (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/templates/index.html (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/templates/listing_ng_wrapper.html (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/templates/load_workspace.html (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/templates/save_workspace.html (100%) rename x-pack/legacy/plugins/graph/public/{ => angular}/templates/settings.html (100%) create mode 100644 x-pack/legacy/plugins/graph/public/services/url.ts rename x-pack/legacy/plugins/graph/public/types/{workspace.ts => persistence.ts} (62%) diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index 668bce522bf4e..8798c1a88bff7 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -63,6 +63,7 @@ export interface ChromeBreadcrumb { text: string; href?: string; 'data-test-subj'?: string; + onClick?: () => void; } /** @public */ diff --git a/x-pack/legacy/plugins/graph/public/__tests__/workspace.js b/x-pack/legacy/plugins/graph/public/angular/__tests__/workspace.js similarity index 100% rename from x-pack/legacy/plugins/graph/public/__tests__/workspace.js rename to x-pack/legacy/plugins/graph/public/angular/__tests__/workspace.js diff --git a/x-pack/legacy/plugins/graph/public/angular-venn-simple.js b/x-pack/legacy/plugins/graph/public/angular/angular_venn_simple.js similarity index 100% rename from x-pack/legacy/plugins/graph/public/angular-venn-simple.js rename to x-pack/legacy/plugins/graph/public/angular/angular_venn_simple.js diff --git a/x-pack/legacy/plugins/graph/public/directives/graph_load.js b/x-pack/legacy/plugins/graph/public/angular/directives/graph_load.js similarity index 100% rename from x-pack/legacy/plugins/graph/public/directives/graph_load.js rename to x-pack/legacy/plugins/graph/public/angular/directives/graph_load.js diff --git a/x-pack/legacy/plugins/graph/public/directives/graph_save.js b/x-pack/legacy/plugins/graph/public/angular/directives/graph_save.js similarity index 100% rename from x-pack/legacy/plugins/graph/public/directives/graph_save.js rename to x-pack/legacy/plugins/graph/public/angular/directives/graph_save.js diff --git a/x-pack/legacy/plugins/graph/public/directives/graph_settings.js b/x-pack/legacy/plugins/graph/public/angular/directives/graph_settings.js similarity index 100% rename from x-pack/legacy/plugins/graph/public/directives/graph_settings.js rename to x-pack/legacy/plugins/graph/public/angular/directives/graph_settings.js diff --git a/x-pack/legacy/plugins/graph/public/graphClientWorkspace.js b/x-pack/legacy/plugins/graph/public/angular/graph_client_workspace.js similarity index 100% rename from x-pack/legacy/plugins/graph/public/graphClientWorkspace.js rename to x-pack/legacy/plugins/graph/public/angular/graph_client_workspace.js diff --git a/x-pack/legacy/plugins/graph/public/services/outlink_encoders.js b/x-pack/legacy/plugins/graph/public/angular/services/outlink_encoders.js similarity index 100% rename from x-pack/legacy/plugins/graph/public/services/outlink_encoders.js rename to x-pack/legacy/plugins/graph/public/angular/services/outlink_encoders.js diff --git a/x-pack/legacy/plugins/graph/public/services/saved_workspace.js b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace.js similarity index 100% rename from x-pack/legacy/plugins/graph/public/services/saved_workspace.js rename to x-pack/legacy/plugins/graph/public/angular/services/saved_workspace.js diff --git a/x-pack/legacy/plugins/graph/public/services/saved_workspace_references.js b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.js similarity index 100% rename from x-pack/legacy/plugins/graph/public/services/saved_workspace_references.js rename to x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.js diff --git a/x-pack/legacy/plugins/graph/public/services/saved_workspace_references.test.js b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.test.js similarity index 100% rename from x-pack/legacy/plugins/graph/public/services/saved_workspace_references.test.js rename to x-pack/legacy/plugins/graph/public/angular/services/saved_workspace_references.test.js diff --git a/x-pack/legacy/plugins/graph/public/services/saved_workspaces.js b/x-pack/legacy/plugins/graph/public/angular/services/saved_workspaces.js similarity index 100% rename from x-pack/legacy/plugins/graph/public/services/saved_workspaces.js rename to x-pack/legacy/plugins/graph/public/angular/services/saved_workspaces.js diff --git a/x-pack/legacy/plugins/graph/public/templates/_graph.scss b/x-pack/legacy/plugins/graph/public/angular/templates/_graph.scss similarity index 100% rename from x-pack/legacy/plugins/graph/public/templates/_graph.scss rename to x-pack/legacy/plugins/graph/public/angular/templates/_graph.scss diff --git a/x-pack/legacy/plugins/graph/public/templates/_index.scss b/x-pack/legacy/plugins/graph/public/angular/templates/_index.scss similarity index 100% rename from x-pack/legacy/plugins/graph/public/templates/_index.scss rename to x-pack/legacy/plugins/graph/public/angular/templates/_index.scss diff --git a/x-pack/legacy/plugins/graph/public/templates/_settings.scss b/x-pack/legacy/plugins/graph/public/angular/templates/_settings.scss similarity index 100% rename from x-pack/legacy/plugins/graph/public/templates/_settings.scss rename to x-pack/legacy/plugins/graph/public/angular/templates/_settings.scss diff --git a/x-pack/legacy/plugins/graph/public/templates/_sidebar.scss b/x-pack/legacy/plugins/graph/public/angular/templates/_sidebar.scss similarity index 100% rename from x-pack/legacy/plugins/graph/public/templates/_sidebar.scss rename to x-pack/legacy/plugins/graph/public/angular/templates/_sidebar.scss diff --git a/x-pack/legacy/plugins/graph/public/templates/index.html b/x-pack/legacy/plugins/graph/public/angular/templates/index.html similarity index 100% rename from x-pack/legacy/plugins/graph/public/templates/index.html rename to x-pack/legacy/plugins/graph/public/angular/templates/index.html diff --git a/x-pack/legacy/plugins/graph/public/templates/listing_ng_wrapper.html b/x-pack/legacy/plugins/graph/public/angular/templates/listing_ng_wrapper.html similarity index 100% rename from x-pack/legacy/plugins/graph/public/templates/listing_ng_wrapper.html rename to x-pack/legacy/plugins/graph/public/angular/templates/listing_ng_wrapper.html diff --git a/x-pack/legacy/plugins/graph/public/templates/load_workspace.html b/x-pack/legacy/plugins/graph/public/angular/templates/load_workspace.html similarity index 100% rename from x-pack/legacy/plugins/graph/public/templates/load_workspace.html rename to x-pack/legacy/plugins/graph/public/angular/templates/load_workspace.html diff --git a/x-pack/legacy/plugins/graph/public/templates/save_workspace.html b/x-pack/legacy/plugins/graph/public/angular/templates/save_workspace.html similarity index 100% rename from x-pack/legacy/plugins/graph/public/templates/save_workspace.html rename to x-pack/legacy/plugins/graph/public/angular/templates/save_workspace.html diff --git a/x-pack/legacy/plugins/graph/public/templates/settings.html b/x-pack/legacy/plugins/graph/public/angular/templates/settings.html similarity index 100% rename from x-pack/legacy/plugins/graph/public/templates/settings.html rename to x-pack/legacy/plugins/graph/public/angular/templates/settings.html diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index ae0c000e8f955..79c3a387ca5f4 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -31,20 +31,21 @@ 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 listingTemplate from './templates/listing_ng_wrapper.html'; +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 { GraphListing } from './components/graph_listing'; -import './angular-venn-simple.js'; -import gws from './graphClientWorkspace.js'; +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, @@ -54,16 +55,16 @@ 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 loadTemplate from './angular/templates/load_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_load'; +import './angular/directives/graph_save'; +import './angular/directives/graph_settings'; const app = uiModules.get('app/graph'); @@ -103,31 +104,26 @@ uiRoutes controller($injector, $location, $scope, $route, Private, config, Promise, kbnBaseUrl) { checkLicense(Promise, kbnBaseUrl); const services = Private(SavedObjectRegistryProvider).byLoaderPropertiesName; + const graphService = services['Graph workspace']; const kbnUrl = $injector.get('kbnUrl'); $scope.listingLimit = config.get('savedObjects:listingLimit'); $scope.create = () => { - kbnUrl.redirect('/workspace/'); + kbnUrl.redirect(getNewPath()); }; $scope.find = (search) => { - return services['Graph workspace'].find(search, $scope.listingLimit); - }; - $scope.editItem = ({ id }) => { - kbnUrl.redirect(`/workspace/${id}`); + return graphService.find(search, $scope.listingLimit); }; - $scope.getViewUrl = ({ id }) => { - return chrome.addBasePath(`#/workspace/${id}`); + $scope.editItem = (workspace) => { + kbnUrl.redirect(getEditPath(workspace)); }; + $scope.getViewUrl = (workspace) => getEditUrl(chrome, workspace); $scope.delete = (ids) => { - return services.dashboards.delete(ids); + return graphService.delete(ids); }; $scope.capabilities = capabilities.get().graph; $scope.initialFilter = ($location.search()).filter || ''; - chrome.breadcrumbs.set([{ - text: i18n.translate('xpack.graph.graphBreadcrumbsTitle', { - defaultMessage: 'Graph', - }), - }]); + setBreadcrumbs({ chrome }); } }) .when('/workspace/:id?', { @@ -916,22 +912,17 @@ app.controller('graphuiPlugin', function ( }, }); - chrome.breadcrumbs.set([{ - text: i18n.translate('xpack.graph.graphBreadcrumbsTitle', { - defaultMessage: 'Graph', - }), - onClick: () => { + setBreadcrumbs({ + chrome, + savedWorkspace: $route.current.locals.savedWorkspace, + navigateTo: () => { canWipeWorkspace(function () { $scope.$evalAsync(() => { kbnUrl.changePath('/home/'); }); }); } - }, { - text: $route.current.locals.savedWorkspace - ? $route.current.locals.savedWorkspace.title - : i18n.translate('xpack.graph.newWorkspaceTitle', { defaultMessage: 'Unsaved workspace' }), - }]); + }); $scope.menus = { showSave: false, diff --git a/x-pack/legacy/plugins/graph/public/components/graph_listing.tsx b/x-pack/legacy/plugins/graph/public/components/graph_listing.tsx index 77e6649d06fee..f271fcc27d42a 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_listing.tsx +++ b/x-pack/legacy/plugins/graph/public/components/graph_listing.tsx @@ -11,7 +11,7 @@ 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/workspace'; +import { SavedGraphWorkspace } from '../types/persistence'; export interface GraphListingProps { createItem: () => void; @@ -146,7 +146,7 @@ function getTableColumns(getViewUrl: (record: SavedGraphWorkspace) => string): D render: (field, record) => ( {field} diff --git a/x-pack/legacy/plugins/graph/public/index.scss b/x-pack/legacy/plugins/graph/public/index.scss index eb166638ca248..3986f64c6f4c9 100644 --- a/x-pack/legacy/plugins/graph/public/index.scss +++ b/x-pack/legacy/plugins/graph/public/index.scss @@ -11,4 +11,4 @@ // gphChart__legend-isLoading @import './main'; -@import './templates/index'; +@import './angular/templates/index'; diff --git a/x-pack/legacy/plugins/graph/public/services/url.ts b/x-pack/legacy/plugins/graph/public/services/url.ts new file mode 100644 index 0000000000000..d4c79b0bcc273 --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/services/url.ts @@ -0,0 +1,66 @@ +/* + * 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.graphBreadcrumbsTitle', { + defaultMessage: 'Graph', + }), + onClick: () => { + options.navigateTo(getHomePath()); + }, + }, + { + text: options.savedWorkspace + ? options.savedWorkspace.title + : i18n.translate('xpack.graph.newWorkspaceTitle', { + defaultMessage: 'Unsaved workspace', + }), + }, + ]); + } else { + options.chrome.breadcrumbs.set([ + { + text: i18n.translate('xpack.graph.graphBreadcrumbsTitle', { + defaultMessage: 'Graph', + }), + href: `#${getHomePath()}`, + }, + ]); + } +} diff --git a/x-pack/legacy/plugins/graph/public/types/workspace.ts b/x-pack/legacy/plugins/graph/public/types/persistence.ts similarity index 62% rename from x-pack/legacy/plugins/graph/public/types/workspace.ts rename to x-pack/legacy/plugins/graph/public/types/persistence.ts index 646163664ddf9..56040aa30db4c 100644 --- a/x-pack/legacy/plugins/graph/public/types/workspace.ts +++ b/x-pack/legacy/plugins/graph/public/types/persistence.ts @@ -4,7 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -export interface SavedGraphWorkspace { +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; From 95f003b4120d92ef569f65a2c7bb79867781a3d4 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 27 Aug 2019 11:02:30 +0200 Subject: [PATCH 03/31] remove inline loading menu --- .../public/angular/directives/graph_load.js | 17 ----------------- .../graph/public/angular/templates/index.html | 3 +-- .../angular/templates/load_workspace.html | 15 --------------- x-pack/legacy/plugins/graph/public/app.js | 10 +--------- .../plugins/graph/public/app_with_autoload.js | 8 -------- 5 files changed, 2 insertions(+), 51 deletions(-) delete mode 100644 x-pack/legacy/plugins/graph/public/angular/directives/graph_load.js delete mode 100644 x-pack/legacy/plugins/graph/public/angular/templates/load_workspace.html delete mode 100644 x-pack/legacy/plugins/graph/public/app_with_autoload.js diff --git a/x-pack/legacy/plugins/graph/public/angular/directives/graph_load.js b/x-pack/legacy/plugins/graph/public/angular/directives/graph_load.js deleted file mode 100644 index 369243fff7487..0000000000000 --- a/x-pack/legacy/plugins/graph/public/angular/directives/graph_load.js +++ /dev/null @@ -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, - }; -}); diff --git a/x-pack/legacy/plugins/graph/public/angular/templates/index.html b/x-pack/legacy/plugins/graph/public/angular/templates/index.html index fc536d54547e1..4dfc1846bb259 100644 --- a/x-pack/legacy/plugins/graph/public/angular/templates/index.html +++ b/x-pack/legacy/plugins/graph/public/angular/templates/index.html @@ -3,8 +3,7 @@ -
- +
diff --git a/x-pack/legacy/plugins/graph/public/angular/templates/load_workspace.html b/x-pack/legacy/plugins/graph/public/angular/templates/load_workspace.html deleted file mode 100644 index 5f8948caf1e97..0000000000000 --- a/x-pack/legacy/plugins/graph/public/angular/templates/load_workspace.html +++ /dev/null @@ -1,15 +0,0 @@ -
-
- - - -
\ No newline at end of file diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index 79c3a387ca5f4..8189b355e35e7 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -59,10 +59,8 @@ import { import { getEditUrl, getNewPath, getEditPath, setBreadcrumbs } from './services/url'; import saveTemplate from './angular/templates/save_workspace.html'; -import loadTemplate from './angular/templates/load_workspace.html'; import settingsTemplate from './angular/templates/settings.html'; -import './angular/directives/graph_load'; import './angular/directives/graph_save'; import './angular/directives/graph_settings'; @@ -257,11 +255,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 @@ -926,7 +919,6 @@ app.controller('graphuiPlugin', function ( $scope.menus = { showSave: false, - showLoad: false, showSettings: false, }; @@ -1199,7 +1191,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); diff --git a/x-pack/legacy/plugins/graph/public/app_with_autoload.js b/x-pack/legacy/plugins/graph/public/app_with_autoload.js deleted file mode 100644 index ca01a93fefc09..0000000000000 --- a/x-pack/legacy/plugins/graph/public/app_with_autoload.js +++ /dev/null @@ -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'); From ae44388e127cc5206acca6af9c7dbbaa1037afdc Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 27 Aug 2019 11:08:13 +0200 Subject: [PATCH 04/31] also add badge to workspace route --- x-pack/legacy/plugins/graph/public/app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index 8189b355e35e7..4b221e7d9ef2e 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -126,6 +126,7 @@ uiRoutes }) .when('/workspace/:id?', { template: appTemplate, + badge: getReadonlyBadge, resolve: { savedWorkspace: function (savedGraphWorkspaces, courier, $route) { return $route.current.params.id && savedGraphWorkspaces.get($route.current.params.id) From 2f1056f194f3b44934919d5f9bd6e760f484a1ba Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 27 Aug 2019 12:07:26 +0200 Subject: [PATCH 05/31] fix tests --- .../public/angular/__tests__/workspace.js | 2 +- .../plugins/graph/public/services/url.ts | 3 ++ .../graph/feature_controls/graph_security.ts | 31 ++++++++++--------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/x-pack/legacy/plugins/graph/public/angular/__tests__/workspace.js b/x-pack/legacy/plugins/graph/public/angular/__tests__/workspace.js index 592872c96ee05..2575edb333af1 100644 --- a/x-pack/legacy/plugins/graph/public/angular/__tests__/workspace.js +++ b/x-pack/legacy/plugins/graph/public/angular/__tests__/workspace.js @@ -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 () { diff --git a/x-pack/legacy/plugins/graph/public/services/url.ts b/x-pack/legacy/plugins/graph/public/services/url.ts index d4c79b0bcc273..acdb701557ba8 100644 --- a/x-pack/legacy/plugins/graph/public/services/url.ts +++ b/x-pack/legacy/plugins/graph/public/services/url.ts @@ -44,6 +44,7 @@ export function setBreadcrumbs(options: SetBreadcrumbOptions) { onClick: () => { options.navigateTo(getHomePath()); }, + 'data-test-subj': 'graphHomeBreadcrumb', }, { text: options.savedWorkspace @@ -51,6 +52,7 @@ export function setBreadcrumbs(options: SetBreadcrumbOptions) { : i18n.translate('xpack.graph.newWorkspaceTitle', { defaultMessage: 'Unsaved workspace', }), + 'data-test-subj': 'graphCurrentWorkspaceBreadcrumb', }, ]); } else { @@ -60,6 +62,7 @@ export function setBreadcrumbs(options: SetBreadcrumbOptions) { defaultMessage: 'Graph', }), href: `#${getHomePath()}`, + 'data-test-subj': 'graphHomeBreadcrumb', }, ]); } diff --git a/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts b/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts index 05f6717106bad..2dbf6427c347e 100644 --- a/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts +++ b/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts @@ -71,18 +71,25 @@ 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'); + await testSubjects.existOrFail('workspaceLandingPage', { timeout: 10000 }); + await testSubjects.existOrFail('newItemButton'); }); - it('shows delete button', async () => { + 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.existOrFail('graphDeleteButton'); + await testSubjects.click('newItemButton'); + const breadcrumb = await testSubjects.find('graphCurrentWorkspaceBreadcrumb'); + expect(await breadcrumb.getVisibleText()).to.equal('Unsaved workspace'); }); - it(`doesn't show read-only badge`, async () => { - await globalNav.badgeMissingOrFail(); + it('shows save button', async () => { + await testSubjects.existOrFail('graphSaveButton'); }); }); @@ -129,16 +136,10 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { expect(navLinks).to.eql(['Graph', 'Management']); }); - it(`doesn't show save button`, async () => { - await PageObjects.common.navigateToApp('graph'); - await testSubjects.existOrFail('graphOpenButton'); - await testSubjects.missingOrFail('graphSaveButton'); - }); - - it(`doesn't show delete button`, async () => { + it('does not show a "Create new Workspace" 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 () => { From 5d637f525f6fc4eea859aa20cc935737d9f196d9 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 27 Aug 2019 13:00:51 +0200 Subject: [PATCH 06/31] fix graph spaces functional test --- .../apps/graph/feature_controls/graph_spaces.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts b/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts index a0b81a8df702a..4e7c2233286a2 100644 --- a/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts +++ b/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts @@ -41,18 +41,21 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { expect(navLinks).to.contain('Graph'); }); - it('shows save button', async () => { - await PageObjects.common.navigateToApp('graph', { + it('landing page shows "Create new Workspace" button', async () => { + await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); - await testSubjects.existOrFail('graphSaveButton'); + await testSubjects.existOrFail('workspaceLandingPage', { timeout: 10000 }); + await testSubjects.existOrFail('newItemButton'); }); - it('shows delete button', async () => { - await PageObjects.common.navigateToApp('graph', { + it('allows creating a new workspace', async () => { + await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); - await testSubjects.existOrFail('graphDeleteButton'); + await testSubjects.click('newItemButton'); + const breadcrumb = await testSubjects.find('graphCurrentWorkspaceBreadcrumb'); + expect(await breadcrumb.getVisibleText()).to.equal('Unsaved workspace'); }); }); From 9d17862f25e6268a9071dac6fd7d568a1529416f Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 27 Aug 2019 13:06:37 +0200 Subject: [PATCH 07/31] generate documentation for new breadcrumb property --- .../public/kibana-plugin-public.chromebreadcrumb.md | 1 + .../kibana-plugin-public.chromebreadcrumb.onclick.md | 11 +++++++++++ src/core/public/public.api.md | 2 ++ 3 files changed, 14 insertions(+) create mode 100644 docs/development/core/public/kibana-plugin-public.chromebreadcrumb.onclick.md diff --git a/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md index 9a6e0a7cc8715..f395defd5eecd 100644 --- a/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md +++ b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md @@ -17,5 +17,6 @@ export interface ChromeBreadcrumb | --- | --- | --- | | [data-test-subj](./kibana-plugin-public.chromebreadcrumb.data-test-subj.md) | string | | | [href](./kibana-plugin-public.chromebreadcrumb.href.md) | string | | +| [onClick](./kibana-plugin-public.chromebreadcrumb.onclick.md) | () => void | | | [text](./kibana-plugin-public.chromebreadcrumb.text.md) | string | | diff --git a/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.onclick.md b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.onclick.md new file mode 100644 index 0000000000000..806b209b5cb35 --- /dev/null +++ b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.onclick.md @@ -0,0 +1,11 @@ + + +[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 + +Signature: + +```typescript +onClick?: () => void; +``` diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index a5c31e41e0267..71260a856ad07 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -63,6 +63,8 @@ export interface ChromeBreadcrumb { // (undocumented) href?: string; // (undocumented) + onClick?: () => void; + // (undocumented) text: string; } From db1d74065bb0715cac304f148ac14704149488bb Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 27 Aug 2019 13:11:18 +0200 Subject: [PATCH 08/31] fix test subject names --- .../legacy/plugins/graph/public/components/graph_listing.tsx | 4 ++-- .../functional/apps/graph/feature_controls/graph_security.ts | 4 ++-- .../functional/apps/graph/feature_controls/graph_spaces.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/legacy/plugins/graph/public/components/graph_listing.tsx b/x-pack/legacy/plugins/graph/public/components/graph_listing.tsx index f271fcc27d42a..75dcc61017c7a 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_listing.tsx +++ b/x-pack/legacy/plugins/graph/public/components/graph_listing.tsx @@ -113,10 +113,10 @@ function getNoItemsMessage(hideWriteControls: boolean, createItem: () => void) { onClick={createItem} fill iconType="plusInCircle" - data-test-subj="createDashboardPromptButton" + data-test-subj="graphCreateWorkspacePromptButton" > diff --git a/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts b/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts index 2dbf6427c347e..808a21388bcda 100644 --- a/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts +++ b/x-pack/test/functional/apps/graph/feature_controls/graph_security.ts @@ -74,7 +74,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('landing page shows "Create new Workspace" button', async () => { await PageObjects.common.navigateToApp('graph'); await testSubjects.existOrFail('workspaceLandingPage', { timeout: 10000 }); - await testSubjects.existOrFail('newItemButton'); + await testSubjects.existOrFail('graphCreateWorkspacePromptButton'); }); it(`doesn't show read-only badge`, async () => { @@ -83,7 +83,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { it('allows creating a new workspace', async () => { await PageObjects.common.navigateToApp('graph'); - await testSubjects.click('newItemButton'); + await testSubjects.click('graphCreateWorkspacePromptButton'); const breadcrumb = await testSubjects.find('graphCurrentWorkspaceBreadcrumb'); expect(await breadcrumb.getVisibleText()).to.equal('Unsaved workspace'); }); diff --git a/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts b/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts index 4e7c2233286a2..9afbc0a8f2ea2 100644 --- a/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts +++ b/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts @@ -46,14 +46,14 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { basePath: '/s/custom_space', }); await testSubjects.existOrFail('workspaceLandingPage', { timeout: 10000 }); - await testSubjects.existOrFail('newItemButton'); + await testSubjects.existOrFail('graphCreateWorkspacePromptButton'); }); it('allows creating a new workspace', async () => { await PageObjects.common.navigateToApp('home', { basePath: '/s/custom_space', }); - await testSubjects.click('newItemButton'); + await testSubjects.click('graphCreateWorkspacePromptButton'); const breadcrumb = await testSubjects.find('graphCurrentWorkspaceBreadcrumb'); expect(await breadcrumb.getVisibleText()).to.equal('Unsaved workspace'); }); From e09b70d7ed7bdca8439632084523f954775ffbba Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 27 Aug 2019 14:31:24 +0200 Subject: [PATCH 09/31] remove unused translations --- x-pack/legacy/plugins/graph/public/services/url.ts | 4 ++-- .../plugins/translations/translations/ja-JP.json | 14 -------------- .../plugins/translations/translations/zh-CN.json | 14 -------------- 3 files changed, 2 insertions(+), 30 deletions(-) diff --git a/x-pack/legacy/plugins/graph/public/services/url.ts b/x-pack/legacy/plugins/graph/public/services/url.ts index acdb701557ba8..dd9db8fa1f07a 100644 --- a/x-pack/legacy/plugins/graph/public/services/url.ts +++ b/x-pack/legacy/plugins/graph/public/services/url.ts @@ -38,7 +38,7 @@ export function setBreadcrumbs(options: SetBreadcrumbOptions) { if ('savedWorkspace' in options) { options.chrome.breadcrumbs.set([ { - text: i18n.translate('xpack.graph.graphBreadcrumbsTitle', { + text: i18n.translate('xpack.graph.home.breadcrumb', { defaultMessage: 'Graph', }), onClick: () => { @@ -58,7 +58,7 @@ export function setBreadcrumbs(options: SetBreadcrumbOptions) { } else { options.chrome.breadcrumbs.set([ { - text: i18n.translate('xpack.graph.graphBreadcrumbsTitle', { + text: i18n.translate('xpack.graph.home.breadcrumb', { defaultMessage: 'Graph', }), href: `#${getHomePath()}`, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index ddc9037785dc6..7e5ab25b38786 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4638,23 +4638,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": "説明", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index a44195ba28a43..3438002e5cb06 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4781,23 +4781,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": "描述", From 2dab9948855075844974967f006257d37a169ff2 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 27 Aug 2019 15:38:47 +0200 Subject: [PATCH 10/31] start implementing save modal flow for Graph --- x-pack/legacy/plugins/graph/public/app.js | 53 ++++++++++++++++--- .../public/components/graph_save_modal.tsx | 31 +++++++++++ 2 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index 4b221e7d9ef2e..4ede1e68e7268 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -32,6 +32,7 @@ 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 { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal'; import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; @@ -41,6 +42,7 @@ import { getReadonlyBadge } from './badge'; import { FormattedMessage } from '@kbn/i18n/react'; import { GraphListing } from './components/graph_listing'; +import { GraphSaveModal } from './components/graph_save_modal'; import './angular/angular_venn_simple.js'; import gws from './angular/graph_client_workspace.js'; @@ -879,11 +881,42 @@ app.controller('graphuiPlugin', function ( return $scope.allSavingDisabled || $scope.selectedFields.length === 0; }, run: () => { - $scope.$evalAsync(() => { - const curState = $scope.menus.showSave; - $scope.closeMenus(); - $scope.menus.showSave = !curState; - }); + const currentTitle = $scope.savedWorkspace.title; + const currentDescription = $scope.savedWorkspace.title; + const onSave = ({ + newTitle, + newDescription, + newCopyOnSave, + newTimeRestore, + isTitleDuplicateConfirmed, + onTitleDuplicate, + }) => { + $scope.savedWorkspace.title = newTitle; + $scope.savedWorkspace.description = newDescription; + const saveOptions = { + confirmOverwrite: false, + isTitleDuplicateConfirmed, + onTitleDuplicate, + }; + return $scope.saveWorkspace(saveOptions).then((response) => { + // If the save wasn't successful, put the original values back. + if (!(response.id)) { + $scope.savedWorkspace.title = currentTitle; + $scope.savedWorkspace.description = currentDescription; + } + return response; + }); + }; + const graphSaveModal = ( + {}} + title={$scope.savedWorkspace.title} + description={$scope.savedWorkspace.description} + showCopyOnSave={$scope.savedWorkspace.id} + /> + ); + showSaveModal(graphSaveModal); }, testId: 'graphSaveButton', }); @@ -1171,7 +1204,7 @@ app.controller('graphuiPlugin', function ( $scope.savedWorkspace.description = $scope.description; - $scope.savedWorkspace.save().then(function (id) { + return $scope.savedWorkspace.save().then(function (id) { $scope.closeMenus(); $scope.userHasConfirmedSaveWorkspaceData = false; //reset flag if (id) { @@ -1191,8 +1224,12 @@ app.controller('graphuiPlugin', function ( text, 'data-test-subj': 'saveGraphSuccess', }); - if ($scope.savedWorkspace.id === $route.current.params.id) return; - kbnUrl.change(getEditPath($scope.savedWorkspace)); + if ($scope.savedWorkspace.id !== $route.current.params.id) { + kbnUrl.change(getEditPath($scope.savedWorkspace)); + } + return { id }; + } else { + return { error: 'Save was not sucessfull' }; } }, fatalError); diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx new file mode 100644 index 0000000000000..a5c80f29c06c2 --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx @@ -0,0 +1,31 @@ +/* + * 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 React from 'react'; +import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal'; + +export function GraphSaveModal({ + onSave, + onClose, + title, + showCopyOnSave, +}: { + onSave: () => any; + onClose: () => void; + title: string; + showCopyOnSave: boolean; +}) { + return ( + + ); +} From c34d84555ee79a08a149a4e9483a001e2dfb073e Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 27 Aug 2019 17:27:57 +0200 Subject: [PATCH 11/31] fix spaces functional test --- .../functional/apps/graph/feature_controls/graph_spaces.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts b/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts index 9afbc0a8f2ea2..25c094dc5ec99 100644 --- a/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts +++ b/x-pack/test/functional/apps/graph/feature_controls/graph_spaces.ts @@ -42,7 +42,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); it('landing page shows "Create new Workspace" button', async () => { - await PageObjects.common.navigateToApp('home', { + await PageObjects.common.navigateToApp('graph', { basePath: '/s/custom_space', }); await testSubjects.existOrFail('workspaceLandingPage', { timeout: 10000 }); @@ -50,7 +50,7 @@ export default function({ getPageObjects, getService }: FtrProviderContext) { }); it('allows creating a new workspace', async () => { - await PageObjects.common.navigateToApp('home', { + await PageObjects.common.navigateToApp('graph', { basePath: '/s/custom_space', }); await testSubjects.click('graphCreateWorkspacePromptButton'); From 2d775e6724df47471af1e77fd11a5fc802d7b1a4 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 27 Aug 2019 17:52:53 +0200 Subject: [PATCH 12/31] wip save modal --- .../components/saved_object_save_modal.tsx | 2 +- ...al.js => show_saved_object_save_modal.tsx} | 0 x-pack/legacy/plugins/graph/public/app.js | 37 ++++++++++--------- .../public/components/graph_save_modal.tsx | 4 +- .../plugins/graph/public/services/save.tsx | 0 5 files changed, 23 insertions(+), 20 deletions(-) rename src/legacy/ui/public/saved_objects/{show_saved_object_save_modal.js => show_saved_object_save_modal.tsx} (100%) create mode 100644 x-pack/legacy/plugins/graph/public/services/save.tsx diff --git a/src/legacy/ui/public/saved_objects/components/saved_object_save_modal.tsx b/src/legacy/ui/public/saved_objects/components/saved_object_save_modal.tsx index b6802758b958a..05685817bb0da 100644 --- a/src/legacy/ui/public/saved_objects/components/saved_object_save_modal.tsx +++ b/src/legacy/ui/public/saved_objects/components/saved_object_save_modal.tsx @@ -36,7 +36,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import React, { Fragment } from 'react'; import { EuiText } from '@elastic/eui'; -interface OnSaveProps { +export interface OnSaveProps { newTitle: string; newCopyOnSave: boolean; isTitleDuplicateConfirmed: boolean; diff --git a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.js b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx similarity index 100% rename from src/legacy/ui/public/saved_objects/show_saved_object_save_modal.js rename to src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index 4ede1e68e7268..5906f469f631c 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -209,6 +209,20 @@ app.controller('graphuiPlugin', function ( }); } + function updateBreadcrumbs() { + setBreadcrumbs({ + chrome, + savedWorkspace: $route.current.locals.savedWorkspace, + navigateTo: () => { + canWipeWorkspace(function () { + $scope.$evalAsync(() => { + kbnUrl.changePath('/home/'); + }); + }); + } + }); + } + $scope.title = 'Graph'; $scope.spymode = 'request'; @@ -887,12 +901,12 @@ app.controller('graphuiPlugin', function ( newTitle, newDescription, newCopyOnSave, - newTimeRestore, isTitleDuplicateConfirmed, onTitleDuplicate, }) => { $scope.savedWorkspace.title = newTitle; $scope.savedWorkspace.description = newDescription; + $scope.savedWorkspace.copyOnSave = newCopyOnSave; const saveOptions = { confirmOverwrite: false, isTitleDuplicateConfirmed, @@ -939,17 +953,7 @@ app.controller('graphuiPlugin', function ( }, }); - setBreadcrumbs({ - chrome, - savedWorkspace: $route.current.locals.savedWorkspace, - navigateTo: () => { - canWipeWorkspace(function () { - $scope.$evalAsync(() => { - kbnUrl.changePath('/home/'); - }); - }); - } - }); + updateBreadcrumbs(); $scope.menus = { showSave: false, @@ -1114,7 +1118,7 @@ app.controller('graphuiPlugin', function ( }); } - $scope.saveWorkspace = function () { + $scope.saveWorkspace = function (saveOptions) { if ($scope.allSavingDisabled) { // It should not be possible to navigate to this function if allSavingDisabled is set // but adding check here as a safeguard. @@ -1204,7 +1208,7 @@ app.controller('graphuiPlugin', function ( $scope.savedWorkspace.description = $scope.description; - return $scope.savedWorkspace.save().then(function (id) { + return $scope.savedWorkspace.save(saveOptions).then(function (id) { $scope.closeMenus(); $scope.userHasConfirmedSaveWorkspaceData = false; //reset flag if (id) { @@ -1227,10 +1231,9 @@ app.controller('graphuiPlugin', function ( if ($scope.savedWorkspace.id !== $route.current.params.id) { kbnUrl.change(getEditPath($scope.savedWorkspace)); } - return { id }; - } else { - return { error: 'Save was not sucessfull' }; + updateBreadcrumbs(); } + return { id }; }, fatalError); }; diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx index a5c80f29c06c2..834251ddba2f5 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx +++ b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx @@ -5,7 +5,7 @@ */ import React from 'react'; -import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal'; +import { SavedObjectSaveModal, OnSaveProps } from 'ui/saved_objects/components/saved_object_save_modal'; export function GraphSaveModal({ onSave, @@ -13,7 +13,7 @@ export function GraphSaveModal({ title, showCopyOnSave, }: { - onSave: () => any; + onSave: (props: OnSaveProps) => void; onClose: () => void; title: string; showCopyOnSave: boolean; diff --git a/x-pack/legacy/plugins/graph/public/services/save.tsx b/x-pack/legacy/plugins/graph/public/services/save.tsx new file mode 100644 index 0000000000000..e69de29bb2d1d From ebe80d151bf5ccae426d6aefb2839ba3c4d56c1a Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 27 Aug 2019 18:27:04 +0200 Subject: [PATCH 13/31] wip save modal --- .../show_saved_object_save_modal.tsx | 27 +++++---- x-pack/legacy/plugins/graph/public/app.js | 45 ++------------- .../public/components/graph_save_modal.tsx | 38 +++++++++++-- .../plugins/graph/public/services/save.tsx | 55 +++++++++++++++++++ 4 files changed, 107 insertions(+), 58 deletions(-) diff --git a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx index bd2fbba3aa145..9c03a3de34d75 100644 --- a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx +++ b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx @@ -21,7 +21,12 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { I18nContext } from 'ui/i18n'; -export function showSaveModal(saveModal) { +interface MinimalSaveModalProps { + onSave: (...args: any[]) => Promise<{ id?: string } | { error: Error }>; + onClose: () => void; +} + +export function showSaveModal(saveModal: React.ReactElement) { const container = document.createElement('div'); const closeModal = () => { ReactDOM.unmountComponentAtNode(container); @@ -30,21 +35,19 @@ export function showSaveModal(saveModal) { const onSave = saveModal.props.onSave; - const onSaveConfirmed = (...args) => { - onSave(...args).then(({ id, error }) => { - if (id || error) { + const onSaveConfirmed: MinimalSaveModalProps['onSave'] = (...args) => { + return onSave(...args).then(response => { + if (('id' in response && response.id) || 'error' in response) { closeModal(); } + return response; }); }; document.body.appendChild(container); - const element = React.cloneElement( - saveModal, - { - onSave: onSaveConfirmed, - onClose: closeModal - } - ); + const element = React.cloneElement(saveModal, { + onSave: onSaveConfirmed, + onClose: closeModal, + }); ReactDOM.render({element}, container); -} +} \ No newline at end of file diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index 5906f469f631c..2b688e711fd41 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -32,7 +32,6 @@ 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 { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal'; import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; @@ -42,7 +41,9 @@ import { getReadonlyBadge } from './badge'; import { FormattedMessage } from '@kbn/i18n/react'; import { GraphListing } from './components/graph_listing'; -import { GraphSaveModal } from './components/graph_save_modal'; + +import { getEditUrl, getNewPath, getEditPath, setBreadcrumbs } from './services/url'; +import { save } from './services/save'; import './angular/angular_venn_simple.js'; import gws from './angular/graph_client_workspace.js'; @@ -58,7 +59,6 @@ import { import { getOutlinkEncoders, } from './angular/services/outlink_encoders'; -import { getEditUrl, getNewPath, getEditPath, setBreadcrumbs } from './services/url'; import saveTemplate from './angular/templates/save_workspace.html'; import settingsTemplate from './angular/templates/settings.html'; @@ -895,42 +895,7 @@ app.controller('graphuiPlugin', function ( return $scope.allSavingDisabled || $scope.selectedFields.length === 0; }, run: () => { - const currentTitle = $scope.savedWorkspace.title; - const currentDescription = $scope.savedWorkspace.title; - const onSave = ({ - newTitle, - newDescription, - newCopyOnSave, - isTitleDuplicateConfirmed, - onTitleDuplicate, - }) => { - $scope.savedWorkspace.title = newTitle; - $scope.savedWorkspace.description = newDescription; - $scope.savedWorkspace.copyOnSave = newCopyOnSave; - const saveOptions = { - confirmOverwrite: false, - isTitleDuplicateConfirmed, - onTitleDuplicate, - }; - return $scope.saveWorkspace(saveOptions).then((response) => { - // If the save wasn't successful, put the original values back. - if (!(response.id)) { - $scope.savedWorkspace.title = currentTitle; - $scope.savedWorkspace.description = currentDescription; - } - return response; - }); - }; - const graphSaveModal = ( - {}} - title={$scope.savedWorkspace.title} - description={$scope.savedWorkspace.description} - showCopyOnSave={$scope.savedWorkspace.id} - /> - ); - showSaveModal(graphSaveModal); + save($scope.savedWorkspace, $scope.saveWorkspace); }, testId: 'graphSaveButton', }); @@ -1205,8 +1170,6 @@ app.controller('graphuiPlugin', function ( }); $scope.savedWorkspace.numVertices = vertices.length; $scope.savedWorkspace.numLinks = links.length; - $scope.savedWorkspace.description = $scope.description; - return $scope.savedWorkspace.save(saveOptions).then(function (id) { $scope.closeMenus(); diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx index 834251ddba2f5..29a606d49ccd4 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx +++ b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx @@ -4,28 +4,56 @@ * you may not use this file except in compliance with the Elastic License. */ -import React from 'react'; -import { SavedObjectSaveModal, OnSaveProps } from 'ui/saved_objects/components/saved_object_save_modal'; +import React, { useState } from 'react'; +import { + SavedObjectSaveModal, + OnSaveProps, +} from 'ui/saved_objects/components/saved_object_save_modal'; +import { EuiFormRow, EuiTextArea } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +export interface OnSaveGraphProps extends OnSaveProps { + newDescription: string; +} export function GraphSaveModal({ onSave, onClose, title, + description, showCopyOnSave, }: { - onSave: (props: OnSaveProps) => void; + onSave: (props: OnSaveGraphProps) => void; onClose: () => void; title: string; + description: string; showCopyOnSave: boolean; }) { + const [newDescription, setDescription] = useState(description); return ( { + onSave({ ...props, newDescription }); + }} onClose={onClose} title={title} showCopyOnSave={showCopyOnSave} objectType="graph-workspace" - options={null} + options={ + + { + setDescription(e.target.value); + }} + /> + + } /> ); } diff --git a/x-pack/legacy/plugins/graph/public/services/save.tsx b/x-pack/legacy/plugins/graph/public/services/save.tsx index e69de29bb2d1d..9991aa2b9eada 100644 --- a/x-pack/legacy/plugins/graph/public/services/save.tsx +++ b/x-pack/legacy/plugins/graph/public/services/save.tsx @@ -0,0 +1,55 @@ +/* + * 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 React from 'react'; +import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal'; +import { SavedGraphWorkspace } from '../types/persistence'; +import { GraphSaveModal, OnSaveGraphProps } from '../components/graph_save_modal'; + +export function save( + workspace: SavedGraphWorkspace, + saveWorkspace: (saveOptions: { + confirmOverwrite: boolean; + isTitleDuplicateConfirmed: boolean; + onTitleDuplicate: () => void; + }) => Promise<{ id?: string } | { error: string }> +) { + const currentTitle = workspace.title; + const currentDescription = workspace.title; + const onSave = ({ + newTitle, + newDescription, + newCopyOnSave, + isTitleDuplicateConfirmed, + onTitleDuplicate, + }: OnSaveGraphProps) => { + workspace.title = newTitle; + workspace.description = newDescription; + workspace.copyOnSave = newCopyOnSave; + const saveOptions = { + confirmOverwrite: false, + isTitleDuplicateConfirmed, + onTitleDuplicate, + }; + return saveWorkspace(saveOptions).then(response => { + // If the save wasn't successful, put the original values back. + if (!('id' in response) || !Boolean(response.id)) { + workspace.title = currentTitle; + workspace.description = currentDescription; + } + return response; + }); + }; + showSaveModal( + {}} + title={workspace.title} + description={workspace.description} + showCopyOnSave={Boolean(workspace.id)} + /> + ); +} From fab1577c75026bc707ec7a8276c2e40fcc5dfa30 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 28 Aug 2019 16:27:01 +0200 Subject: [PATCH 14/31] add and style save modal --- .../public/angular/directives/graph_save.js | 17 ----- .../graph/public/angular/templates/index.html | 3 +- .../angular/templates/save_workspace.html | 62 ---------------- x-pack/legacy/plugins/graph/public/app.js | 16 ++--- .../public/components/graph_save_modal.scss | 6 ++ .../public/components/graph_save_modal.tsx | 72 +++++++++++++++---- x-pack/legacy/plugins/graph/public/index.scss | 2 + .../plugins/graph/public/services/save.tsx | 32 ++++++--- .../plugins/graph/public/types/config.ts | 7 ++ 9 files changed, 104 insertions(+), 113 deletions(-) delete mode 100644 x-pack/legacy/plugins/graph/public/angular/directives/graph_save.js delete mode 100644 x-pack/legacy/plugins/graph/public/angular/templates/save_workspace.html create mode 100644 x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss create mode 100644 x-pack/legacy/plugins/graph/public/types/config.ts diff --git a/x-pack/legacy/plugins/graph/public/angular/directives/graph_save.js b/x-pack/legacy/plugins/graph/public/angular/directives/graph_save.js deleted file mode 100644 index e8a2889feda24..0000000000000 --- a/x-pack/legacy/plugins/graph/public/angular/directives/graph_save.js +++ /dev/null @@ -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/save_workspace.html'; -const app = uiModules.get('app/graph'); - -app.directive('graphSave', function () { - return { - replace: true, - restrict: 'E', - template, - }; -}); diff --git a/x-pack/legacy/plugins/graph/public/angular/templates/index.html b/x-pack/legacy/plugins/graph/public/angular/templates/index.html index 4dfc1846bb259..5aaa944d45b27 100644 --- a/x-pack/legacy/plugins/graph/public/angular/templates/index.html +++ b/x-pack/legacy/plugins/graph/public/angular/templates/index.html @@ -3,8 +3,7 @@ -
- +
diff --git a/x-pack/legacy/plugins/graph/public/angular/templates/save_workspace.html b/x-pack/legacy/plugins/graph/public/angular/templates/save_workspace.html deleted file mode 100644 index 76c492397b42c..0000000000000 --- a/x-pack/legacy/plugins/graph/public/angular/templates/save_workspace.html +++ /dev/null @@ -1,62 +0,0 @@ -
-
-
- - -
- -
- - -
-
- - {{ ::'xpack.graph.topNavMenu.save.saveConfigurationOnlyWarning' | i18n: { - defaultMessage: 'The data in this workspace will be cleared and only the configuration will be saved', - } }} -
-
- -
- - - -
- - - {{ ::'xpack.graph.topNavMenu.save.saveConfigurationOnlyText' | i18n: { - defaultMessage: 'The data in this workspace will be cleared and only the configuration will be saved', - } }} - -
- -
diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index 2b688e711fd41..d996d69b7f33a 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -60,10 +60,8 @@ import { getOutlinkEncoders, } from './angular/services/outlink_encoders'; -import saveTemplate from './angular/templates/save_workspace.html'; import settingsTemplate from './angular/templates/settings.html'; -import './angular/directives/graph_save'; import './angular/directives/graph_settings'; const app = uiModules.get('app/graph'); @@ -671,7 +669,6 @@ app.controller('graphuiPlugin', function ( $scope.resetWorkspace = function () { $scope.clearWorkspace(); - $scope.userHasConfirmedSaveWorkspaceData = false; $scope.selectedIndex = null; $scope.proposedIndex = null; $scope.detail = null; @@ -895,7 +892,12 @@ app.controller('graphuiPlugin', function ( return $scope.allSavingDisabled || $scope.selectedFields.length === 0; }, run: () => { - save($scope.savedWorkspace, $scope.saveWorkspace); + save({ + savePolicy: $scope.graphSavePolicy, + hasData: $scope.workspace && ($scope.workspace.nodes.length > 0 || $scope.workspace.blacklistedNodes.length > 0), + workspace: $scope.savedWorkspace, + saveWorkspace: $scope.saveWorkspace + }); }, testId: 'graphSaveButton', }); @@ -921,7 +923,6 @@ app.controller('graphuiPlugin', function ( updateBreadcrumbs(); $scope.menus = { - showSave: false, showSettings: false, }; @@ -1083,7 +1084,7 @@ app.controller('graphuiPlugin', function ( }); } - $scope.saveWorkspace = function (saveOptions) { + $scope.saveWorkspace = function (saveOptions, userHasConfirmedSaveWorkspaceData) { if ($scope.allSavingDisabled) { // It should not be possible to navigate to this function if allSavingDisabled is set // but adding check here as a safeguard. @@ -1094,7 +1095,7 @@ app.controller('graphuiPlugin', function ( } initWorkspaceIfRequired(); const canSaveData = $scope.graphSavePolicy === 'configAndData' || - ($scope.graphSavePolicy === 'configAndDataWithConsent' && $scope.userHasConfirmedSaveWorkspaceData); + ($scope.graphSavePolicy === 'configAndDataWithConsent' && userHasConfirmedSaveWorkspaceData); let blacklist = []; @@ -1173,7 +1174,6 @@ app.controller('graphuiPlugin', function ( return $scope.savedWorkspace.save(saveOptions).then(function (id) { $scope.closeMenus(); - $scope.userHasConfirmedSaveWorkspaceData = false; //reset flag if (id) { const title = i18n.translate('xpack.graph.saveWorkspace.successNotificationTitle', { defaultMessage: 'Saved "{workspaceTitle}"', diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss new file mode 100644 index 0000000000000..def32603643a2 --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss @@ -0,0 +1,6 @@ +// Import the EUI global scope so we can use EUI constants +@import 'src/legacy/ui/public/styles/_styling_constants'; + +.gphSaveModal__warning { + width: $euiSizeXXL * 10; +} \ No newline at end of file diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx index 29a606d49ccd4..a6215f7215944 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx +++ b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx @@ -9,11 +9,14 @@ import { SavedObjectSaveModal, OnSaveProps, } from 'ui/saved_objects/components/saved_object_save_modal'; -import { EuiFormRow, EuiTextArea } from '@elastic/eui'; +import { EuiFormRow, EuiTextArea, EuiCallOut, EuiCheckbox, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { GraphSavePolicy } from '../types/config'; + export interface OnSaveGraphProps extends OnSaveProps { newDescription: string; + dataConsent: boolean; } export function GraphSaveModal({ @@ -22,37 +25,76 @@ export function GraphSaveModal({ title, description, showCopyOnSave, + savePolicy, + hasData, }: { onSave: (props: OnSaveGraphProps) => void; onClose: () => void; title: string; description: string; showCopyOnSave: boolean; + savePolicy: GraphSavePolicy; + hasData: boolean; }) { const [newDescription, setDescription] = useState(description); + const [dataConsent, setDataConsent] = useState(false); return ( { - onSave({ ...props, newDescription }); + onSave({ ...props, newDescription, dataConsent }); }} onClose={onClose} title={title} showCopyOnSave={showCopyOnSave} objectType="graph-workspace" options={ - - { - setDescription(e.target.value); - }} - /> - + <> + + { + setDescription(e.target.value); + }} + fullWidth + rows={5} + /> + + {savePolicy === 'configAndDataWithConsent' && hasData && !dataConsent && ( + <> + +

+ {i18n.translate('xpack.graph.topNavMenu.save.saveConfigurationOnlyWarning', { + defaultMessage: + 'The data in this workspace will be cleared and only the configuration will be saved.', + })} +

+
+ + + )} + {savePolicy === 'configAndDataWithConsent' && hasData && ( + { + setDataConsent(e.target.checked); + }} + /> + )} + } /> ); diff --git a/x-pack/legacy/plugins/graph/public/index.scss b/x-pack/legacy/plugins/graph/public/index.scss index 3986f64c6f4c9..236551973ee7a 100644 --- a/x-pack/legacy/plugins/graph/public/index.scss +++ b/x-pack/legacy/plugins/graph/public/index.scss @@ -12,3 +12,5 @@ @import './main'; @import './angular/templates/index'; + +@import './components/graph_save_modal'; \ No newline at end of file diff --git a/x-pack/legacy/plugins/graph/public/services/save.tsx b/x-pack/legacy/plugins/graph/public/services/save.tsx index 9991aa2b9eada..f942a4ba1f746 100644 --- a/x-pack/legacy/plugins/graph/public/services/save.tsx +++ b/x-pack/legacy/plugins/graph/public/services/save.tsx @@ -8,15 +8,26 @@ import React from 'react'; import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal'; import { SavedGraphWorkspace } from '../types/persistence'; import { GraphSaveModal, OnSaveGraphProps } from '../components/graph_save_modal'; +import { GraphSavePolicy } from '../types/config'; -export function save( - workspace: SavedGraphWorkspace, - saveWorkspace: (saveOptions: { - confirmOverwrite: boolean; - isTitleDuplicateConfirmed: boolean; - onTitleDuplicate: () => void; - }) => Promise<{ id?: string } | { error: string }> -) { +export function save({ + savePolicy, + hasData, + workspace, + saveWorkspace, +}: { + savePolicy: GraphSavePolicy; + hasData: boolean; + workspace: SavedGraphWorkspace; + saveWorkspace: ( + saveOptions: { + confirmOverwrite: boolean; + isTitleDuplicateConfirmed: boolean; + onTitleDuplicate: () => void; + }, + dataConsent: boolean + ) => Promise<{ id?: string } | { error: string }>; +}) { const currentTitle = workspace.title; const currentDescription = workspace.title; const onSave = ({ @@ -25,6 +36,7 @@ export function save( newCopyOnSave, isTitleDuplicateConfirmed, onTitleDuplicate, + dataConsent, }: OnSaveGraphProps) => { workspace.title = newTitle; workspace.description = newDescription; @@ -34,7 +46,7 @@ export function save( isTitleDuplicateConfirmed, onTitleDuplicate, }; - return saveWorkspace(saveOptions).then(response => { + return saveWorkspace(saveOptions, dataConsent).then(response => { // If the save wasn't successful, put the original values back. if (!('id' in response) || !Boolean(response.id)) { workspace.title = currentTitle; @@ -45,6 +57,8 @@ export function save( }; showSaveModal( {}} title={workspace.title} diff --git a/x-pack/legacy/plugins/graph/public/types/config.ts b/x-pack/legacy/plugins/graph/public/types/config.ts new file mode 100644 index 0000000000000..eaff11d9d4548 --- /dev/null +++ b/x-pack/legacy/plugins/graph/public/types/config.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export type GraphSavePolicy = 'configAndDataWithConsent' | 'configAndData' | 'config' | 'none'; From a9d31c8cc42c5b426941f85b0d58f0b3ac7a7820 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Wed, 28 Aug 2019 16:44:30 +0200 Subject: [PATCH 15/31] add placeholder to description field --- .../plugins/graph/public/components/graph_save_modal.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx index a6215f7215944..d53f5a64cd73c 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx +++ b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx @@ -58,6 +58,10 @@ export function GraphSaveModal({ { setDescription(e.target.value); }} From d187eae6b22d78d85f4d995f3079af19a322886e Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 29 Aug 2019 10:17:17 +0200 Subject: [PATCH 16/31] disable dirty check on breadcrumb navigation and fix delete function --- x-pack/legacy/plugins/graph/public/app.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index 4b221e7d9ef2e..910bdd13c03c4 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -99,7 +99,7 @@ uiRoutes .when('/home', { template: listingTemplate, badge: getReadonlyBadge, - controller($injector, $location, $scope, $route, Private, config, Promise, kbnBaseUrl) { + controller($injector, $location, $scope, Private, config, Promise, kbnBaseUrl) { checkLicense(Promise, kbnBaseUrl); const services = Private(SavedObjectRegistryProvider).byLoaderPropertiesName; const graphService = services['Graph workspace']; @@ -116,8 +116,8 @@ uiRoutes kbnUrl.redirect(getEditPath(workspace)); }; $scope.getViewUrl = (workspace) => getEditUrl(chrome, workspace); - $scope.delete = (ids) => { - return graphService.delete(ids); + $scope.delete = (workspaces) => { + return graphService.delete(workspaces.map(({ id }) => id)); }; $scope.capabilities = capabilities.get().graph; $scope.initialFilter = ($location.search()).filter || ''; @@ -910,10 +910,11 @@ app.controller('graphuiPlugin', function ( chrome, savedWorkspace: $route.current.locals.savedWorkspace, navigateTo: () => { - canWipeWorkspace(function () { - $scope.$evalAsync(() => { - kbnUrl.changePath('/home/'); - }); + // 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/'); }); } }); From a289d7dd96731b58c7d3f605b71bacfe401ce293 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 29 Aug 2019 15:36:33 +0200 Subject: [PATCH 17/31] improve onClick typing on breadcrumb --- .../core/public/kibana-plugin-public.chromebreadcrumb.md | 2 +- .../public/kibana-plugin-public.chromebreadcrumb.onclick.md | 2 +- src/core/public/chrome/chrome_service.tsx | 4 ++-- src/core/public/public.api.md | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md index f395defd5eecd..330702a45f633 100644 --- a/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md +++ b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.md @@ -17,6 +17,6 @@ export interface ChromeBreadcrumb | --- | --- | --- | | [data-test-subj](./kibana-plugin-public.chromebreadcrumb.data-test-subj.md) | string | | | [href](./kibana-plugin-public.chromebreadcrumb.href.md) | string | | -| [onClick](./kibana-plugin-public.chromebreadcrumb.onclick.md) | () => void | | +| [onClick](./kibana-plugin-public.chromebreadcrumb.onclick.md) | MouseEventHandler<HTMLButtonElement> | | | [text](./kibana-plugin-public.chromebreadcrumb.text.md) | string | | diff --git a/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.onclick.md b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.onclick.md index 806b209b5cb35..1e0ae36e893a1 100644 --- a/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.onclick.md +++ b/docs/development/core/public/kibana-plugin-public.chromebreadcrumb.onclick.md @@ -7,5 +7,5 @@ Signature: ```typescript -onClick?: () => void; +onClick?: MouseEventHandler; ``` diff --git a/src/core/public/chrome/chrome_service.tsx b/src/core/public/chrome/chrome_service.tsx index 24c47abd55c24..d829a27260d27 100644 --- a/src/core/public/chrome/chrome_service.tsx +++ b/src/core/public/chrome/chrome_service.tsx @@ -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,7 +63,7 @@ export interface ChromeBreadcrumb { text: string; href?: string; 'data-test-subj'?: string; - onClick?: () => void; + onClick?: MouseEventHandler; } /** @public */ diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 71260a856ad07..060188608b860 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -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,7 +64,7 @@ export interface ChromeBreadcrumb { // (undocumented) href?: string; // (undocumented) - onClick?: () => void; + onClick?: MouseEventHandler; // (undocumented) text: string; } From be1e59a621d05e5ded2d78cb8d14d539ad176d29 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 29 Aug 2019 15:40:59 +0200 Subject: [PATCH 18/31] fix newline error and use new types in dashboard app controller --- .../kibana/public/dashboard/dashboard_app_controller.tsx | 1 - .../ui/public/saved_objects/show_saved_object_save_modal.tsx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx index 081ad3fa3a95d..802f3cc7bbc09 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx @@ -33,7 +33,6 @@ import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter'; import { docTitle } from 'ui/doc_title/doc_title'; -// @ts-ignore import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal'; import { showShareContextMenu, ShareContextMenuExtensionsRegistryProvider } from 'ui/share'; diff --git a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx index 9c03a3de34d75..4de4978424299 100644 --- a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx +++ b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx @@ -50,4 +50,4 @@ export function showSaveModal(saveModal: React.ReactElement{element}, container); -} \ No newline at end of file +} From c5ac49b5c759b215a9534a95b9a95a719a398702 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Fri, 30 Aug 2019 12:32:00 +0200 Subject: [PATCH 19/31] fix translation errors --- x-pack/legacy/plugins/graph/public/app.js | 2 +- .../public/components/graph_save_modal.scss | 2 +- .../public/components/graph_save_modal.tsx | 17 +++++++++++++++-- .../translations/translations/ja-JP.json | 5 ----- .../translations/translations/zh-CN.json | 5 ----- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index 2eb98ca0477ea..3774a7a410f91 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -876,7 +876,7 @@ app.controller('graphuiPlugin', function ( defaultMessage: 'Save', }), description: i18n.translate('xpack.graph.topNavMenu.saveWorkspace.enabledAriaLabel', { - defaultMessage: 'Save Workspace', + defaultMessage: 'Save workspace', }), tooltip: () => { if ($scope.allSavingDisabled) { diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss index def32603643a2..c9a49bf2e11eb 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss +++ b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss @@ -1,6 +1,6 @@ // Import the EUI global scope so we can use EUI constants @import 'src/legacy/ui/public/styles/_styling_constants'; -.gphSaveModal__warning { +.gphSaveModal__callout { width: $euiSizeXXL * 10; } \ No newline at end of file diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx index d53f5a64cd73c..17157af75e853 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx +++ b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx @@ -51,7 +51,7 @@ export function GraphSaveModal({ <> @@ -74,7 +74,7 @@ export function GraphSaveModal({

{i18n.translate('xpack.graph.topNavMenu.save.saveConfigurationOnlyWarning', { @@ -98,6 +98,19 @@ export function GraphSaveModal({ }} /> )} + {savePolicy === 'config' && hasData && ( + <> + +

+ {i18n.translate('xpack.graph.topNavMenu.save.saveConfigurationOnlyText', { + defaultMessage: + 'The data in this workspace will be cleared and only the configuration will be saved.', + })} +

+
+ + + )} } /> diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 50eff336fcffe..87b8d534ff408 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4643,16 +4643,11 @@ "xpack.graph.topNavMenu.newWorkspaceAriaLabel": "新規ワークスペース", "xpack.graph.topNavMenu.newWorkspaceLabel": "新規", "xpack.graph.topNavMenu.newWorkspaceTooltip": "新規ワークスペースを作成します", - "xpack.graph.topNavMenu.save.confirmButtonAriaLabel": "ワークスペースを保存", - "xpack.graph.topNavMenu.save.confirmButtonLabel": "保存", "xpack.graph.topNavMenu.save.descriptionInputLabel": "説明", "xpack.graph.topNavMenu.save.descriptionInputPlaceholder": "メモ…", - "xpack.graph.topNavMenu.save.nameInputLabel": "名前", - "xpack.graph.topNavMenu.save.nameInputPlaceholder": "グラフワークスペース名", "xpack.graph.topNavMenu.save.saveConfigurationOnlyText": "このワークスペースのデータは消去され、構成のみが保存されます", "xpack.graph.topNavMenu.save.saveConfigurationOnlyWarning": "このワークスペースのデータは消去され、構成のみが保存されます", "xpack.graph.topNavMenu.save.saveGraphContentCheckboxLabel": "Graph コンテンツを保存", - "xpack.graph.topNavMenu.save.saveWorkspaceTitle": "ワークスペースの保存", "xpack.graph.topNavMenu.saveWorkspace.disabledTooltip": "現在の保存ポリシーでは、保存されたワークスペースへの変更が許可されていません", "xpack.graph.topNavMenu.saveWorkspace.enabledAriaLabel": "ワークスペースを保存", "xpack.graph.topNavMenu.saveWorkspace.enabledLabel": "保存", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 1dfb90dd7389c..8f1a00e825ddd 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4786,16 +4786,11 @@ "xpack.graph.topNavMenu.newWorkspaceAriaLabel": "新建工作空间", "xpack.graph.topNavMenu.newWorkspaceLabel": "新建", "xpack.graph.topNavMenu.newWorkspaceTooltip": "新建工作空间", - "xpack.graph.topNavMenu.save.confirmButtonAriaLabel": "保存工作空间", - "xpack.graph.topNavMenu.save.confirmButtonLabel": "保存", "xpack.graph.topNavMenu.save.descriptionInputLabel": "描述", "xpack.graph.topNavMenu.save.descriptionInputPlaceholder": "任何备注......", - "xpack.graph.topNavMenu.save.nameInputLabel": "名称", - "xpack.graph.topNavMenu.save.nameInputPlaceholder": "Graph 工作空间名称", "xpack.graph.topNavMenu.save.saveConfigurationOnlyText": "将清除此工作空间的数据,仅保存配置", "xpack.graph.topNavMenu.save.saveConfigurationOnlyWarning": "将清除此工作空间的数据,仅保存配置", "xpack.graph.topNavMenu.save.saveGraphContentCheckboxLabel": "保存 Graph 内容", - "xpack.graph.topNavMenu.save.saveWorkspaceTitle": "保存工作空间", "xpack.graph.topNavMenu.saveWorkspace.disabledTooltip": "当前保存策略不允许对已保存的工作空间做任何更改", "xpack.graph.topNavMenu.saveWorkspace.enabledAriaLabel": "保存工作空间", "xpack.graph.topNavMenu.saveWorkspace.enabledLabel": "保存", From 8d6cec17e6d7224f778afd334444e7289e7bf6ea Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Fri, 30 Aug 2019 14:54:55 +0200 Subject: [PATCH 20/31] fix i18n translation for real --- .../legacy/plugins/graph/public/components/graph_save_modal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx index 17157af75e853..5421c43256215 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx +++ b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx @@ -51,7 +51,7 @@ export function GraphSaveModal({ <> From 173804acc089f70a5156b4cd98a5cb5fc7a7dd5c Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Mon, 2 Sep 2019 09:39:00 +0200 Subject: [PATCH 21/31] code review --- .../saved_object_save_modal.test.tsx.snap | 7 +-- .../components/saved_object_save_modal.tsx | 61 +++++++++++------- .../public/angular/directives/graph_save.js | 17 ----- .../angular/templates/save_workspace.html | 62 ------------------- x-pack/legacy/plugins/graph/public/app.js | 7 +-- .../public/components/graph_save_modal.scss | 2 +- .../public/components/graph_save_modal.tsx | 60 +++++++++--------- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 9 files changed, 76 insertions(+), 142 deletions(-) delete mode 100644 x-pack/legacy/plugins/graph/public/angular/directives/graph_save.js delete mode 100644 x-pack/legacy/plugins/graph/public/angular/templates/save_workspace.html diff --git a/src/legacy/ui/public/saved_objects/components/__snapshots__/saved_object_save_modal.test.tsx.snap b/src/legacy/ui/public/saved_objects/components/__snapshots__/saved_object_save_modal.test.tsx.snap index aabf9d8d1d1e7..5ac85fc9d32e8 100644 --- a/src/legacy/ui/public/saved_objects/components/__snapshots__/saved_object_save_modal.test.tsx.snap +++ b/src/legacy/ui/public/saved_objects/components/__snapshots__/saved_object_save_modal.test.tsx.snap @@ -6,7 +6,6 @@ exports[`SavedObjectSaveModal should render matching snapshot 1`] = ` onSubmit={[Function]} > - + Save diff --git a/src/legacy/ui/public/saved_objects/components/saved_object_save_modal.tsx b/src/legacy/ui/public/saved_objects/components/saved_object_save_modal.tsx index 05685817bb0da..d62d5226d6e71 100644 --- a/src/legacy/ui/public/saved_objects/components/saved_object_save_modal.tsx +++ b/src/legacy/ui/public/saved_objects/components/saved_object_save_modal.tsx @@ -35,6 +35,7 @@ import { import { FormattedMessage } from '@kbn/i18n/react'; import React, { Fragment } from 'react'; import { EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; export interface OnSaveProps { newTitle: string; @@ -52,6 +53,7 @@ interface Props { confirmButtonLabel?: React.ReactNode; options?: React.ReactNode; description?: string; + className?: string; } interface State { @@ -79,7 +81,7 @@ export class SavedObjectSaveModal extends React.Component {
@@ -136,22 +138,7 @@ export class SavedObjectSaveModal extends React.Component { /> - - {this.props.confirmButtonLabel ? ( - this.props.confirmButtonLabel - ) : ( - - )} - + {this.renderConfirmButton()}
@@ -204,6 +191,34 @@ export class SavedObjectSaveModal extends React.Component { this.saveSavedObject(); }; + private renderConfirmButton = () => { + const { isLoading, title, hasTitleDuplicate } = this.state; + + let confirmLabel: string | React.ReactNode = hasTitleDuplicate + ? i18n.translate('common.ui.savedObjects.saveModal.confirmSaveButtonLabel', { + defaultMessage: 'Confirm save', + }) + : i18n.translate('common.ui.savedObjects.saveModal.saveButtonLabel', { + defaultMessage: 'Save', + }); + + if (this.props.confirmButtonLabel) { + confirmLabel = this.props.confirmButtonLabel; + } + + return ( + + {confirmLabel} + + ); + }; + private renderDuplicateTitleCallout = () => { if (!this.state.hasTitleDuplicate) { return; @@ -230,10 +245,14 @@ export class SavedObjectSaveModal extends React.Component { objectType: this.props.objectType, confirmSaveLabel: ( - + {this.props.confirmButtonLabel + ? this.props.confirmButtonLabel + : i18n.translate( + 'common.ui.savedObjects.saveModal.duplicateTitleDescription.confirmSaveText', + { + defaultMessage: 'Confirm save', + } + )} ), }} diff --git a/x-pack/legacy/plugins/graph/public/angular/directives/graph_save.js b/x-pack/legacy/plugins/graph/public/angular/directives/graph_save.js deleted file mode 100644 index e8a2889feda24..0000000000000 --- a/x-pack/legacy/plugins/graph/public/angular/directives/graph_save.js +++ /dev/null @@ -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/save_workspace.html'; -const app = uiModules.get('app/graph'); - -app.directive('graphSave', function () { - return { - replace: true, - restrict: 'E', - template, - }; -}); diff --git a/x-pack/legacy/plugins/graph/public/angular/templates/save_workspace.html b/x-pack/legacy/plugins/graph/public/angular/templates/save_workspace.html deleted file mode 100644 index 76c492397b42c..0000000000000 --- a/x-pack/legacy/plugins/graph/public/angular/templates/save_workspace.html +++ /dev/null @@ -1,62 +0,0 @@ -
-
-
- - -
- -
- - -
-
- - {{ ::'xpack.graph.topNavMenu.save.saveConfigurationOnlyWarning' | i18n: { - defaultMessage: 'The data in this workspace will be cleared and only the configuration will be saved', - } }} -
-
- -
- - - -
- - - {{ ::'xpack.graph.topNavMenu.save.saveConfigurationOnlyText' | i18n: { - defaultMessage: 'The data in this workspace will be cleared and only the configuration will be saved', - } }} - -
- -
diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index e43e451050d6c..4dc7faaff4771 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -61,7 +61,6 @@ import { save } from './services/save'; import settingsTemplate from './angular/templates/settings.html'; -import './angular/directives/graph_save'; import './angular/directives/graph_settings'; const app = uiModules.get('app/graph'); @@ -1174,7 +1173,6 @@ app.controller('graphuiPlugin', function ( $scope.savedWorkspace.numLinks = links.length; return $scope.savedWorkspace.save(saveOptions).then(function (id) { - $scope.closeMenus(); if (id) { const title = i18n.translate('xpack.graph.saveWorkspace.successNotificationTitle', { defaultMessage: 'Saved "{workspaceTitle}"', @@ -1192,8 +1190,9 @@ app.controller('graphuiPlugin', function ( text, 'data-test-subj': 'saveGraphSuccess', }); - if ($scope.savedWorkspace.id === $route.current.params.id) return; - kbnUrl.change(getEditPath($scope.savedWorkspace)); + if ($scope.savedWorkspace.id !== $route.current.params.id) { + kbnUrl.change(getEditPath($scope.savedWorkspace)); + } } return { id }; }, fatalError); diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss index c9a49bf2e11eb..334f9b6826732 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss +++ b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss @@ -1,6 +1,6 @@ // Import the EUI global scope so we can use EUI constants @import 'src/legacy/ui/public/styles/_styling_constants'; -.gphSaveModal__callout { +.gphSaveModal { width: $euiSizeXXL * 10; } \ No newline at end of file diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx index 5421c43256215..47c84ea169cd5 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx +++ b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx @@ -9,7 +9,14 @@ import { SavedObjectSaveModal, OnSaveProps, } from 'ui/saved_objects/components/saved_object_save_modal'; -import { EuiFormRow, EuiTextArea, EuiCallOut, EuiCheckbox, EuiSpacer } from '@elastic/eui'; +import { + EuiFormRow, + EuiTextArea, + EuiCallOut, + EuiCheckbox, + EuiSpacer, + EuiSwitch, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { GraphSavePolicy } from '../types/config'; @@ -46,7 +53,10 @@ export function GraphSaveModal({ onClose={onClose} title={title} showCopyOnSave={showCopyOnSave} - objectType="graph-workspace" + objectType={i18n.translate('xpack.graph.topNavMenu.save.objectType', { + defaultMessage: 'workspace', + })} + className="gphSaveModal" options={ <> - {savePolicy === 'configAndDataWithConsent' && hasData && !dataConsent && ( - <> - -

- {i18n.translate('xpack.graph.topNavMenu.save.saveConfigurationOnlyWarning', { - defaultMessage: - 'The data in this workspace will be cleared and only the configuration will be saved.', - })} -

-
- - - )} {savePolicy === 'configAndDataWithConsent' && hasData && ( - { - setDataConsent(e.target.checked); - }} - /> + > + { + setDataConsent(e.target.checked); + }} + /> +
)} {savePolicy === 'config' && hasData && ( <> - +

{i18n.translate('xpack.graph.topNavMenu.save.saveConfigurationOnlyText', { defaultMessage: diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index f273735f56d1c..2818bc115de72 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4646,7 +4646,6 @@ "xpack.graph.topNavMenu.save.descriptionInputLabel": "説明", "xpack.graph.topNavMenu.save.descriptionInputPlaceholder": "メモ…", "xpack.graph.topNavMenu.save.saveConfigurationOnlyText": "このワークスペースのデータは消去され、構成のみが保存されます", - "xpack.graph.topNavMenu.save.saveConfigurationOnlyWarning": "このワークスペースのデータは消去され、構成のみが保存されます", "xpack.graph.topNavMenu.save.saveGraphContentCheckboxLabel": "Graph コンテンツを保存", "xpack.graph.topNavMenu.saveWorkspace.disabledTooltip": "現在の保存ポリシーでは、保存されたワークスペースへの変更が許可されていません", "xpack.graph.topNavMenu.saveWorkspace.enabledAriaLabel": "ワークスペースを保存", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 465a3fac4730e..34398a96858c3 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4789,7 +4789,6 @@ "xpack.graph.topNavMenu.save.descriptionInputLabel": "描述", "xpack.graph.topNavMenu.save.descriptionInputPlaceholder": "任何备注......", "xpack.graph.topNavMenu.save.saveConfigurationOnlyText": "将清除此工作空间的数据,仅保存配置", - "xpack.graph.topNavMenu.save.saveConfigurationOnlyWarning": "将清除此工作空间的数据,仅保存配置", "xpack.graph.topNavMenu.save.saveGraphContentCheckboxLabel": "保存 Graph 内容", "xpack.graph.topNavMenu.saveWorkspace.disabledTooltip": "当前保存策略不允许对已保存的工作空间做任何更改", "xpack.graph.topNavMenu.saveWorkspace.enabledAriaLabel": "保存工作空间", From 6f1bbcac4b6c91fe311a639b4600f9fb0e0e9735 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Mon, 2 Sep 2019 10:21:07 +0200 Subject: [PATCH 22/31] fix i18n phrases --- .../saved_objects/saved_object_save_modal.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx b/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx index a19b71d035faf..88a07e2492fbf 100644 --- a/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx +++ b/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx @@ -87,7 +87,7 @@ export class SavedObjectSaveModal extends React.Component { @@ -109,7 +109,7 @@ export class SavedObjectSaveModal extends React.Component { fullWidth label={ } @@ -133,7 +133,7 @@ export class SavedObjectSaveModal extends React.Component { @@ -195,10 +195,10 @@ export class SavedObjectSaveModal extends React.Component { const { isLoading, title, hasTitleDuplicate } = this.state; let confirmLabel: string | React.ReactNode = hasTitleDuplicate - ? i18n.translate('common.ui.savedObjects.saveModal.confirmSaveButtonLabel', { + ? i18n.translate('kibana-react.savedObjects.saveModal.confirmSaveButtonLabel', { defaultMessage: 'Confirm save', }) - : i18n.translate('common.ui.savedObjects.saveModal.saveButtonLabel', { + : i18n.translate('kibana-react.savedObjects.saveModal.saveButtonLabel', { defaultMessage: 'Save', }); @@ -229,7 +229,7 @@ export class SavedObjectSaveModal extends React.Component { @@ -239,7 +239,7 @@ export class SavedObjectSaveModal extends React.Component { >

{ {this.props.confirmButtonLabel ? this.props.confirmButtonLabel : i18n.translate( - 'common.ui.savedObjects.saveModal.duplicateTitleDescription.confirmSaveText', + 'kibana-react.savedObjects.saveModal.duplicateTitleDescription.confirmSaveText', { defaultMessage: 'Confirm save', } @@ -277,7 +277,7 @@ export class SavedObjectSaveModal extends React.Component { onChange={this.onCopyOnSaveChange} label={ From 7c94337dffc7c53cdcf7ca3f263a569d8cc82546 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Mon, 2 Sep 2019 10:30:50 +0200 Subject: [PATCH 23/31] remove fragments --- .../public/saved_objects/saved_object_save_modal.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx b/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx index 88a07e2492fbf..ffc2aadc482f8 100644 --- a/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx +++ b/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx @@ -33,7 +33,7 @@ import { EuiSwitch, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import React, { Fragment } from 'react'; +import React from 'react'; import { EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -225,7 +225,7 @@ export class SavedObjectSaveModal extends React.Component { } return ( - + <> {

- + ); }; @@ -270,7 +270,7 @@ export class SavedObjectSaveModal extends React.Component { } return ( - + <> { } /> - + ); }; } From bcc280f94640b81a453cb719646c0710a7e3b768 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 5 Sep 2019 09:34:44 +0200 Subject: [PATCH 24/31] remove unnecessary max-width and add commentary --- .../saved_objects/show_saved_object_save_modal.tsx | 11 ++++++++++- .../public/saved_objects/saved_object_save_modal.tsx | 3 +-- .../graph/public/components/graph_save_modal.scss | 6 ------ .../graph/public/components/graph_save_modal.tsx | 1 - x-pack/legacy/plugins/graph/public/index.scss | 2 -- 5 files changed, 11 insertions(+), 12 deletions(-) delete mode 100644 x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss diff --git a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx index 4de4978424299..e09645e29910e 100644 --- a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx +++ b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx @@ -21,8 +21,17 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { I18nContext } from 'ui/i18n'; +/** + * Represents the result of trying to persist the saved object. + * Contains `error` prop if something unexpected happened (e.g. network error). + * Contains an `id` if persisting was successful. If `id` and + * `error` are undefined, persisting was not successful, but the + * modal can still recover (e.g. the name of the saved object was already taken). + */ +type SaveResult = { id?: string } | { error: Error }; + interface MinimalSaveModalProps { - onSave: (...args: any[]) => Promise<{ id?: string } | { error: Error }>; + onSave: (...args: any[]) => Promise; onClose: () => void; } diff --git a/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx b/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx index ffc2aadc482f8..8a345ae2b30b1 100644 --- a/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx +++ b/src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.tsx @@ -53,7 +53,6 @@ interface Props { confirmButtonLabel?: React.ReactNode; options?: React.ReactNode; description?: string; - className?: string; } interface State { @@ -81,7 +80,7 @@ export class SavedObjectSaveModal extends React.Component {
diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss deleted file mode 100644 index 334f9b6826732..0000000000000 --- a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.scss +++ /dev/null @@ -1,6 +0,0 @@ -// Import the EUI global scope so we can use EUI constants -@import 'src/legacy/ui/public/styles/_styling_constants'; - -.gphSaveModal { - width: $euiSizeXXL * 10; -} \ No newline at end of file diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx index c83915ba5853c..11388ae1f45fc 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx +++ b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx @@ -49,7 +49,6 @@ export function GraphSaveModal({ objectType={i18n.translate('xpack.graph.topNavMenu.save.objectType', { defaultMessage: 'workspace', })} - className="gphSaveModal" options={ <> Date: Thu, 5 Sep 2019 09:35:39 +0200 Subject: [PATCH 25/31] move to async syntax --- .../saved_objects/show_saved_object_save_modal.tsx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx index e09645e29910e..5e25daa0b2f49 100644 --- a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx +++ b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx @@ -44,13 +44,12 @@ export function showSaveModal(saveModal: React.ReactElement { - return onSave(...args).then(response => { - if (('id' in response && response.id) || 'error' in response) { - closeModal(); - } - return response; - }); + const onSaveConfirmed: MinimalSaveModalProps['onSave'] = async (...args) => { + const response = await onSave(...args); + if (('id' in response && response.id) || 'error' in response) { + closeModal(); + } + return response; }; document.body.appendChild(container); const element = React.cloneElement(saveModal, { From 4897b522be09d3ffc3fd91a44590bcca9ecef45a Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 5 Sep 2019 09:38:42 +0200 Subject: [PATCH 26/31] clean up implementation --- .../visualize/embeddable/visualize_embeddable_factory.tsx | 4 ---- .../ui/public/saved_objects/show_saved_object_save_modal.tsx | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx index a77baef960af1..a370a7c409fcb 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx +++ b/src/legacy/core_plugins/kibana/public/visualize/embeddable/visualize_embeddable_factory.tsx @@ -41,10 +41,6 @@ import 'uiExports/visualize'; import { i18n } from '@kbn/i18n'; import { capabilities } from 'ui/capabilities'; -// @ts-ignore -import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal'; -// @ts-ignore -import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal'; import chrome from 'ui/chrome'; import { getVisualizeLoader } from 'ui/visualize/loader'; diff --git a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx index 5e25daa0b2f49..6c42ba4c1f8cb 100644 --- a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx +++ b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx @@ -46,7 +46,7 @@ export function showSaveModal(saveModal: React.ReactElement { const response = await onSave(...args); - if (('id' in response && response.id) || 'error' in response) { + if (('id' in response && response.id) || ('error' in response && response.error)) { closeModal(); } return response; From 7b2b91be2fef99b95f6c2b244581d4df189fc878 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 5 Sep 2019 09:40:16 +0200 Subject: [PATCH 27/31] use description instead of title --- x-pack/legacy/plugins/graph/public/services/save.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/legacy/plugins/graph/public/services/save.tsx b/x-pack/legacy/plugins/graph/public/services/save.tsx index f942a4ba1f746..4903fb4913a3f 100644 --- a/x-pack/legacy/plugins/graph/public/services/save.tsx +++ b/x-pack/legacy/plugins/graph/public/services/save.tsx @@ -29,7 +29,7 @@ export function save({ ) => Promise<{ id?: string } | { error: string }>; }) { const currentTitle = workspace.title; - const currentDescription = workspace.title; + const currentDescription = workspace.description; const onSave = ({ newTitle, newDescription, From e4b9aa0c13db5433f9c50b6a4ac15830961d0c6f Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 5 Sep 2019 10:46:18 +0200 Subject: [PATCH 28/31] fix snapshot --- .../__snapshots__/saved_object_save_modal.test.tsx.snap | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap b/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap index 1d302fff169a3..0072091ee5cb7 100644 --- a/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap +++ b/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap @@ -6,6 +6,7 @@ exports[`SavedObjectSaveModal should render matching snapshot 1`] = ` onSubmit={[Function]} > Date: Thu, 5 Sep 2019 15:39:04 +0200 Subject: [PATCH 29/31] adress review comments and set width for all save modals --- src/legacy/ui/public/_index.scss | 1 + src/legacy/ui/public/saved_objects/_index.scss | 1 + .../public/saved_objects/show_saved_object_save_modal.tsx | 7 ++++++- .../__snapshots__/saved_object_save_modal.test.tsx.snap | 2 +- src/plugins/kibana_react/public/saved_objects/_index.scss | 1 + .../public/saved_objects/saved_object_save_modal.scss | 3 +++ .../public/saved_objects/saved_object_save_modal.tsx | 2 +- .../plugins/graph/public/components/graph_save_modal.tsx | 4 ---- x-pack/plugins/translations/translations/ja-JP.json | 1 - x-pack/plugins/translations/translations/zh-CN.json | 1 - 10 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 src/legacy/ui/public/saved_objects/_index.scss create mode 100644 src/plugins/kibana_react/public/saved_objects/_index.scss create mode 100644 src/plugins/kibana_react/public/saved_objects/saved_object_save_modal.scss diff --git a/src/legacy/ui/public/_index.scss b/src/legacy/ui/public/_index.scss index 1c3a9c006acfd..e7d85b8cc3f8e 100644 --- a/src/legacy/ui/public/_index.scss +++ b/src/legacy/ui/public/_index.scss @@ -19,6 +19,7 @@ @import './exit_full_screen/index'; @import './field_editor/index'; @import './notify/index'; +@import './saved_objects/index'; @import './share/index'; @import './style_compile/index'; diff --git a/src/legacy/ui/public/saved_objects/_index.scss b/src/legacy/ui/public/saved_objects/_index.scss new file mode 100644 index 0000000000000..50a192b6a7b17 --- /dev/null +++ b/src/legacy/ui/public/saved_objects/_index.scss @@ -0,0 +1 @@ +@import '../../../../plugins/kibana_react/public/saved_objects/index'; diff --git a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx index 6c42ba4c1f8cb..5afda98408c61 100644 --- a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx +++ b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx @@ -30,6 +30,10 @@ import { I18nContext } from 'ui/i18n'; */ type SaveResult = { id?: string } | { error: Error }; +function isError(result: SaveResult): result is { error: Error } { + return 'error' in result; +} + interface MinimalSaveModalProps { onSave: (...args: any[]) => Promise; onClose: () => void; @@ -46,7 +50,8 @@ export function showSaveModal(saveModal: React.ReactElement { const response = await onSave(...args); - if (('id' in response && response.id) || ('error' in response && response.error)) { + // close modal if we either hit an error or the saved object got an id + if (Boolean(isError(response) ? response.error : response.id)) { closeModal(); } return response; diff --git a/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap b/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap index 0072091ee5cb7..edb3cc4ec3d10 100644 --- a/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap +++ b/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap @@ -6,7 +6,7 @@ exports[`SavedObjectSaveModal should render matching snapshot 1`] = ` onSubmit={[Function]} > { diff --git a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx index 11388ae1f45fc..654cf473fb03e 100644 --- a/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx +++ b/x-pack/legacy/plugins/graph/public/components/graph_save_modal.tsx @@ -60,10 +60,6 @@ export function GraphSaveModal({ { setDescription(e.target.value); }} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index d142379f98e0b..72f3cfeb23fe0 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4642,7 +4642,6 @@ "xpack.graph.topNavMenu.newWorkspaceLabel": "新規", "xpack.graph.topNavMenu.newWorkspaceTooltip": "新規ワークスペースを作成します", "xpack.graph.topNavMenu.save.descriptionInputLabel": "説明", - "xpack.graph.topNavMenu.save.descriptionInputPlaceholder": "メモ…", "xpack.graph.topNavMenu.save.saveConfigurationOnlyText": "このワークスペースのデータは消去され、構成のみが保存されます", "xpack.graph.topNavMenu.save.saveGraphContentCheckboxLabel": "Graph コンテンツを保存", "xpack.graph.topNavMenu.saveWorkspace.disabledTooltip": "現在の保存ポリシーでは、保存されたワークスペースへの変更が許可されていません", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index ac7ff3e2bc4a9..2a7c7daa6d120 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4785,7 +4785,6 @@ "xpack.graph.topNavMenu.newWorkspaceLabel": "新建", "xpack.graph.topNavMenu.newWorkspaceTooltip": "新建工作空间", "xpack.graph.topNavMenu.save.descriptionInputLabel": "描述", - "xpack.graph.topNavMenu.save.descriptionInputPlaceholder": "任何备注......", "xpack.graph.topNavMenu.save.saveConfigurationOnlyText": "将清除此工作空间的数据,仅保存配置", "xpack.graph.topNavMenu.save.saveGraphContentCheckboxLabel": "保存 Graph 内容", "xpack.graph.topNavMenu.saveWorkspace.disabledTooltip": "当前保存策略不允许对已保存的工作空间做任何更改", From 372f3b461fc0ee36a3d062df02f73cabc17ddf05 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 5 Sep 2019 17:11:27 +0200 Subject: [PATCH 30/31] fix bug and improve typing --- .../kibana/public/dashboard/dashboard_app_controller.tsx | 6 +++--- .../public/saved_objects/show_saved_object_save_modal.tsx | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx index 802f3cc7bbc09..5b4a4c99d403a 100644 --- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx +++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_app_controller.tsx @@ -33,7 +33,7 @@ import { FilterBarQueryFilterProvider } from 'ui/filter_manager/query_filter'; import { docTitle } from 'ui/doc_title/doc_title'; -import { showSaveModal } from 'ui/saved_objects/show_saved_object_save_modal'; +import { showSaveModal, SaveResult } from 'ui/saved_objects/show_saved_object_save_modal'; import { showShareContextMenu, ShareContextMenuExtensionsRegistryProvider } from 'ui/share'; import { migrateLegacyQuery } from 'ui/utils/migrate_legacy_query'; @@ -603,7 +603,7 @@ export class DashboardAppController { * @return {Promise} * @resolved {String} - The id of the doc */ - function save(saveOptions: SaveOptions): Promise<{ id?: string } | { error: Error }> { + function save(saveOptions: SaveOptions): Promise { return saveDashboard(angular.toJson, timefilter, dashboardStateManager, saveOptions) .then(function(id) { if (id) { @@ -694,7 +694,7 @@ export class DashboardAppController { isTitleDuplicateConfirmed, onTitleDuplicate, }; - return save(saveOptions).then((response: { id?: string } | { error: Error }) => { + return save(saveOptions).then((response: SaveResult) => { // If the save wasn't successful, put the original values back. if (!(response as { id: string }).id) { dashboardStateManager.setTitle(currentTitle); diff --git a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx index 5afda98408c61..6aea3c72e0c34 100644 --- a/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx +++ b/src/legacy/ui/public/saved_objects/show_saved_object_save_modal.tsx @@ -28,10 +28,10 @@ import { I18nContext } from 'ui/i18n'; * `error` are undefined, persisting was not successful, but the * modal can still recover (e.g. the name of the saved object was already taken). */ -type SaveResult = { id?: string } | { error: Error }; +export type SaveResult = { id?: string } | { error: Error }; -function isError(result: SaveResult): result is { error: Error } { - return 'error' in result; +function isSuccess(result: SaveResult): result is { id?: string } { + return 'id' in result; } interface MinimalSaveModalProps { @@ -51,7 +51,7 @@ export function showSaveModal(saveModal: React.ReactElement { const response = await onSave(...args); // close modal if we either hit an error or the saved object got an id - if (Boolean(isError(response) ? response.error : response.id)) { + if (Boolean(isSuccess(response) ? response.id : response.error)) { closeModal(); } return response; From 3de7e4fe603b5727d03aa4968378c6b152fd5976 Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Thu, 5 Sep 2019 17:19:30 +0200 Subject: [PATCH 31/31] fix classname --- .../__snapshots__/saved_object_save_modal.test.tsx.snap | 2 +- .../public/saved_objects/saved_object_save_modal.scss | 2 +- .../public/saved_objects/saved_object_save_modal.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap b/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap index edb3cc4ec3d10..5bf5c8be05ed8 100644 --- a/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap +++ b/src/plugins/kibana_react/public/saved_objects/__snapshots__/saved_object_save_modal.test.tsx.snap @@ -6,7 +6,7 @@ exports[`SavedObjectSaveModal should render matching snapshot 1`] = ` onSubmit={[Function]} > {