From c5bf708c55ef2a360e1b30178bce89089009527d Mon Sep 17 00:00:00 2001
From: Maja Grubic
Date: Thu, 12 Dec 2019 16:07:25 +0000
Subject: [PATCH] [Dashboard] Add visualization from dasbhoard empty screen
(#52670)
* [Dashboard] Add visualization from dasbhoard empty screen
* Fixing linting errors
* Fixing i18n error
* Fixing unit test that was causing typecheck failure
---
.../dashboard_empty_screen.test.tsx.snap | 74 ++-
.../__tests__/dashboard_empty_screen.test.tsx | 11 +
.../dashboard/dashboard_app_controller.tsx | 33 +-
.../dashboard/dashboard_empty_screen.tsx | 32 +-
.../dashboard_empty_screen_constants.tsx | 6 +
.../__snapshots__/new_vis_modal.test.tsx.snap | 628 +++++++++++++++++-
.../visualize/wizard/new_vis_modal.test.tsx | 31 +
.../public/visualize/wizard/new_vis_modal.tsx | 6 +-
.../embeddable/grid/_dashboard_grid.scss | 2 +-
.../viewport/_dashboard_viewport.scss | 1 -
.../apps/dashboard/empty_dashboard.js | 8 +
.../services/dashboard/visualizations.js | 8 +-
12 files changed, 773 insertions(+), 67 deletions(-)
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/__snapshots__/dashboard_empty_screen.test.tsx.snap b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/__snapshots__/dashboard_empty_screen.test.tsx.snap
index 8410040a0100d..4ea658bcd03ef 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/__snapshots__/dashboard_empty_screen.test.tsx.snap
+++ b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/__snapshots__/dashboard_empty_screen.test.tsx.snap
@@ -306,40 +306,56 @@ exports[`DashboardEmptyScreen renders correctly with visualize paragraph 1`] = `
className="euiSpacer euiSpacer--m"
/>
-
-
-
-
- visit the Visualize app
- ,
- }
- }
+
-
-
-
+
+
+
+
+
+ Create new
+
+
+
+
+
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/dashboard_empty_screen.test.tsx b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/dashboard_empty_screen.test.tsx
index 69bdcf59bb227..653e7d4215eef 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/__tests__/dashboard_empty_screen.test.tsx
+++ b/src/legacy/core_plugins/kibana/public/dashboard/__tests__/dashboard_empty_screen.test.tsx
@@ -47,4 +47,15 @@ describe('DashboardEmptyScreen', () => {
const paragraph = findTestSubject(component, 'linkToVisualizeParagraph');
expect(paragraph.length).toBe(0);
});
+
+ test('when specified, prop onVisualizeClick is called correctly', () => {
+ const onVisualizeClick = jest.fn();
+ const component = mountComponent({
+ ...defaultProps,
+ ...{ showLinkToVisualize: true, onVisualizeClick },
+ });
+ const button = findTestSubject(component, 'addVisualizationButton');
+ button.simulate('click');
+ expect(onVisualizeClick).toHaveBeenCalled();
+ });
});
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 fd49b26e0d948..d8496ebb5cdbc 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
@@ -21,7 +21,7 @@ import _ from 'lodash';
import { i18n } from '@kbn/i18n';
import React from 'react';
import angular from 'angular';
-import { uniq, noop } from 'lodash';
+import { uniq } from 'lodash';
import { Subscription } from 'rxjs';
import { DashboardEmptyScreen, DashboardEmptyScreenProps } from './dashboard_empty_screen';
@@ -53,6 +53,7 @@ import {
ErrorEmbeddable,
ViewMode,
openAddPanelFlyout,
+ EmbeddableFactoryNotFoundError,
} from '../../../embeddable_api/public/np_ready/public';
import { DashboardAppState, NavAction, ConfirmModalFn, SavedDashboardPanel } from './types';
@@ -145,16 +146,20 @@ export class DashboardAppController {
}
$scope.showSaveQuery = dashboardCapabilities.saveQuery as boolean;
- $scope.getShouldShowEditHelp = () =>
+ const getShouldShowEditHelp = () =>
!dashboardStateManager.getPanels().length &&
dashboardStateManager.getIsEditMode() &&
!dashboardConfig.getHideWriteControls();
- $scope.getShouldShowViewHelp = () =>
+ const getShouldShowViewHelp = () =>
!dashboardStateManager.getPanels().length &&
dashboardStateManager.getIsViewMode() &&
!dashboardConfig.getHideWriteControls();
+ const addVisualization = () => {
+ navActions[TopNavIds.VISUALIZE]();
+ };
+
const updateIndexPatterns = (container?: DashboardContainer) => {
if (!container || isErrorEmbeddable(container)) {
return;
@@ -189,7 +194,7 @@ export class DashboardAppController {
showLinkToVisualize: shouldShowEditHelp,
};
if (shouldShowEditHelp) {
- emptyScreenProps.onVisualizeClick = noop;
+ emptyScreenProps.onVisualizeClick = addVisualization;
}
return emptyScreenProps;
};
@@ -205,8 +210,8 @@ export class DashboardAppController {
if (dashboardContainer && !isErrorEmbeddable(dashboardContainer)) {
expandedPanelId = dashboardContainer.getInput().expandedPanelId;
}
- const shouldShowEditHelp = $scope.getShouldShowEditHelp();
- const shouldShowViewHelp = $scope.getShouldShowViewHelp();
+ const shouldShowEditHelp = getShouldShowEditHelp();
+ const shouldShowViewHelp = getShouldShowViewHelp();
return {
id: dashboardStateManager.savedDashboard.id || '',
filters: queryFilter.getFilters(),
@@ -261,8 +266,8 @@ export class DashboardAppController {
dashboardContainer = container;
dashboardContainer.renderEmpty = () => {
- const shouldShowEditHelp = $scope.getShouldShowEditHelp();
- const shouldShowViewHelp = $scope.getShouldShowViewHelp();
+ const shouldShowEditHelp = getShouldShowEditHelp();
+ const shouldShowViewHelp = getShouldShowViewHelp();
const isEmptyState = shouldShowEditHelp || shouldShowViewHelp;
return isEmptyState ? (
@@ -759,7 +764,17 @@ export class DashboardAppController {
}
};
- navActions[TopNavIds.VISUALIZE] = async () => {};
+ navActions[TopNavIds.VISUALIZE] = async () => {
+ const type = 'visualization';
+ const factory = embeddables.getEmbeddableFactory(type);
+ if (!factory) {
+ throw new EmbeddableFactoryNotFoundError(type);
+ }
+ const explicitInput = await factory.getExplicitInput();
+ if (dashboardContainer) {
+ await dashboardContainer.addNewEmbeddable(type, explicitInput);
+ }
+ };
navActions[TopNavIds.OPTIONS] = anchorElement => {
showOptionsPopover({
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_empty_screen.tsx b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_empty_screen.tsx
index 234228ba4166a..2fc78d64d0a0c 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_empty_screen.tsx
+++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_empty_screen.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
import React from 'react';
-import { I18nProvider, FormattedMessage } from '@kbn/i18n/react';
+import { I18nProvider } from '@kbn/i18n/react';
import {
EuiIcon,
EuiLink,
@@ -26,6 +26,7 @@ import {
EuiPageBody,
EuiPage,
EuiText,
+ EuiButton,
} from '@elastic/eui';
import * as constants from './dashboard_empty_screen_constants';
@@ -38,23 +39,20 @@ export interface DashboardEmptyScreenProps {
export function DashboardEmptyScreen({
showLinkToVisualize,
onLinkClick,
+ onVisualizeClick,
}: DashboardEmptyScreenProps) {
const linkToVisualizeParagraph = (
-
-
-
- {constants.visualizeAppLinkTest}
-
- ),
- }}
- />
-
-
+
+
+ {constants.createNewVisualizationButton}
+
+
);
const paragraph = (
description1: string,
@@ -96,7 +94,7 @@ export function DashboardEmptyScreen({
);
return (
-
+
diff --git a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_empty_screen_constants.tsx b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_empty_screen_constants.tsx
index 0f510375aaf59..03004f6270fef 100644
--- a/src/legacy/core_plugins/kibana/public/dashboard/dashboard_empty_screen_constants.tsx
+++ b/src/legacy/core_plugins/kibana/public/dashboard/dashboard_empty_screen_constants.tsx
@@ -76,3 +76,9 @@ export const visualizeAppLinkTest: string = i18n.translate(
defaultMessage: 'visit the Visualize app',
}
);
+export const createNewVisualizationButton: string = i18n.translate(
+ 'kbn.dashboard.createNewVisualizationButton',
+ {
+ defaultMessage: 'Create new',
+ }
+);
diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap
index 04b7cddc75289..ca6b872c73f8f 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap
+++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/__snapshots__/new_vis_modal.test.tsx.snap
@@ -242,13 +242,70 @@ exports[`NewVisModal filter for visualization types should render as expected 1`
aria-live="polite"
class="euiScreenReaderOnly"
>
- 1 type found
+ 2 types found
+
+
+ Vis with alias Url
+
+ }
+ onBlur={[Function]}
+ onClick={[Function]}
+ onFocus={[Function]}
+ onMouseEnter={[Function]}
+ onMouseLeave={[Function]}
+ role="menuitem"
+ >
+
+
{
+ const { location } = window;
const defaultVisTypeParams = {
hidden: false,
visualization: class Controller {
@@ -51,6 +52,12 @@ describe('NewVisModal', () => {
stage: 'production',
...defaultVisTypeParams,
},
+ {
+ name: 'visWithAliasUrl',
+ title: 'Vis with alias Url',
+ stage: 'production',
+ aliasUrl: '/aliasUrl',
+ },
];
const visTypes: TypesStart = {
get: (id: string) => {
@@ -69,6 +76,10 @@ describe('NewVisModal', () => {
jest.clearAllMocks();
});
+ afterAll(() => {
+ window.location = location;
+ });
+
it('should render as expected', () => {
const wrapper = mountWithIntl(
{
visButton.simulate('click');
expect(window.location.assign).toBeCalledWith('#/visualize/create?type=vis&foo=true&bar=42');
});
+
+ it('closes if visualization with aliasUrl and addToDashboard in editorParams', () => {
+ const onClose = jest.fn();
+ window.location.assign = jest.fn();
+ const wrapper = mountWithIntl(
+
+ );
+ const visButton = wrapper.find('button[data-test-subj="visType-visWithAliasUrl"]');
+ visButton.simulate('click');
+ expect(window.location.assign).toBeCalledWith('testbasepath/aliasUrl');
+ expect(onClose).toHaveBeenCalled();
+ });
});
describe('filter for visualization types', () => {
diff --git a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx
index 0402265610fb1..e84797302589d 100644
--- a/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx
+++ b/src/legacy/core_plugins/kibana/public/visualize/wizard/new_vis_modal.tsx
@@ -132,8 +132,10 @@ class NewVisModal extends React.Component {
@@ -54,6 +56,12 @@ export default function ({ getService, getPageObjects }) {
expect(isAddPanelOpen).to.be(true);
});
+ it('should add new visualization from dashboard', async () => {
+ await testSubjects.click('addVisualizationButton');
+ await dashboardVisualizations.createAndAddMarkdown({ name: 'Dashboard Test Markdown', markdown: 'Markdown text' }, false);
+ await PageObjects.dashboard.waitForRenderComplete();
+ await dashboardExpect.markdownWithValuesExists(['Markdown text']);
+ });
});
}
diff --git a/test/functional/services/dashboard/visualizations.js b/test/functional/services/dashboard/visualizations.js
index 8cde98861ca88..97433a1e4923c 100644
--- a/test/functional/services/dashboard/visualizations.js
+++ b/test/functional/services/dashboard/visualizations.js
@@ -73,14 +73,16 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }) {
await dashboardAddPanel.addSavedSearch(name);
}
- async createAndAddMarkdown({ name, markdown }) {
+ async createAndAddMarkdown({ name, markdown }, checkForAddPanel = true) {
log.debug(`createAndAddMarkdown(${markdown})`);
const inViewMode = await PageObjects.dashboard.getIsInViewMode();
if (inViewMode) {
await PageObjects.dashboard.switchToEditMode();
}
- await dashboardAddPanel.ensureAddPanelIsShowing();
- await dashboardAddPanel.clickAddNewEmbeddableLink('visualization');
+ if (checkForAddPanel) {
+ await dashboardAddPanel.ensureAddPanelIsShowing();
+ await dashboardAddPanel.clickAddNewEmbeddableLink('visualization');
+ }
await PageObjects.visualize.clickMarkdownWidget();
await PageObjects.visualize.setMarkdownTxt(markdown);
await PageObjects.visualize.clickGo();