Skip to content

Commit 1b76123

Browse files
author
Maja Grubic
committed
[Dashboard] Add visualization by value to dashboard (#69898)
* Plugging in DashboardStart dependency * Create embeddable by reference and navigate back to dashboard * Trying to feature flag the new flow * Feature flagging new visualize flow * Removing unnecessary console statement * Fixing typescript errors * Adding a functional test for new functionality * Adding a functional test for new functionality * Fixing test name * Changing test name * Moving functional test to a separate folder * Trying to fix the config file * Adding an index file * Remove falsly included file * Adding aggs and params to vis input * Serializing vis before passing it as an input * Incorporating new state transfer logic * Remove dashboardStart as a dependency * Trying to get the test to run * Remove unused import * Readding spaces * Fixing type errors * Incorporating new changes # Conflicts: # scripts/functional_tests.js # tasks/function_test_groups.js
1 parent 327fe28 commit 1b76123

15 files changed

Lines changed: 870 additions & 16 deletions

File tree

scripts/functional_tests.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ require('@kbn/test').runTestsCli([
2525
require.resolve('../test/interpreter_functional/config.ts'),
2626
require.resolve('../test/ui_capabilities/newsfeed_err/config.ts'),
2727
require.resolve('../test/examples/config.js'),
28+
require.resolve('../test/new_visualize_flow/config.js'),
2829
]);

src/plugins/dashboard/public/application/dashboard_app_controller.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ import {
5858
isErrorEmbeddable,
5959
openAddPanelFlyout,
6060
ViewMode,
61-
SavedObjectEmbeddableInput,
6261
ContainerOutput,
6362
EmbeddableInput,
6463
} from '../../../embeddable/public';
@@ -432,14 +431,16 @@ export class DashboardAppController {
432431
.getIncomingEmbeddablePackage();
433432
if (incomingState) {
434433
if ('id' in incomingState) {
435-
container.addNewEmbeddable<SavedObjectEmbeddableInput>(incomingState.type, {
434+
container.addNewEmbeddable<EmbeddableInput>(incomingState.type, {
436435
savedObjectId: incomingState.id,
437436
});
438437
} else if ('input' in incomingState) {
439-
container.addNewEmbeddable<EmbeddableInput>(
440-
incomingState.type,
441-
incomingState.input
442-
);
438+
const input = incomingState.input;
439+
delete input.id;
440+
const explicitInput = {
441+
savedVis: input,
442+
};
443+
container.addNewEmbeddable<EmbeddableInput>(incomingState.type, explicitInput);
443444
}
444445
}
445446
}

src/plugins/visualizations/public/embeddable/visualize_embeddable_factory.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
import { DisabledLabEmbeddable } from './disabled_lab_embeddable';
3131
import { VisualizeEmbeddable, VisualizeInput, VisualizeOutput } from './visualize_embeddable';
3232
import { VISUALIZE_EMBEDDABLE_TYPE } from './constants';
33-
import { Vis } from '../vis';
33+
import { SerializedVis, Vis } from '../vis';
3434
import {
3535
getCapabilities,
3636
getTypes,
@@ -124,13 +124,20 @@ export class VisualizeEmbeddableFactory
124124
}
125125
}
126126

127-
public async create() {
127+
public async create(input: VisualizeInput & { savedVis?: SerializedVis }, parent?: IContainer) {
128128
// TODO: This is a bit of a hack to preserve the original functionality. Ideally we will clean this up
129129
// to allow for in place creation of visualizations without having to navigate away to a new URL.
130-
showNewVisModal({
131-
originatingApp: await this.getCurrentAppId(),
132-
outsideVisualizeApp: true,
133-
});
134-
return undefined;
130+
if (input.savedVis) {
131+
const visState = input.savedVis;
132+
const vis = new Vis(visState.type, visState);
133+
await vis.setState(visState);
134+
return createVisEmbeddableFromObject(this.deps)(vis, input, parent);
135+
} else {
136+
showNewVisModal({
137+
originatingApp: await this.getCurrentAppId(),
138+
outsideVisualizeApp: true,
139+
});
140+
return undefined;
141+
}
135142
}
136143
}

src/plugins/visualize/config.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import { schema, TypeOf } from '@kbn/config-schema';
21+
22+
export const configSchema = schema.object({
23+
showNewVisualizeFlow: schema.boolean({ defaultValue: false }),
24+
});
25+
26+
export type ConfigSchema = TypeOf<typeof configSchema>;

src/plugins/visualize/public/application/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import { SharePluginStart } from 'src/plugins/share/public';
4444
import { SavedObjectsStart, SavedObject } from 'src/plugins/saved_objects/public';
4545
import { EmbeddableStart } from 'src/plugins/embeddable/public';
4646
import { KibanaLegacyStart } from 'src/plugins/kibana_legacy/public';
47+
import { ConfigSchema } from '../../config';
4748

4849
export type PureVisState = SavedVisState;
4950

@@ -110,6 +111,7 @@ export interface VisualizeServices extends CoreStart {
110111
createVisEmbeddableFromObject: VisualizationsStart['__LEGACY']['createVisEmbeddableFromObject'];
111112
restorePreviousUrl: () => void;
112113
scopedHistory: ScopedHistory;
114+
featureFlagConfig: ConfigSchema;
113115
}
114116

115117
export interface SavedVisInstance {

src/plugins/visualize/public/application/utils/get_top_nav_config.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import React from 'react';
2121
import { i18n } from '@kbn/i18n';
2222

2323
import { TopNavMenuData } from 'src/plugins/navigation/public';
24+
import uuid from 'uuid';
2425
import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../visualizations/public';
2526
import {
2627
showSaveModal,
@@ -33,7 +34,6 @@ import { unhashUrl } from '../../../../kibana_utils/public';
3334
import { SavedVisInstance, VisualizeServices, VisualizeAppStateContainer } from '../types';
3435
import { VisualizeConstants } from '../visualize_constants';
3536
import { getEditBreadcrumbs } from './breadcrumbs';
36-
3737
interface TopNavConfigParams {
3838
hasUnsavedChanges: boolean;
3939
setHasUnsavedChanges: (value: boolean) => void;
@@ -66,6 +66,7 @@ export const getTopNavConfig = (
6666
toastNotifications,
6767
visualizeCapabilities,
6868
i18n: { Context: I18nContext },
69+
featureFlagConfig,
6970
}: VisualizeServices
7071
) => {
7172
/**
@@ -234,6 +235,19 @@ export const getTopNavConfig = (
234235
return response;
235236
};
236237

238+
const createVisReference = () => {
239+
if (!originatingApp) {
240+
return;
241+
}
242+
const input = {
243+
...vis.serialize(),
244+
id: uuid.v4(),
245+
};
246+
embeddable.getStateTransfer().navigateToWithEmbeddablePackage(originatingApp, {
247+
state: { input, type: VISUALIZE_EMBEDDABLE_TYPE },
248+
});
249+
};
250+
237251
const saveModal = (
238252
<SavedObjectSaveModalOrigin
239253
documentInfo={savedVis}
@@ -243,7 +257,11 @@ export const getTopNavConfig = (
243257
originatingApp={originatingApp}
244258
/>
245259
);
246-
showSaveModal(saveModal, I18nContext);
260+
if (originatingApp === 'dashboards' && featureFlagConfig.showNewVisualizeFlow) {
261+
createVisReference();
262+
} else {
263+
showSaveModal(saveModal, I18nContext);
264+
}
247265
},
248266
},
249267
]

src/plugins/visualize/public/plugin.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ export interface VisualizePluginSetupDependencies {
6060
data: DataPublicPluginSetup;
6161
}
6262

63+
export interface FeatureFlagConfig {
64+
showNewVisualizeFlow: boolean;
65+
}
66+
6367
export class VisualizePlugin
6468
implements
6569
Plugin<void, void, VisualizePluginSetupDependencies, VisualizePluginStartDependencies> {
@@ -165,6 +169,7 @@ export class VisualizePlugin
165169
savedObjectsPublic: pluginsStart.savedObjects,
166170
scopedHistory: params.history,
167171
restorePreviousUrl,
172+
featureFlagConfig: this.initializerContext.config.get<FeatureFlagConfig>(),
168173
};
169174

170175
params.element.classList.add('visAppWrapper');

src/plugins/visualize/server/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,17 @@
1717
* under the License.
1818
*/
1919

20-
import { PluginInitializerContext } from 'kibana/server';
20+
import { PluginInitializerContext, PluginConfigDescriptor } from 'kibana/server';
2121
import { VisualizeServerPlugin } from './plugin';
2222

23+
import { ConfigSchema, configSchema } from '../config';
24+
25+
export const config: PluginConfigDescriptor<ConfigSchema> = {
26+
exposeToBrowser: {
27+
showNewVisualizeFlow: true,
28+
},
29+
schema: configSchema,
30+
};
31+
2332
export const plugin = (initContext: PluginInitializerContext) =>
2433
new VisualizeServerPlugin(initContext);

tasks/function_test_groups.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ export function getFunctionalTestGroupRunConfigs({ kibanaInstallDir } = {}) {
4545
'test/functional/config.js',
4646
'--config',
4747
'test/ui_capabilities/newsfeed_err/config.ts',
48+
'--config',
49+
'test/new_visualize_flow/config.js',
4850
// '--config', 'test/functional/config.firefox.js',
4951
'--bail',
5052
'--debug',

test/functional/services/dashboard/visualizations.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,31 @@ export function DashboardVisualizationProvider({ getService, getPageObjects }: F
139139
redirectToOrigin: true,
140140
});
141141
}
142+
143+
async createAndEmbedMetric(name: string) {
144+
log.debug(`createAndEmbedMetric(${name})`);
145+
const inViewMode = await PageObjects.dashboard.getIsInViewMode();
146+
if (inViewMode) {
147+
await PageObjects.dashboard.switchToEditMode();
148+
}
149+
await this.ensureNewVisualizationDialogIsShowing();
150+
await PageObjects.visualize.clickMetric();
151+
await find.clickByCssSelector('li.euiListGroupItem:nth-of-type(2)');
152+
await testSubjects.exists('visualizeSaveButton');
153+
await testSubjects.click('visualizeSaveButton');
154+
}
155+
156+
async createAndEmbedMarkdown({ name, markdown }: { name: string; markdown: string }) {
157+
log.debug(`createAndEmbedMarkdown(${markdown})`);
158+
const inViewMode = await PageObjects.dashboard.getIsInViewMode();
159+
if (inViewMode) {
160+
await PageObjects.dashboard.switchToEditMode();
161+
}
162+
await this.ensureNewVisualizationDialogIsShowing();
163+
await PageObjects.visualize.clickMarkdownWidget();
164+
await PageObjects.visEditor.setMarkdownTxt(markdown);
165+
await PageObjects.visEditor.clickGo();
166+
await testSubjects.click('visualizeSaveButton');
167+
}
142168
})();
143169
}

0 commit comments

Comments
 (0)