mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Combine visualizations and visualize plugins (#121550)
* [WIP] Combine visualizations and visualize plugins * Revert some changes and do some refactoring * Refactor some code * Fix some tests * Fix functional tests and some jest test cases * Update telemetry * Fix get_visualization_instance.test and plugin-list.asciidoc * Refactor some code * fix CI * Add visualizations to vis_default_editor tsconfig * Revert changes related to telemetry and permissions * Add dashboard to timeseries tsconfig.json * Update limits file * Update translation keys * Add capabilitiesProvider back to server and replace visEditorsRegistry getter and setter with service * Update mocks.ts * Revert changes related to visEditorsRegistry * Get rid of visEditorsRegistry getter and setter * Remove dashboard from timeseries/tsconfig.json * Return back dashboard dependency to timeseries/tsconfig.json, rename applicaion folder to visualize_app and APP_NAME to VISUALIZE_APP_NAME, revert types.ts * Remove comma in .i18nrc.json Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Alexey Antonov <alexwizp@gmail.com>
This commit is contained in:
parent
b34476e659
commit
a9ec1be357
86 changed files with 688 additions and 968 deletions
|
@ -77,8 +77,7 @@
|
|||
"visTypeVega": "src/plugins/vis_types/vega",
|
||||
"visTypeVislib": "src/plugins/vis_types/vislib",
|
||||
"visTypeXy": "src/plugins/vis_types/xy",
|
||||
"visualizations": "src/plugins/visualizations",
|
||||
"visualize": "src/plugins/visualize"
|
||||
"visualizations": "src/plugins/visualizations"
|
||||
},
|
||||
"translations": []
|
||||
}
|
||||
|
|
|
@ -342,10 +342,6 @@ The plugin exposes the static DefaultEditorController class to consume.
|
|||
|WARNING: Missing README.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/visualize[visualize]
|
||||
|WARNING: Missing README.
|
||||
|
||||
|
||||
|===
|
||||
|
||||
[discrete]
|
||||
|
|
|
@ -71,7 +71,6 @@ pageLoadAssetSize:
|
|||
visTypeVislib: 242838
|
||||
visTypeXy: 113478
|
||||
visualizations: 90000
|
||||
visualize: 57431
|
||||
watcher: 43598
|
||||
runtimeFields: 41752
|
||||
stackAlerts: 29684
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "visDefaultEditor",
|
||||
"version": "kibana",
|
||||
"ui": true,
|
||||
"optionalPlugins": ["visualize"],
|
||||
"optionalPlugins": ["visualizations"],
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact", "data", "fieldFormats", "discover", "esUiShared"],
|
||||
"owner": {
|
||||
"name": "Vis Editors",
|
||||
|
|
|
@ -13,8 +13,11 @@ import React, { useEffect, useRef, useState, useCallback } from 'react';
|
|||
import { EventEmitter } from 'events';
|
||||
import { EuiResizableContainer } from '@elastic/eui';
|
||||
|
||||
import { Vis, VisualizeEmbeddableContract } from 'src/plugins/visualizations/public';
|
||||
import { EditorRenderProps } from 'src/plugins/visualize/public';
|
||||
import {
|
||||
Vis,
|
||||
VisualizeEmbeddableContract,
|
||||
EditorRenderProps,
|
||||
} from 'src/plugins/visualizations/public';
|
||||
import { KibanaContextProvider } from '../../kibana_react/public';
|
||||
import { Storage } from '../../kibana_utils/public';
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import { EventEmitter } from 'events';
|
|||
import { EuiErrorBoundary, EuiLoadingChart } from '@elastic/eui';
|
||||
|
||||
import { Vis, VisualizeEmbeddableContract } from 'src/plugins/visualizations/public';
|
||||
import { IEditorController, EditorRenderProps } from 'src/plugins/visualize/public';
|
||||
import { IEditorController, EditorRenderProps } from 'src/plugins/visualizations/public';
|
||||
import { KibanaThemeProvider } from '../../kibana_react/public';
|
||||
import { getTheme } from './services';
|
||||
|
||||
|
|
|
@ -8,21 +8,21 @@
|
|||
|
||||
import { CoreSetup, Plugin } from 'kibana/public';
|
||||
|
||||
import { VisualizePluginSetup } from '../../visualize/public';
|
||||
import { DefaultEditorController } from './default_editor_controller';
|
||||
import { setTheme } from './services';
|
||||
import type { VisualizationsSetup } from '../../visualizations/public';
|
||||
|
||||
export interface VisDefaultEditorSetupDependencies {
|
||||
visualize: VisualizePluginSetup;
|
||||
visualizations: VisualizationsSetup;
|
||||
}
|
||||
|
||||
export class VisDefaultEditorPlugin
|
||||
implements Plugin<void, void, VisDefaultEditorSetupDependencies, {}>
|
||||
{
|
||||
public setup(core: CoreSetup, { visualize }: VisDefaultEditorSetupDependencies) {
|
||||
public setup(core: CoreSetup, { visualizations }: VisDefaultEditorSetupDependencies) {
|
||||
setTheme(core.theme);
|
||||
if (visualize) {
|
||||
visualize.visEditorsRegistry.registerDefault(DefaultEditorController);
|
||||
if (visualizations) {
|
||||
visualizations.visEditorsRegistry.registerDefault(DefaultEditorController);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
"references": [
|
||||
{ "path": "../../core/tsconfig.json" },
|
||||
{ "path": "../data/tsconfig.json" },
|
||||
{ "path": "../visualize/tsconfig.json" },
|
||||
{ "path": "../visualizations/tsconfig.json" },
|
||||
{ "path": "../discover/tsconfig.json" },
|
||||
{ "path": "../kibana_utils/tsconfig.json" },
|
||||
{ "path": "../kibana_react/tsconfig.json" },
|
||||
{ "path": "../field_formats/tsconfig.json" }
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"kibanaVersion": "kibana",
|
||||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["charts", "data", "expressions", "visualizations", "visualize"],
|
||||
"requiredPlugins": ["charts", "data", "expressions", "visualizations"],
|
||||
"optionalPlugins": ["home","usageCollection"],
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact", "fieldFormats"],
|
||||
"owner": {
|
||||
|
|
|
@ -32,7 +32,7 @@ import { fetchFields, VisFields } from '../lib/fetch_fields';
|
|||
import { getDataStart, getCoreStart } from '../../services';
|
||||
import type { TimeseriesVisParams } from '../../types';
|
||||
import { UseIndexPatternModeCallout } from './use_index_patter_mode_callout';
|
||||
import type { EditorRenderProps } from '../../../../../visualize/public';
|
||||
import type { EditorRenderProps } from '../../../../../visualizations/public';
|
||||
|
||||
const VIS_STATE_DEBOUNCE_DELAY = 200;
|
||||
const APP_NAME = 'VisEditor';
|
||||
|
|
|
@ -9,9 +9,12 @@
|
|||
import React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import type { EventEmitter } from 'events';
|
||||
import type { Vis, VisualizeEmbeddableContract } from 'src/plugins/visualizations/public';
|
||||
import type { IEditorController, EditorRenderProps } from 'src/plugins/visualize/public';
|
||||
|
||||
import type {
|
||||
Vis,
|
||||
VisualizeEmbeddableContract,
|
||||
IEditorController,
|
||||
EditorRenderProps,
|
||||
} from 'src/plugins/visualizations/public';
|
||||
import { getUISettings, getI18n, getCoreStart } from '../services';
|
||||
import { VisEditor } from './components/vis_editor_lazy';
|
||||
import type { TimeseriesVisParams } from '../types';
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'kibana/public';
|
||||
import { Plugin as ExpressionsPublicPlugin } from '../../../expressions/public';
|
||||
import { VisualizationsSetup } from '../../../visualizations/public';
|
||||
import { VisualizePluginSetup } from '../../../visualize/public';
|
||||
import { EditorController, TSVB_EDITOR_NAME } from './application/editor_controller';
|
||||
|
||||
import { createMetricsFn } from './metrics_fn';
|
||||
|
@ -30,7 +29,6 @@ import { getTimeseriesVisRenderer } from './timeseries_vis_renderer';
|
|||
export interface MetricsPluginSetupDependencies {
|
||||
expressions: ReturnType<ExpressionsPublicPlugin['setup']>;
|
||||
visualizations: VisualizationsSetup;
|
||||
visualize: VisualizePluginSetup;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
@ -47,11 +45,8 @@ export class MetricsPlugin implements Plugin<void, void> {
|
|||
this.initializerContext = initializerContext;
|
||||
}
|
||||
|
||||
public setup(
|
||||
core: CoreSetup,
|
||||
{ expressions, visualizations, visualize }: MetricsPluginSetupDependencies
|
||||
) {
|
||||
visualize.visEditorsRegistry.register(TSVB_EDITOR_NAME, EditorController);
|
||||
public setup(core: CoreSetup, { expressions, visualizations }: MetricsPluginSetupDependencies) {
|
||||
visualizations.visEditorsRegistry.register(TSVB_EDITOR_NAME, EditorController);
|
||||
expressions.registerFunction(createMetricsFn);
|
||||
expressions.registerRenderer(
|
||||
getTimeseriesVisRenderer({
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
{ "path": "../../data/tsconfig.json" },
|
||||
{ "path": "../../expressions/tsconfig.json" },
|
||||
{ "path": "../../visualizations/tsconfig.json" },
|
||||
{ "path": "../../visualize/tsconfig.json" },
|
||||
{ "path": "../../dashboard/tsconfig.json" },
|
||||
{ "path": "../../kibana_utils/tsconfig.json" },
|
||||
{ "path": "../../kibana_react/tsconfig.json" },
|
||||
{ "path": "../../usage_collection/tsconfig.json" },
|
||||
|
|
|
@ -8,3 +8,19 @@
|
|||
|
||||
export const VISUALIZE_ENABLE_LABS_SETTING = 'visualize:enableLabs';
|
||||
export const VISUALIZE_EMBEDDABLE_TYPE = 'visualization';
|
||||
|
||||
export const STATE_STORAGE_KEY = '_a';
|
||||
export const GLOBAL_STATE_STORAGE_KEY = '_g';
|
||||
|
||||
export const VISUALIZE_APP_NAME = 'visualize';
|
||||
|
||||
export const VisualizeConstants = {
|
||||
VISUALIZE_BASE_PATH: '/app/visualize',
|
||||
LANDING_PAGE_PATH: '/',
|
||||
WIZARD_STEP_1_PAGE_PATH: '/new',
|
||||
WIZARD_STEP_2_PAGE_PATH: '/new/configure',
|
||||
CREATE_PATH: '/create',
|
||||
EDIT_PATH: '/edit',
|
||||
EDIT_BY_VALUE_PATH: '/edit_by_value',
|
||||
APP_ID: 'visualize',
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ import type { LocatorDefinition, LocatorPublic } from 'src/plugins/share/common'
|
|||
import { isFilterPinned } from '../../data/common';
|
||||
import { url } from '../../kibana_utils/common';
|
||||
import { GLOBAL_STATE_STORAGE_KEY, STATE_STORAGE_KEY, VisualizeConstants } from './constants';
|
||||
import { PureVisState } from './types';
|
||||
import type { SavedVisState } from './types';
|
||||
|
||||
const removeEmptyKeys = (o: Record<string, Serializable>): Record<string, Serializable> =>
|
||||
omitBy(o, (v) => v == null);
|
||||
|
@ -59,7 +59,7 @@ export type VisualizeLocatorParams = {
|
|||
*
|
||||
* @note This is required to navigate to "create" page (i.e., when no `visId` has been provided).
|
||||
*/
|
||||
vis?: PureVisState;
|
||||
vis?: SavedVisState;
|
||||
|
||||
/**
|
||||
* Whether this visualization is linked a saved search.
|
|
@ -7,12 +7,15 @@
|
|||
"data",
|
||||
"expressions",
|
||||
"uiActions",
|
||||
"urlForwarding",
|
||||
"navigation",
|
||||
"embeddable",
|
||||
"inspector",
|
||||
"savedObjects"
|
||||
"savedObjects",
|
||||
"presentationUtil"
|
||||
],
|
||||
"optionalPlugins": ["usageCollection", "spaces", "savedObjectsTaggingOss"],
|
||||
"requiredBundles": ["kibanaUtils", "discover", "kibanaReact"],
|
||||
"optionalPlugins": [ "home", "share", "usageCollection", "spaces", "savedObjectsTaggingOss"],
|
||||
"requiredBundles": ["kibanaUtils", "discover", "kibanaReact", "home"],
|
||||
"extraPublicDirs": ["common/constants", "common/prepare_log_table", "common/expression_functions"],
|
||||
"owner": {
|
||||
"name": "Vis Editors",
|
||||
|
|
|
@ -55,3 +55,5 @@ export type {
|
|||
HistogramParams,
|
||||
} from '../common/expression_functions/xy_dimension';
|
||||
export { urlFor, getFullPath } from './utils/saved_visualize_utils';
|
||||
|
||||
export type { IEditorController, EditorRenderProps } from './visualize_app/types';
|
||||
|
|
|
@ -19,12 +19,16 @@ import { usageCollectionPluginMock } from '../../../plugins/usage_collection/pub
|
|||
import { uiActionsPluginMock } from '../../../plugins/ui_actions/public/mocks';
|
||||
import { inspectorPluginMock } from '../../../plugins/inspector/public/mocks';
|
||||
import { savedObjectsPluginMock } from '../../../plugins/saved_objects/public/mocks';
|
||||
import { urlForwardingPluginMock } from '../../../plugins/url_forwarding/public/mocks';
|
||||
import { navigationPluginMock } from '../../../plugins/navigation/public/mocks';
|
||||
import { presentationUtilPluginMock } from '../../../plugins/presentation_util/public/mocks';
|
||||
import { savedObjectTaggingOssPluginMock } from '../../saved_objects_tagging_oss/public/mocks';
|
||||
|
||||
const createSetupContract = (): VisualizationsSetup => ({
|
||||
createBaseVisualization: jest.fn(),
|
||||
registerAlias: jest.fn(),
|
||||
hideTypes: jest.fn(),
|
||||
visEditorsRegistry: { registerDefault: jest.fn(), register: jest.fn(), get: jest.fn() },
|
||||
});
|
||||
|
||||
const createStartContract = (): VisualizationsStart => ({
|
||||
|
@ -33,16 +37,7 @@ const createStartContract = (): VisualizationsStart => ({
|
|||
getAliases: jest.fn(),
|
||||
getByGroup: jest.fn(),
|
||||
unRegisterAlias: jest.fn(),
|
||||
getSavedVisualization: jest.fn(),
|
||||
saveVisualization: jest.fn(),
|
||||
findListItems: jest.fn(),
|
||||
showNewVisModal: jest.fn(),
|
||||
createVis: jest.fn(),
|
||||
convertFromSerializedVis: jest.fn(),
|
||||
convertToSerializedVis: jest.fn(),
|
||||
__LEGACY: {
|
||||
createVisEmbeddableFromObject: jest.fn(),
|
||||
},
|
||||
});
|
||||
|
||||
const createInstance = async () => {
|
||||
|
@ -54,6 +49,7 @@ const createInstance = async () => {
|
|||
expressions: expressionsPluginMock.createSetupContract(),
|
||||
inspector: inspectorPluginMock.createSetupContract(),
|
||||
usageCollection: usageCollectionPluginMock.createSetupContract(),
|
||||
urlForwarding: urlForwardingPluginMock.createSetupContract(),
|
||||
});
|
||||
const doStart = () =>
|
||||
plugin.start(coreMock.createStart(), {
|
||||
|
@ -68,6 +64,9 @@ const createInstance = async () => {
|
|||
savedObjectsClient: coreMock.createStart().savedObjects.client,
|
||||
savedObjects: savedObjectsPluginMock.createStartContract(),
|
||||
savedObjectsTaggingOss: savedObjectTaggingOssPluginMock.createStart(),
|
||||
navigation: navigationPluginMock.createStartContract(),
|
||||
presentationUtil: presentationUtilPluginMock.createStartContract(coreMock.createStart()),
|
||||
urlForwarding: urlForwardingPluginMock.createStartContract(),
|
||||
});
|
||||
|
||||
return {
|
||||
|
|
|
@ -6,7 +6,17 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { SavedObjectsFindOptionsReference } from 'kibana/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { createHashHistory } from 'history';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import {
|
||||
AppMountParameters,
|
||||
AppUpdater,
|
||||
DEFAULT_APP_CATEGORIES,
|
||||
ScopedHistory,
|
||||
} from '../../../core/public';
|
||||
import { VisualizeConstants } from '../common/constants';
|
||||
import {
|
||||
setUISettings,
|
||||
setTypes,
|
||||
|
@ -28,28 +38,29 @@ import {
|
|||
setTheme,
|
||||
} from './services';
|
||||
import {
|
||||
createVisEmbeddableFromObject,
|
||||
VISUALIZE_EMBEDDABLE_TYPE,
|
||||
VisualizeEmbeddableFactory,
|
||||
createVisEmbeddableFromObject,
|
||||
} from './embeddable';
|
||||
import type { SpacesPluginStart } from '../../../../x-pack/plugins/spaces/public';
|
||||
import { TypesService } from './vis_types/types_service';
|
||||
import { range as rangeExpressionFunction } from '../common/expression_functions/range';
|
||||
import { visDimension as visDimensionExpressionFunction } from '../common/expression_functions/vis_dimension';
|
||||
import { xyDimension as xyDimensionExpressionFunction } from '../common/expression_functions/xy_dimension';
|
||||
|
||||
import { createStartServicesGetter, StartServicesGetter } from '../../kibana_utils/public';
|
||||
import type { SerializedVis, Vis } from './vis';
|
||||
import { showNewVisModal } from './wizard';
|
||||
|
||||
import {
|
||||
convertFromSerializedVis,
|
||||
convertToSerializedVis,
|
||||
getSavedVisualization,
|
||||
saveVisualization,
|
||||
findListItems,
|
||||
} from './utils/saved_visualize_utils';
|
||||
createKbnUrlStateStorage,
|
||||
createKbnUrlTracker,
|
||||
createStartServicesGetter,
|
||||
Storage,
|
||||
withNotifyOnErrors,
|
||||
} from '../../kibana_utils/public';
|
||||
import { VisualizeLocatorDefinition } from '../common/locator';
|
||||
import { showNewVisModal } from './wizard';
|
||||
import { createVisEditorsRegistry, VisEditorsRegistry } from './vis_editors_registry';
|
||||
import { esFilters } from '../../../plugins/data/public';
|
||||
import { FeatureCatalogueCategory } from '../../home/public';
|
||||
|
||||
import type { VisualizeServices } from './visualize_app/types';
|
||||
import type {
|
||||
PluginInitializerContext,
|
||||
CoreSetup,
|
||||
|
@ -70,8 +81,13 @@ import type { DataPublicPluginSetup, DataPublicPluginStart } from '../../../plug
|
|||
import type { ExpressionsSetup, ExpressionsStart } from '../../expressions/public';
|
||||
import type { EmbeddableSetup, EmbeddableStart } from '../../embeddable/public';
|
||||
import type { SavedObjectTaggingOssPluginStart } from '../../saved_objects_tagging_oss/public';
|
||||
import { createVisAsync } from './vis_async';
|
||||
import type { VisSavedObject, SaveVisOptions, GetVisOptions } from './types';
|
||||
import type { NavigationPublicPluginStart as NavigationStart } from '../../navigation/public';
|
||||
import type { SharePluginSetup, SharePluginStart } from '../../share/public';
|
||||
import type { UrlForwardingSetup, UrlForwardingStart } from '../../url_forwarding/public';
|
||||
import type { PresentationUtilPluginStart } from '../../presentation_util/public';
|
||||
import type { UsageCollectionStart } from '../../usage_collection/public';
|
||||
import type { HomePublicPluginSetup } from '../../home/public';
|
||||
import type { SpacesPluginStart } from '../../../../x-pack/plugins/spaces/public';
|
||||
|
||||
/**
|
||||
* Interface for this plugin's returned setup/start contracts.
|
||||
|
@ -79,21 +95,10 @@ import type { VisSavedObject, SaveVisOptions, GetVisOptions } from './types';
|
|||
* @public
|
||||
*/
|
||||
|
||||
export type VisualizationsSetup = TypesSetup;
|
||||
export type VisualizationsSetup = TypesSetup & { visEditorsRegistry: VisEditorsRegistry };
|
||||
|
||||
export interface VisualizationsStart extends TypesStart {
|
||||
createVis: (visType: string, visState: SerializedVis) => Promise<Vis>;
|
||||
convertToSerializedVis: typeof convertToSerializedVis;
|
||||
convertFromSerializedVis: typeof convertFromSerializedVis;
|
||||
showNewVisModal: typeof showNewVisModal;
|
||||
getSavedVisualization: (opts?: GetVisOptions | string) => Promise<VisSavedObject>;
|
||||
saveVisualization: (savedVis: VisSavedObject, saveOptions: SaveVisOptions) => Promise<string>;
|
||||
findListItems: (
|
||||
searchTerm: string,
|
||||
listingLimit: number,
|
||||
references?: SavedObjectsFindOptionsReference[]
|
||||
) => Promise<{ hits: Array<Record<string, unknown>>; total: number }>;
|
||||
__LEGACY: { createVisEmbeddableFromObject: ReturnType<typeof createVisEmbeddableFromObject> };
|
||||
}
|
||||
|
||||
export interface VisualizationsSetupDeps {
|
||||
|
@ -102,6 +107,9 @@ export interface VisualizationsSetupDeps {
|
|||
expressions: ExpressionsSetup;
|
||||
inspector: InspectorSetup;
|
||||
usageCollection: UsageCollectionSetup;
|
||||
urlForwarding: UrlForwardingSetup;
|
||||
home?: HomePublicPluginSetup;
|
||||
share?: SharePluginSetup;
|
||||
}
|
||||
|
||||
export interface VisualizationsStartDeps {
|
||||
|
@ -112,10 +120,15 @@ export interface VisualizationsStartDeps {
|
|||
uiActions: UiActionsStart;
|
||||
application: ApplicationStart;
|
||||
getAttributeService: EmbeddableStart['getAttributeService'];
|
||||
navigation: NavigationStart;
|
||||
presentationUtil: PresentationUtilPluginStart;
|
||||
savedObjects: SavedObjectsStart;
|
||||
savedObjectsClient: SavedObjectsClientContract;
|
||||
spaces?: SpacesPluginStart;
|
||||
savedObjectsTaggingOss?: SavedObjectTaggingOssPluginStart;
|
||||
share?: SharePluginStart;
|
||||
urlForwarding: UrlForwardingStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,15 +149,175 @@ export class VisualizationsPlugin
|
|||
>
|
||||
{
|
||||
private readonly types: TypesService = new TypesService();
|
||||
private getStartServicesOrDie?: StartServicesGetter<VisualizationsStartDeps, VisualizationsStart>;
|
||||
private appStateUpdater = new BehaviorSubject<AppUpdater>(() => ({}));
|
||||
private stopUrlTracking: (() => void) | undefined = undefined;
|
||||
private currentHistory: ScopedHistory | undefined = undefined;
|
||||
private isLinkedToOriginatingApp: (() => boolean) | undefined = undefined;
|
||||
|
||||
constructor(initializerContext: PluginInitializerContext) {}
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
|
||||
public setup(
|
||||
core: CoreSetup<VisualizationsStartDeps, VisualizationsStart>,
|
||||
{ expressions, embeddable, usageCollection, data }: VisualizationsSetupDeps
|
||||
{
|
||||
expressions,
|
||||
embeddable,
|
||||
usageCollection,
|
||||
data,
|
||||
home,
|
||||
urlForwarding,
|
||||
share,
|
||||
}: VisualizationsSetupDeps
|
||||
): VisualizationsSetup {
|
||||
const start = (this.getStartServicesOrDie = createStartServicesGetter(core.getStartServices));
|
||||
const {
|
||||
appMounted,
|
||||
appUnMounted,
|
||||
stop: stopUrlTracker,
|
||||
setActiveUrl,
|
||||
restorePreviousUrl,
|
||||
} = createKbnUrlTracker({
|
||||
baseUrl: core.http.basePath.prepend(VisualizeConstants.VISUALIZE_BASE_PATH),
|
||||
defaultSubUrl: '#/',
|
||||
storageKey: `lastUrl:${core.http.basePath.get()}:visualize`,
|
||||
navLinkUpdater$: this.appStateUpdater,
|
||||
toastNotifications: core.notifications.toasts,
|
||||
stateParams: [
|
||||
{
|
||||
kbnUrlKey: '_g',
|
||||
stateUpdate$: data.query.state$.pipe(
|
||||
filter(
|
||||
({ changes }) => !!(changes.globalFilters || changes.time || changes.refreshInterval)
|
||||
),
|
||||
map(({ state }) => ({
|
||||
...state,
|
||||
filters: state.filters?.filter(esFilters.isFilterPinned),
|
||||
}))
|
||||
),
|
||||
},
|
||||
],
|
||||
getHistory: () => this.currentHistory!,
|
||||
onBeforeNavLinkSaved: (urlToSave: string) => {
|
||||
if (this.isLinkedToOriginatingApp?.()) {
|
||||
return core.http.basePath.prepend(VisualizeConstants.VISUALIZE_BASE_PATH);
|
||||
}
|
||||
return urlToSave;
|
||||
},
|
||||
});
|
||||
this.stopUrlTracking = () => {
|
||||
stopUrlTracker();
|
||||
};
|
||||
|
||||
const start = createStartServicesGetter(core.getStartServices);
|
||||
const visEditorsRegistry = createVisEditorsRegistry();
|
||||
|
||||
core.application.register({
|
||||
id: VisualizeConstants.APP_ID,
|
||||
title: 'Visualize Library',
|
||||
order: 8000,
|
||||
euiIconType: 'logoKibana',
|
||||
defaultPath: '#/',
|
||||
category: DEFAULT_APP_CATEGORIES.kibana,
|
||||
updater$: this.appStateUpdater.asObservable(),
|
||||
// remove all references to visualize
|
||||
mount: async (params: AppMountParameters) => {
|
||||
const [coreStart, pluginsStart] = await core.getStartServices();
|
||||
this.currentHistory = params.history;
|
||||
|
||||
// allows the urlTracker to only save URLs that are not linked to an originatingApp
|
||||
this.isLinkedToOriginatingApp = () => {
|
||||
return Boolean(
|
||||
pluginsStart.embeddable
|
||||
.getStateTransfer()
|
||||
.getIncomingEditorState(VisualizeConstants.APP_ID)?.originatingApp
|
||||
);
|
||||
};
|
||||
|
||||
// make sure the index pattern list is up to date
|
||||
pluginsStart.data.indexPatterns.clearCache();
|
||||
// make sure a default index pattern exists
|
||||
// if not, the page will be redirected to management and visualize won't be rendered
|
||||
await pluginsStart.data.indexPatterns.ensureDefaultDataView();
|
||||
|
||||
appMounted();
|
||||
|
||||
// dispatch synthetic hash change event to update hash history objects
|
||||
// this is necessary because hash updates triggered by using popState won't trigger this event naturally.
|
||||
const unlistenParentHistory = params.history.listen(() => {
|
||||
window.dispatchEvent(new HashChangeEvent('hashchange'));
|
||||
});
|
||||
/**
|
||||
* current implementation uses 2 history objects:
|
||||
* 1. the hash history (used for the react hash router)
|
||||
* 2. and the scoped history (used for url tracking)
|
||||
* this should be replaced to use only scoped history after moving legacy apps to browser routing
|
||||
*/
|
||||
const history = createHashHistory();
|
||||
const services: VisualizeServices = {
|
||||
...coreStart,
|
||||
history,
|
||||
kbnUrlStateStorage: createKbnUrlStateStorage({
|
||||
history,
|
||||
useHash: coreStart.uiSettings.get('state:storeInSessionStorage'),
|
||||
...withNotifyOnErrors(coreStart.notifications.toasts),
|
||||
}),
|
||||
urlForwarding: pluginsStart.urlForwarding,
|
||||
pluginInitializerContext: this.initializerContext,
|
||||
chrome: coreStart.chrome,
|
||||
data: pluginsStart.data,
|
||||
localStorage: new Storage(localStorage),
|
||||
navigation: pluginsStart.navigation,
|
||||
share: pluginsStart.share,
|
||||
toastNotifications: coreStart.notifications.toasts,
|
||||
visualizeCapabilities: coreStart.application.capabilities.visualize,
|
||||
dashboardCapabilities: coreStart.application.capabilities.dashboard,
|
||||
embeddable: pluginsStart.embeddable,
|
||||
stateTransferService: pluginsStart.embeddable.getStateTransfer(),
|
||||
setActiveUrl,
|
||||
createVisEmbeddableFromObject: createVisEmbeddableFromObject({ start }),
|
||||
savedObjectsPublic: pluginsStart.savedObjects,
|
||||
scopedHistory: params.history,
|
||||
restorePreviousUrl,
|
||||
setHeaderActionMenu: params.setHeaderActionMenu,
|
||||
savedObjectsTagging: pluginsStart.savedObjectsTaggingOss?.getTaggingApi(),
|
||||
presentationUtil: pluginsStart.presentationUtil,
|
||||
usageCollection: pluginsStart.usageCollection,
|
||||
getKibanaVersion: () => this.initializerContext.env.packageInfo.version,
|
||||
spaces: pluginsStart.spaces,
|
||||
visEditorsRegistry,
|
||||
};
|
||||
|
||||
params.element.classList.add('visAppWrapper');
|
||||
const { renderApp } = await import('./visualize_app');
|
||||
const unmount = renderApp(params, services);
|
||||
return () => {
|
||||
data.search.session.clear();
|
||||
params.element.classList.remove('visAppWrapper');
|
||||
unlistenParentHistory();
|
||||
unmount();
|
||||
appUnMounted();
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
urlForwarding.forwardApp('visualize', 'visualize');
|
||||
|
||||
if (home) {
|
||||
home.featureCatalogue.register({
|
||||
id: 'visualize',
|
||||
title: 'Visualize Library',
|
||||
description: i18n.translate('visualizations.visualizeDescription', {
|
||||
defaultMessage:
|
||||
'Create visualizations and aggregate data stores in your Elasticsearch indices.',
|
||||
}),
|
||||
icon: 'visualizeApp',
|
||||
path: `/app/visualize#${VisualizeConstants.LANDING_PAGE_PATH}`,
|
||||
showOnHomePage: false,
|
||||
category: FeatureCatalogueCategory.DATA,
|
||||
});
|
||||
}
|
||||
|
||||
if (share) {
|
||||
share.url.locators.create(new VisualizeLocatorDefinition());
|
||||
}
|
||||
|
||||
setUISettings(core.uiSettings);
|
||||
setUsageCollector(usageCollection);
|
||||
|
@ -158,6 +331,7 @@ export class VisualizationsPlugin
|
|||
|
||||
return {
|
||||
...this.types.setup(),
|
||||
visEditorsRegistry,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -171,6 +345,7 @@ export class VisualizationsPlugin
|
|||
savedObjects,
|
||||
spaces,
|
||||
savedObjectsTaggingOss,
|
||||
usageCollection,
|
||||
}: VisualizationsStartDeps
|
||||
): VisualizationsStart {
|
||||
const types = this.types.start();
|
||||
|
@ -196,46 +371,13 @@ export class VisualizationsPlugin
|
|||
return {
|
||||
...types,
|
||||
showNewVisModal,
|
||||
getSavedVisualization: async (opts) => {
|
||||
return getSavedVisualization(
|
||||
{
|
||||
search: data.search,
|
||||
savedObjectsClient: core.savedObjects.client,
|
||||
dataViews: data.dataViews,
|
||||
spaces,
|
||||
savedObjectsTagging: savedObjectsTaggingOss?.getTaggingApi(),
|
||||
},
|
||||
opts
|
||||
);
|
||||
},
|
||||
saveVisualization: async (savedVis, saveOptions) => {
|
||||
return saveVisualization(savedVis, saveOptions, {
|
||||
savedObjectsClient: core.savedObjects.client,
|
||||
overlays: core.overlays,
|
||||
savedObjectsTagging: savedObjectsTaggingOss?.getTaggingApi(),
|
||||
});
|
||||
},
|
||||
findListItems: async (searchTerm, listingLimit, references) => {
|
||||
return findListItems(core.savedObjects.client, types, searchTerm, listingLimit, references);
|
||||
},
|
||||
/**
|
||||
* creates new instance of Vis
|
||||
* @param {IndexPattern} indexPattern - index pattern to use
|
||||
* @param {VisState} visState - visualization configuration
|
||||
*/
|
||||
createVis: async (visType: string, visState: SerializedVis) =>
|
||||
await createVisAsync(visType, visState),
|
||||
convertToSerializedVis,
|
||||
convertFromSerializedVis,
|
||||
__LEGACY: {
|
||||
createVisEmbeddableFromObject: createVisEmbeddableFromObject({
|
||||
start: this.getStartServicesOrDie!,
|
||||
}),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public stop() {
|
||||
this.types.stop();
|
||||
if (this.stopUrlTracking) {
|
||||
this.stopUrlTracking();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { VisEditorConstructor } from './application/types';
|
||||
import { VisEditorConstructor } from './visualize_app/types';
|
||||
|
||||
const DEFAULT_NAME = 'default';
|
||||
|
|
@ -20,7 +20,7 @@ import {
|
|||
VisualizeNoMatch,
|
||||
VisualizeByValueEditor,
|
||||
} from './components';
|
||||
import { VisualizeConstants } from './visualize_constants';
|
||||
import { VisualizeConstants } from '../../common/constants';
|
||||
|
||||
export interface VisualizeAppProps {
|
||||
onAppLeave: AppMountParameters['onAppLeave'];
|
|
@ -14,7 +14,7 @@ export const InfoComponent = () => {
|
|||
const title = (
|
||||
<>
|
||||
<FormattedMessage
|
||||
id="visualize.experimentalVisInfoText"
|
||||
id="visualizations.experimentalVisInfoText"
|
||||
defaultMessage="This visualization is experimental and is not subject to the support SLA of official GA features.
|
||||
For feedback, please create an issue in {githubLink}."
|
||||
values={{
|
|
@ -26,20 +26,20 @@ export const SplitChartWarning = () => {
|
|||
data-test-subj="vizSplitChartWarning"
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="visualize.newHeatmapChart.notificationMessage"
|
||||
id="visualizations.newHeatmapChart.notificationMessage"
|
||||
defaultMessage="The new heatmap charts library does not yet support split chart aggregation. {conditionalMessage}"
|
||||
values={{
|
||||
conditionalMessage: (
|
||||
<>
|
||||
{canEditAdvancedSettings && (
|
||||
<FormattedMessage
|
||||
id="visualize.newHeatmapChart.conditionalMessage.newLibrary"
|
||||
id="visualizations.newHeatmapChart.conditionalMessage.newLibrary"
|
||||
defaultMessage="Switch to the old library in {link}"
|
||||
values={{
|
||||
link: (
|
||||
<EuiLink href={advancedSettingsLink}>
|
||||
<FormattedMessage
|
||||
id="visualize.newHeatmapChart.conditionalMessage.advanced settings link"
|
||||
id="visualizations.newHeatmapChart.conditionalMessage.advancedSettingsLink"
|
||||
defaultMessage="Advanced Settings."
|
||||
/>
|
||||
</EuiLink>
|
||||
|
@ -49,7 +49,7 @@ export const SplitChartWarning = () => {
|
|||
)}
|
||||
{!canEditAdvancedSettings && (
|
||||
<FormattedMessage
|
||||
id="visualize.legacyCharts.conditionalMessage.noPermissions"
|
||||
id="visualizations.legacyCharts.conditionalMessage.noPermissions"
|
||||
defaultMessage="Contact your system administrator to switch to the old library."
|
||||
/>
|
||||
)}
|
|
@ -22,7 +22,7 @@ import {
|
|||
import { VisualizeServices } from '../types';
|
||||
import { VisualizeEditorCommon } from './visualize_editor_common';
|
||||
import { VisualizeAppProps } from '../app';
|
||||
import { VisualizeConstants } from '../..';
|
||||
import { VisualizeConstants } from '../../../common/constants';
|
||||
|
||||
export const VisualizeByValueEditor = ({ onAppLeave }: VisualizeAppProps) => {
|
||||
const [originatingApp, setOriginatingApp] = useState<string>();
|
|
@ -22,7 +22,7 @@ import {
|
|||
import { VisualizeServices } from '../types';
|
||||
import { VisualizeEditorCommon } from './visualize_editor_common';
|
||||
import { VisualizeAppProps } from '../app';
|
||||
import { VisualizeConstants } from '../..';
|
||||
import { VisualizeConstants } from '../../../common/constants';
|
||||
|
||||
export const VisualizeEditor = ({ onAppLeave }: VisualizeAppProps) => {
|
||||
const { id: visualizationIdFromUrl } = useParams<{ id: string }>();
|
|
@ -72,7 +72,7 @@ export const VisualizeEditorCommon = ({
|
|||
const newPath = `${urlFor(newObjectId!)}${services.history.location.search}`;
|
||||
await services.spaces.ui.redirectLegacyUrl(
|
||||
newPath,
|
||||
i18n.translate('visualize.legacyUrlConflict.objectNoun', {
|
||||
i18n.translate('visualizations.legacyUrlConflict.objectNoun', {
|
||||
defaultMessage: '{visName} visualization',
|
||||
values: {
|
||||
visName: visInstance?.vis?.type.title,
|
||||
|
@ -96,7 +96,7 @@ export const VisualizeEditorCommon = ({
|
|||
const otherObjectId = sharingSavedObjectProps?.aliasTargetId!; // This is always defined if outcome === 'conflict'
|
||||
const otherObjectPath = `${urlFor(otherObjectId)}${services.history.location.search}`;
|
||||
return services.spaces.ui.components.getLegacyUrlConflict({
|
||||
objectNoun: i18n.translate('visualize.legacyUrlConflict.objectNoun', {
|
||||
objectNoun: i18n.translate('visualizations.legacyUrlConflict.objectNoun', {
|
||||
defaultMessage: '{visName} visualization',
|
||||
values: {
|
||||
visName: visInstance?.vis?.type.title,
|
||||
|
@ -144,7 +144,7 @@ export const VisualizeEditorCommon = ({
|
|||
<h1>
|
||||
{'savedVis' in visInstance && visInstance.savedVis.id ? (
|
||||
<FormattedMessage
|
||||
id="visualize.pageHeading"
|
||||
id="visualizations.pageHeading"
|
||||
defaultMessage="{chartName} {chartType} visualization"
|
||||
values={{
|
||||
chartName: (visInstance as SavedVisInstance).savedVis.title,
|
||||
|
@ -153,7 +153,7 @@ export const VisualizeEditorCommon = ({
|
|||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="visualize.byValue_pageHeading"
|
||||
id="visualizations.byValue_pageHeading"
|
||||
defaultMessage="Visualization of type {chartType} embedded into {originatingApp} app"
|
||||
values={{
|
||||
chartType: visInstance.vis.type.title,
|
|
@ -17,11 +17,14 @@ import useMount from 'react-use/lib/useMount';
|
|||
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
import { findListItems } from '../../utils/saved_visualize_utils';
|
||||
import { showNewVisModal } from '../../wizard';
|
||||
import { getTypes } from '../../services';
|
||||
import { SavedObjectsFindOptionsReference } from '../../../../../core/public';
|
||||
import { useKibana, TableListView } from '../../../../kibana_react/public';
|
||||
import { VISUALIZE_ENABLE_LABS_SETTING } from '../../../../visualizations/public';
|
||||
import { VisualizeServices } from '../types';
|
||||
import { VisualizeConstants } from '../visualize_constants';
|
||||
import { VisualizeConstants } from '../../../common/constants';
|
||||
import { getTableColumns, getNoItemsMessage } from '../utils';
|
||||
|
||||
export const VisualizeListing = () => {
|
||||
|
@ -29,10 +32,8 @@ export const VisualizeListing = () => {
|
|||
services: {
|
||||
application,
|
||||
chrome,
|
||||
dashboard,
|
||||
history,
|
||||
toastNotifications,
|
||||
visualizations,
|
||||
stateTransferService,
|
||||
savedObjects,
|
||||
savedObjectsPublic,
|
||||
|
@ -50,7 +51,7 @@ export const VisualizeListing = () => {
|
|||
useEffect(() => {
|
||||
if (pathname === '/new') {
|
||||
// In case the user navigated to the page via the /visualize/new URL we start the dialog immediately
|
||||
closeNewVisModal.current = visualizations.showNewVisModal({
|
||||
closeNewVisModal.current = showNewVisModal({
|
||||
onClose: () => {
|
||||
// In case the user came via a URL to this page, change the URL to the regular landing page URL after closing the modal
|
||||
history.push(VisualizeConstants.LANDING_PAGE_PATH);
|
||||
|
@ -60,27 +61,27 @@ export const VisualizeListing = () => {
|
|||
// close modal window if exists
|
||||
closeNewVisModal.current();
|
||||
}
|
||||
}, [history, pathname, visualizations]);
|
||||
}, [history, pathname]);
|
||||
|
||||
useMount(() => {
|
||||
// Reset editor state for all apps if the visualize listing page is loaded.
|
||||
stateTransferService.clearEditorState();
|
||||
chrome.setBreadcrumbs([
|
||||
{
|
||||
text: i18n.translate('visualize.visualizeListingBreadcrumbsTitle', {
|
||||
text: i18n.translate('visualizations.visualizeListingBreadcrumbsTitle', {
|
||||
defaultMessage: 'Visualize Library',
|
||||
}),
|
||||
},
|
||||
]);
|
||||
chrome.docTitle.change(
|
||||
i18n.translate('visualize.listingPageTitle', { defaultMessage: 'Visualize Library' })
|
||||
i18n.translate('visualizations.listingPageTitle', { defaultMessage: 'Visualize Library' })
|
||||
);
|
||||
});
|
||||
useUnmount(() => closeNewVisModal.current());
|
||||
|
||||
const createNewVis = useCallback(() => {
|
||||
closeNewVisModal.current = visualizations.showNewVisModal();
|
||||
}, [visualizations]);
|
||||
closeNewVisModal.current = showNewVisModal();
|
||||
}, []);
|
||||
|
||||
const editItem = useCallback(
|
||||
({ editUrl, editApp }) => {
|
||||
|
@ -112,16 +113,18 @@ export const VisualizeListing = () => {
|
|||
}
|
||||
|
||||
const isLabsEnabled = uiSettings.get(VISUALIZE_ENABLE_LABS_SETTING);
|
||||
return visualizations
|
||||
.findListItems(searchTerm, listingLimit, references)
|
||||
.then(({ total, hits }: { total: number; hits: Array<Record<string, unknown>> }) => ({
|
||||
total,
|
||||
hits: hits.filter(
|
||||
(result: any) => isLabsEnabled || result.type?.stage !== 'experimental'
|
||||
),
|
||||
}));
|
||||
return findListItems(
|
||||
savedObjects.client,
|
||||
getTypes(),
|
||||
searchTerm,
|
||||
listingLimit,
|
||||
references
|
||||
).then(({ total, hits }: { total: number; hits: Array<Record<string, unknown>> }) => ({
|
||||
total,
|
||||
hits: hits.filter((result: any) => isLabsEnabled || result.type?.stage !== 'experimental'),
|
||||
}));
|
||||
},
|
||||
[listingLimit, uiSettings, savedObjectsTagging, visualizations]
|
||||
[listingLimit, uiSettings, savedObjectsTagging, savedObjects.client]
|
||||
);
|
||||
|
||||
const deleteItems = useCallback(
|
||||
|
@ -130,7 +133,7 @@ export const VisualizeListing = () => {
|
|||
selectedItems.map((item: any) => savedObjects.client.delete(item.savedObjectType, item.id))
|
||||
).catch((error) => {
|
||||
toastNotifications.addError(error, {
|
||||
title: i18n.translate('visualize.visualizeListingDeleteErrorTitle', {
|
||||
title: i18n.translate('visualizations.visualizeListingDeleteErrorTitle', {
|
||||
defaultMessage: 'Error deleting visualization',
|
||||
}),
|
||||
});
|
||||
|
@ -148,7 +151,7 @@ export const VisualizeListing = () => {
|
|||
const calloutMessage = (
|
||||
<FormattedMessage
|
||||
data-test-subj="visualize-dashboard-flow-prompt"
|
||||
id="visualize.visualizeListingDashboardFlowDescription"
|
||||
id="visualizations.visualizeListingDashboardFlowDescription"
|
||||
defaultMessage="Building a dashboard? Create and add your visualizations right from the {dashboardApp}."
|
||||
values={{
|
||||
dashboardApp: (
|
||||
|
@ -160,7 +163,7 @@ export const VisualizeListing = () => {
|
|||
}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="visualize.visualizeListingDashboardAppName"
|
||||
id="visualizations.visualizeListingDashboardAppName"
|
||||
defaultMessage="Dashboard application"
|
||||
/>
|
||||
</EuiLink>
|
||||
|
@ -175,7 +178,7 @@ export const VisualizeListing = () => {
|
|||
// we allow users to create visualizations even if they can't save them
|
||||
// for data exploration purposes
|
||||
createItem={createNewVis}
|
||||
tableCaption={i18n.translate('visualize.listing.table.listTitle', {
|
||||
tableCaption={i18n.translate('visualizations.listing.table.listTitle', {
|
||||
defaultMessage: 'Visualize Library',
|
||||
})}
|
||||
findItems={fetchItems}
|
||||
|
@ -187,25 +190,24 @@ export const VisualizeListing = () => {
|
|||
initialFilter={''}
|
||||
rowHeader="title"
|
||||
emptyPrompt={noItemsFragment}
|
||||
entityName={i18n.translate('visualize.listing.table.entityName', {
|
||||
entityName={i18n.translate('visualizations.listing.table.entityName', {
|
||||
defaultMessage: 'visualization',
|
||||
})}
|
||||
entityNamePlural={i18n.translate('visualize.listing.table.entityNamePlural', {
|
||||
entityNamePlural={i18n.translate('visualizations.listing.table.entityNamePlural', {
|
||||
defaultMessage: 'visualizations',
|
||||
})}
|
||||
tableListTitle={i18n.translate('visualize.listing.table.listTitle', {
|
||||
tableListTitle={i18n.translate('visualizations.listing.table.listTitle', {
|
||||
defaultMessage: 'Visualize Library',
|
||||
})}
|
||||
toastNotifications={toastNotifications}
|
||||
searchFilters={searchFilters}
|
||||
>
|
||||
{dashboard.dashboardFeatureFlagConfig.allowByValueEmbeddables &&
|
||||
dashboardCapabilities.createNew && (
|
||||
<>
|
||||
<EuiCallOut size="s" title={calloutMessage} iconType="iInCircle" />
|
||||
<EuiSpacer size="m" />
|
||||
</>
|
||||
)}
|
||||
{dashboardCapabilities.createNew && (
|
||||
<>
|
||||
<EuiCallOut size="s" title={calloutMessage} iconType="iInCircle" />
|
||||
<EuiSpacer size="m" />
|
||||
</>
|
||||
)}
|
||||
</TableListView>
|
||||
);
|
||||
};
|
|
@ -13,7 +13,7 @@ import { EuiCallOut, EuiLink } from '@elastic/eui';
|
|||
|
||||
import { useKibana, toMountPoint, KibanaThemeProvider } from '../../../../kibana_react/public';
|
||||
import { VisualizeServices } from '../types';
|
||||
import { VisualizeConstants } from '../visualize_constants';
|
||||
import { VisualizeConstants } from '../../../common/constants';
|
||||
|
||||
let bannerId: string;
|
||||
|
||||
|
@ -28,7 +28,7 @@ export const VisualizeNoMatch = () => {
|
|||
);
|
||||
|
||||
if (!navigated) {
|
||||
const bannerMessage = i18n.translate('visualize.noMatchRoute.bannerTitleText', {
|
||||
const bannerMessage = i18n.translate('visualizations.noMatchRoute.bannerTitleText', {
|
||||
defaultMessage: 'Page not found',
|
||||
});
|
||||
|
||||
|
@ -39,7 +39,7 @@ export const VisualizeNoMatch = () => {
|
|||
<EuiCallOut color="warning" iconType="iInCircle" title={bannerMessage}>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="visualize.noMatchRoute.bannerText"
|
||||
id="visualizations.noMatchRoute.bannerText"
|
||||
defaultMessage="Visualize application doesn't recognize this route: {route}."
|
||||
values={{
|
||||
route: (
|
|
@ -17,7 +17,7 @@ import {
|
|||
VisualizeAppStateContainer,
|
||||
VisualizeEditorVisInstance,
|
||||
} from '../types';
|
||||
import { APP_NAME } from '../visualize_constants';
|
||||
import { VISUALIZE_APP_NAME } from '../../../common/constants';
|
||||
import { getTopNavConfig } from '../utils';
|
||||
import type { IndexPattern } from '../../../../data/public';
|
||||
|
||||
|
@ -146,10 +146,10 @@ const TopNav = ({
|
|||
!services.stateTransferService.isTransferInProgress
|
||||
) {
|
||||
return actions.confirm(
|
||||
i18n.translate('visualize.confirmModal.confirmTextDescription', {
|
||||
i18n.translate('visualizations.confirmModal.confirmTextDescription', {
|
||||
defaultMessage: 'Leave Visualize editor with unsaved changes?',
|
||||
}),
|
||||
i18n.translate('visualize.confirmModal.title', {
|
||||
i18n.translate('visualizations.confirmModal.title', {
|
||||
defaultMessage: 'Unsaved changes',
|
||||
})
|
||||
);
|
||||
|
@ -216,7 +216,7 @@ const TopNav = ({
|
|||
* it is enabled by default in the TopNavMenu component.
|
||||
*/
|
||||
<TopNavMenu
|
||||
appName={APP_NAME}
|
||||
appName={VISUALIZE_APP_NAME}
|
||||
config={config}
|
||||
setMenuMountPoint={setHeaderActionMenu}
|
||||
onQuerySubmit={handleRefresh}
|
||||
|
@ -238,7 +238,7 @@ const TopNav = ({
|
|||
* we show the filter bar on its own here if the chrome is not visible.
|
||||
*/
|
||||
<TopNavMenu
|
||||
appName={APP_NAME}
|
||||
appName={VISUALIZE_APP_NAME}
|
||||
setMenuMountPoint={setHeaderActionMenu}
|
||||
indexPatterns={indexPatterns}
|
||||
showSearchBar
|
|
@ -20,7 +20,6 @@ import type {
|
|||
} from 'kibana/public';
|
||||
|
||||
import type {
|
||||
VisualizationsStart,
|
||||
Vis,
|
||||
VisualizeEmbeddableContract,
|
||||
VisSavedObject,
|
||||
|
@ -35,7 +34,7 @@ import type {
|
|||
} from 'src/plugins/kibana_utils/public';
|
||||
|
||||
import type { NavigationPublicPluginStart as NavigationStart } from 'src/plugins/navigation/public';
|
||||
import { Filter } from '@kbn/es-query';
|
||||
import type { Filter } from '@kbn/es-query';
|
||||
import type { Query, DataPublicPluginStart, TimeRange } from 'src/plugins/data/public';
|
||||
import type { SharePluginStart } from 'src/plugins/share/public';
|
||||
import type { SavedObjectsStart } from 'src/plugins/saved_objects/public';
|
||||
|
@ -43,17 +42,18 @@ import type { EmbeddableStart, EmbeddableStateTransfer } from 'src/plugins/embed
|
|||
import type { UrlForwardingStart } from 'src/plugins/url_forwarding/public';
|
||||
import type { PresentationUtilPluginStart } from 'src/plugins/presentation_util/public';
|
||||
import type { SpacesPluginStart } from '../../../../../x-pack/plugins/spaces/public';
|
||||
import type { DashboardStart } from '../../../dashboard/public';
|
||||
import type { SavedObjectsTaggingApi } from '../../../saved_objects_tagging_oss/public';
|
||||
import type { UsageCollectionStart } from '../../../usage_collection/public';
|
||||
import type { SavedSearch } from '../../../discover/public';
|
||||
|
||||
import { PureVisState } from '../../common/types';
|
||||
import type { SavedVisState } from '../types';
|
||||
import type { createVisEmbeddableFromObject } from '../embeddable';
|
||||
import type { VisEditorsRegistry } from '../vis_editors_registry';
|
||||
|
||||
export interface VisualizeAppState {
|
||||
filters: Filter[];
|
||||
uiState: SerializableRecord;
|
||||
vis: PureVisState;
|
||||
vis: SavedVisState;
|
||||
query: Query;
|
||||
savedQuery?: string;
|
||||
linked: boolean;
|
||||
|
@ -66,11 +66,11 @@ export interface VisualizeAppStateTransitions {
|
|||
prop: T,
|
||||
value: VisualizeAppState[T]
|
||||
) => VisualizeAppState;
|
||||
setVis: (state: VisualizeAppState) => (vis: Partial<PureVisState>) => VisualizeAppState;
|
||||
setVis: (state: VisualizeAppState) => (vis: Partial<SavedVisState>) => VisualizeAppState;
|
||||
unlinkSavedSearch: (
|
||||
state: VisualizeAppState
|
||||
) => ({ query, parentFilters }: { query?: Query; parentFilters?: Filter[] }) => VisualizeAppState;
|
||||
updateVisState: (state: VisualizeAppState) => (vis: PureVisState) => VisualizeAppState;
|
||||
updateVisState: (state: VisualizeAppState) => (vis: SavedVisState) => VisualizeAppState;
|
||||
updateSavedQuery: (state: VisualizeAppState) => (savedQueryId?: string) => VisualizeAppState;
|
||||
}
|
||||
|
||||
|
@ -94,19 +94,18 @@ export interface VisualizeServices extends CoreStart {
|
|||
share?: SharePluginStart;
|
||||
visualizeCapabilities: Record<string, boolean | Record<string, boolean>>;
|
||||
dashboardCapabilities: Record<string, boolean | Record<string, boolean>>;
|
||||
visualizations: VisualizationsStart;
|
||||
savedObjectsPublic: SavedObjectsStart;
|
||||
setActiveUrl: (newUrl: string) => void;
|
||||
createVisEmbeddableFromObject: VisualizationsStart['__LEGACY']['createVisEmbeddableFromObject'];
|
||||
createVisEmbeddableFromObject: ReturnType<typeof createVisEmbeddableFromObject>;
|
||||
restorePreviousUrl: () => void;
|
||||
scopedHistory: ScopedHistory;
|
||||
dashboard: DashboardStart;
|
||||
setHeaderActionMenu: AppMountParameters['setHeaderActionMenu'];
|
||||
savedObjectsTagging?: SavedObjectsTaggingApi;
|
||||
presentationUtil: PresentationUtilPluginStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
getKibanaVersion: () => string;
|
||||
spaces?: SpacesPluginStart;
|
||||
visEditorsRegistry: VisEditorsRegistry;
|
||||
}
|
||||
|
||||
export interface VisInstance {
|
||||
|
@ -145,5 +144,3 @@ export interface EditorRenderProps {
|
|||
*/
|
||||
linked: boolean;
|
||||
}
|
||||
|
||||
export type { PureVisState };
|
|
@ -8,16 +8,16 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { VisualizeConstants } from '../visualize_constants';
|
||||
import { VisualizeConstants } from '../../../common/constants';
|
||||
|
||||
const defaultEditText = i18n.translate('visualize.editor.defaultEditBreadcrumbText', {
|
||||
const defaultEditText = i18n.translate('visualizations.editor.defaultEditBreadcrumbText', {
|
||||
defaultMessage: 'Edit visualization',
|
||||
});
|
||||
|
||||
export function getLandingBreadcrumbs() {
|
||||
return [
|
||||
{
|
||||
text: i18n.translate('visualize.listing.breadcrumb', {
|
||||
text: i18n.translate('visualizations.listing.breadcrumb', {
|
||||
defaultMessage: 'Visualize Library',
|
||||
}),
|
||||
href: `#${VisualizeConstants.LANDING_PAGE_PATH}`,
|
||||
|
@ -38,7 +38,7 @@ export function getCreateBreadcrumbs({
|
|||
...(originatingAppName ? [{ text: originatingAppName, onClick: redirectToOrigin }] : []),
|
||||
...(!byValue ? getLandingBreadcrumbs() : []),
|
||||
{
|
||||
text: i18n.translate('visualize.editor.createBreadcrumb', {
|
||||
text: i18n.translate('visualizations.editor.createBreadcrumb', {
|
||||
defaultMessage: 'Create',
|
||||
}),
|
||||
},
|
|
@ -14,7 +14,8 @@ import {
|
|||
syncState,
|
||||
IKbnUrlStateStorage,
|
||||
} from '../../../../kibana_utils/public';
|
||||
import { PureVisState, VisualizeAppState, VisualizeAppStateTransitions } from '../types';
|
||||
import type { SavedVisState } from '../../types';
|
||||
import type { VisualizeAppState, VisualizeAppStateTransitions } from '../types';
|
||||
|
||||
const STATE_STORAGE_KEY = '_a';
|
||||
|
||||
|
@ -24,10 +25,10 @@ interface Arguments {
|
|||
byValue?: boolean;
|
||||
}
|
||||
|
||||
function toObject(state: PureVisState): PureVisState {
|
||||
function toObject(state: SavedVisState): SavedVisState {
|
||||
return omitBy(state, (value, key: string) => {
|
||||
return key.charAt(0) === '$' || key.charAt(0) === '_' || isFunction(value);
|
||||
}) as PureVisState;
|
||||
}) as SavedVisState;
|
||||
}
|
||||
|
||||
const pureTransitions = {
|
|
@ -26,13 +26,13 @@ import type { SavedObjectsTaggingApi } from 'src/plugins/saved_objects_tagging_o
|
|||
import { RedirectAppLinks } from '../../../../kibana_react/public';
|
||||
import { getVisualizeListItemLink } from './get_visualize_list_item_link';
|
||||
import { getUsageCollector } from '../../services';
|
||||
import { APP_NAME } from '../visualize_constants';
|
||||
import { VISUALIZE_APP_NAME } from '../../../common/constants';
|
||||
|
||||
const doTelemetryForAddEvent = (visType?: string) => {
|
||||
const usageCollection = getUsageCollector();
|
||||
|
||||
if (usageCollection && visType) {
|
||||
usageCollection.reportUiCounter(APP_NAME, METRIC_TYPE.CLICK, `${visType}:add`);
|
||||
usageCollection.reportUiCounter(VISUALIZE_APP_NAME, METRIC_TYPE.CLICK, `${visType}:add`);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -42,10 +42,10 @@ const getBadge = (item: VisualizationListItem) => {
|
|||
<EuiBetaBadge
|
||||
className="visListingTable__betaIcon"
|
||||
label="B"
|
||||
title={i18n.translate('visualize.listing.betaTitle', {
|
||||
title={i18n.translate('visualizations.listing.betaTitle', {
|
||||
defaultMessage: 'Beta',
|
||||
})}
|
||||
tooltipContent={i18n.translate('visualize.listing.betaTooltip', {
|
||||
tooltipContent={i18n.translate('visualizations.listing.betaTooltip', {
|
||||
defaultMessage:
|
||||
'This visualization is in beta and is subject to change. The design and code is less mature than official GA ' +
|
||||
'features and is being provided as-is with no warranties. Beta features are not subject to the support SLA of official GA ' +
|
||||
|
@ -58,10 +58,10 @@ const getBadge = (item: VisualizationListItem) => {
|
|||
<EuiBetaBadge
|
||||
className="visListingTable__experimentalIcon"
|
||||
label="E"
|
||||
title={i18n.translate('visualize.listing.experimentalTitle', {
|
||||
title={i18n.translate('visualizations.listing.experimentalTitle', {
|
||||
defaultMessage: 'Experimental',
|
||||
})}
|
||||
tooltipContent={i18n.translate('visualize.listing.experimentalTooltip', {
|
||||
tooltipContent={i18n.translate('visualizations.listing.experimentalTooltip', {
|
||||
defaultMessage:
|
||||
'This visualization might be changed or removed in a future release and is not subject to the support SLA.',
|
||||
})}
|
||||
|
@ -98,7 +98,7 @@ export const getTableColumns = (
|
|||
[
|
||||
{
|
||||
field: 'title',
|
||||
name: i18n.translate('visualize.listing.table.titleColumnName', {
|
||||
name: i18n.translate('visualizations.listing.table.titleColumnName', {
|
||||
defaultMessage: 'Title',
|
||||
}),
|
||||
sortable: true,
|
||||
|
@ -123,7 +123,7 @@ export const getTableColumns = (
|
|||
},
|
||||
{
|
||||
field: 'typeTitle',
|
||||
name: i18n.translate('visualize.listing.table.typeColumnName', {
|
||||
name: i18n.translate('visualizations.listing.table.typeColumnName', {
|
||||
defaultMessage: 'Type',
|
||||
}),
|
||||
sortable: true,
|
||||
|
@ -142,7 +142,7 @@ export const getTableColumns = (
|
|||
},
|
||||
{
|
||||
field: 'description',
|
||||
name: i18n.translate('visualize.listing.table.descriptionColumnName', {
|
||||
name: i18n.translate('visualizations.listing.table.descriptionColumnName', {
|
||||
defaultMessage: 'Description',
|
||||
}),
|
||||
sortable: true,
|
||||
|
@ -157,7 +157,7 @@ export const getNoItemsMessage = (createItem: () => void) => (
|
|||
title={
|
||||
<h1 id="visualizeListingHeading">
|
||||
<FormattedMessage
|
||||
id="visualize.listing.createNew.title"
|
||||
id="visualizations.listing.createNew.title"
|
||||
defaultMessage="Create your first visualization"
|
||||
/>
|
||||
</h1>
|
||||
|
@ -165,7 +165,7 @@ export const getNoItemsMessage = (createItem: () => void) => (
|
|||
body={
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="visualize.listing.createNew.description"
|
||||
id="visualizations.listing.createNew.description"
|
||||
defaultMessage="You can create different visualizations based on your data."
|
||||
/>
|
||||
</p>
|
||||
|
@ -178,7 +178,7 @@ export const getNoItemsMessage = (createItem: () => void) => (
|
|||
data-test-subj="createVisualizationPromptButton"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="visualize.listing.createNew.createButtonLabel"
|
||||
id="visualizations.listing.createNew.createButtonLabel"
|
||||
defaultMessage="Create new visualization"
|
||||
/>
|
||||
</EuiButton>
|
|
@ -73,11 +73,6 @@ describe('getTopNavConfig', () => {
|
|||
const share = sharePluginMock.createStartContract();
|
||||
const services = {
|
||||
...mockServices,
|
||||
dashboard: {
|
||||
dashboardFeatureFlagConfig: {
|
||||
allowByValueEmbeddables: true,
|
||||
},
|
||||
},
|
||||
visualizeCapabilities: {
|
||||
save: true,
|
||||
},
|
|
@ -14,6 +14,7 @@ import { parse } from 'query-string';
|
|||
|
||||
import { Capabilities } from 'src/core/public';
|
||||
import { TopNavMenuData } from 'src/plugins/navigation/public';
|
||||
import { saveVisualization } from '../../utils/saved_visualize_utils';
|
||||
import {
|
||||
VISUALIZE_EMBEDDABLE_TYPE,
|
||||
VisualizeInput,
|
||||
|
@ -36,7 +37,7 @@ import {
|
|||
VisualizeAppStateContainer,
|
||||
VisualizeEditorVisInstance,
|
||||
} from '../types';
|
||||
import { APP_NAME, VisualizeConstants } from '../visualize_constants';
|
||||
import { VISUALIZE_APP_NAME, VisualizeConstants } from '../../../common/constants';
|
||||
import { getEditBreadcrumbs } from './breadcrumbs';
|
||||
import { EmbeddableStateTransfer } from '../../../../embeddable/public';
|
||||
import { VISUALIZE_APP_LOCATOR, VisualizeLocatorParams } from '../../../common/locator';
|
||||
|
@ -101,13 +102,11 @@ export const getTopNavConfig = (
|
|||
visualizeCapabilities,
|
||||
dashboardCapabilities,
|
||||
i18n: { Context: I18nContext },
|
||||
dashboard,
|
||||
savedObjectsTagging,
|
||||
presentationUtil,
|
||||
usageCollection,
|
||||
getKibanaVersion,
|
||||
savedObjects,
|
||||
visualizations,
|
||||
}: VisualizeServices
|
||||
) => {
|
||||
const { vis, embeddableHandler } = visInstance;
|
||||
|
@ -116,7 +115,7 @@ export const getTopNavConfig = (
|
|||
const doTelemetryForSaveEvent = (visType: string) => {
|
||||
if (usageCollection) {
|
||||
usageCollection.reportUiCounter(
|
||||
originatingApp ?? APP_NAME,
|
||||
originatingApp ?? VISUALIZE_APP_NAME,
|
||||
METRIC_TYPE.CLICK,
|
||||
`${visType}:save`
|
||||
);
|
||||
|
@ -140,16 +139,23 @@ export const getTopNavConfig = (
|
|||
setHasUnsavedChanges(false);
|
||||
|
||||
try {
|
||||
const id = await visualizations.saveVisualization(savedVis, saveOptions);
|
||||
const id = await saveVisualization(savedVis, saveOptions, {
|
||||
savedObjectsClient: savedObjects.client,
|
||||
overlays,
|
||||
savedObjectsTagging,
|
||||
});
|
||||
|
||||
if (id) {
|
||||
toastNotifications.addSuccess({
|
||||
title: i18n.translate('visualize.topNavMenu.saveVisualization.successNotificationText', {
|
||||
defaultMessage: `Saved '{visTitle}'`,
|
||||
values: {
|
||||
visTitle: savedVis.title,
|
||||
},
|
||||
}),
|
||||
title: i18n.translate(
|
||||
'visualizations.topNavMenu.saveVisualization.successNotificationText',
|
||||
{
|
||||
defaultMessage: `Saved '{visTitle}'`,
|
||||
values: {
|
||||
visTitle: savedVis.title,
|
||||
},
|
||||
}
|
||||
),
|
||||
'data-test-subj': 'saveVisualizationSuccess',
|
||||
});
|
||||
|
||||
|
@ -210,12 +216,15 @@ export const getTopNavConfig = (
|
|||
// eslint-disable-next-line
|
||||
console.error(error);
|
||||
toastNotifications.addDanger({
|
||||
title: i18n.translate('visualize.topNavMenu.saveVisualization.failureNotificationText', {
|
||||
defaultMessage: `Error on saving '{visTitle}'`,
|
||||
values: {
|
||||
visTitle: savedVis.title,
|
||||
},
|
||||
}),
|
||||
title: i18n.translate(
|
||||
'visualizations.topNavMenu.saveVisualization.failureNotificationText',
|
||||
{
|
||||
defaultMessage: `Error on saving '{visTitle}'`,
|
||||
values: {
|
||||
visTitle: savedVis.title,
|
||||
},
|
||||
}
|
||||
),
|
||||
text: error.message,
|
||||
'data-test-subj': 'saveVisualizationError',
|
||||
});
|
||||
|
@ -246,32 +255,29 @@ export const getTopNavConfig = (
|
|||
}
|
||||
};
|
||||
|
||||
const allowByValue = dashboard.dashboardFeatureFlagConfig.allowByValueEmbeddables;
|
||||
const saveButtonLabel =
|
||||
!savedVis.id && allowByValue && originatingApp
|
||||
? i18n.translate('visualize.topNavMenu.saveVisualizationToLibraryButtonLabel', {
|
||||
!savedVis.id && originatingApp
|
||||
? i18n.translate('visualizations.topNavMenu.saveVisualizationToLibraryButtonLabel', {
|
||||
defaultMessage: 'Save to library',
|
||||
})
|
||||
: originatingApp && savedVis.id
|
||||
? i18n.translate('visualize.topNavMenu.saveVisualizationAsButtonLabel', {
|
||||
? i18n.translate('visualizations.topNavMenu.saveVisualizationAsButtonLabel', {
|
||||
defaultMessage: 'Save as',
|
||||
})
|
||||
: i18n.translate('visualize.topNavMenu.saveVisualizationButtonLabel', {
|
||||
: i18n.translate('visualizations.topNavMenu.saveVisualizationButtonLabel', {
|
||||
defaultMessage: 'Save',
|
||||
});
|
||||
const showSaveAndReturn = originatingApp && (savedVis?.id || allowByValue);
|
||||
|
||||
const showSaveButton =
|
||||
visualizeCapabilities.save ||
|
||||
(allowByValue && !showSaveAndReturn && dashboardCapabilities.showWriteControls);
|
||||
visualizeCapabilities.save || (!originatingApp && dashboardCapabilities.showWriteControls);
|
||||
|
||||
const topNavMenu: TopNavMenuData[] = [
|
||||
{
|
||||
id: 'inspector',
|
||||
label: i18n.translate('visualize.topNavMenu.openInspectorButtonLabel', {
|
||||
label: i18n.translate('visualizations.topNavMenu.openInspectorButtonLabel', {
|
||||
defaultMessage: 'inspect',
|
||||
}),
|
||||
description: i18n.translate('visualize.topNavMenu.openInspectorButtonAriaLabel', {
|
||||
description: i18n.translate('visualizations.topNavMenu.openInspectorButtonAriaLabel', {
|
||||
defaultMessage: 'Open Inspector for visualization',
|
||||
}),
|
||||
testId: 'openInspectorButton',
|
||||
|
@ -281,7 +287,7 @@ export const getTopNavConfig = (
|
|||
run: openInspector,
|
||||
tooltip() {
|
||||
if (!embeddableHandler.hasInspector || !embeddableHandler.hasInspector()) {
|
||||
return i18n.translate('visualize.topNavMenu.openInspectorDisabledButtonTooltip', {
|
||||
return i18n.translate('visualizations.topNavMenu.openInspectorDisabledButtonTooltip', {
|
||||
defaultMessage: `This visualization doesn't support any inspectors.`,
|
||||
});
|
||||
}
|
||||
|
@ -289,10 +295,10 @@ export const getTopNavConfig = (
|
|||
},
|
||||
{
|
||||
id: 'share',
|
||||
label: i18n.translate('visualize.topNavMenu.shareVisualizationButtonLabel', {
|
||||
label: i18n.translate('visualizations.topNavMenu.shareVisualizationButtonLabel', {
|
||||
defaultMessage: 'share',
|
||||
}),
|
||||
description: i18n.translate('visualize.topNavMenu.shareVisualizationButtonAriaLabel', {
|
||||
description: i18n.translate('visualizations.topNavMenu.shareVisualizationButtonAriaLabel', {
|
||||
defaultMessage: 'Share Visualization',
|
||||
}),
|
||||
testId: 'shareTopNavButton',
|
||||
|
@ -325,7 +331,7 @@ export const getTopNavConfig = (
|
|||
sharingData: {
|
||||
title:
|
||||
savedVis?.title ||
|
||||
i18n.translate('visualize.reporting.defaultReportTitle', {
|
||||
i18n.translate('visualizations.reporting.defaultReportTitle', {
|
||||
defaultMessage: 'Visualization [{date}]',
|
||||
values: { date: moment().toISOString(true) },
|
||||
}),
|
||||
|
@ -341,23 +347,23 @@ export const getTopNavConfig = (
|
|||
}
|
||||
},
|
||||
// disable the Share button if no action specified and fot byValue visualizations
|
||||
disableButton: !share || Boolean(!savedVis.id && allowByValue && originatingApp),
|
||||
disableButton: !share || Boolean(!savedVis.id && originatingApp),
|
||||
},
|
||||
...(originatingApp
|
||||
? [
|
||||
{
|
||||
id: 'cancel',
|
||||
label: i18n.translate('visualize.topNavMenu.cancelButtonLabel', {
|
||||
label: i18n.translate('visualizations.topNavMenu.cancelButtonLabel', {
|
||||
defaultMessage: 'Cancel',
|
||||
}),
|
||||
emphasize: false,
|
||||
description: i18n.translate('visualize.topNavMenu.cancelButtonAriaLabel', {
|
||||
description: i18n.translate('visualizations.topNavMenu.cancelButtonAriaLabel', {
|
||||
defaultMessage: 'Return to the last app without saving changes',
|
||||
}),
|
||||
testId: 'visualizeCancelAndReturnButton',
|
||||
tooltip() {
|
||||
if (hasUnappliedChanges || hasUnsavedChanges) {
|
||||
return i18n.translate('visualize.topNavMenu.cancelAndReturnButtonTooltip', {
|
||||
return i18n.translate('visualizations.topNavMenu.cancelAndReturnButtonTooltip', {
|
||||
defaultMessage: 'Discard your changes before finishing',
|
||||
});
|
||||
}
|
||||
|
@ -372,18 +378,21 @@ export const getTopNavConfig = (
|
|||
? [
|
||||
{
|
||||
id: 'save',
|
||||
iconType: showSaveAndReturn ? undefined : 'save',
|
||||
iconType: originatingApp ? undefined : 'save',
|
||||
label: saveButtonLabel,
|
||||
emphasize: !showSaveAndReturn,
|
||||
description: i18n.translate('visualize.topNavMenu.saveVisualizationButtonAriaLabel', {
|
||||
defaultMessage: 'Save Visualization',
|
||||
}),
|
||||
emphasize: !originatingApp,
|
||||
description: i18n.translate(
|
||||
'visualizations.topNavMenu.saveVisualizationButtonAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Save Visualization',
|
||||
}
|
||||
),
|
||||
testId: 'visualizeSaveButton',
|
||||
disableButton: hasUnappliedChanges,
|
||||
tooltip() {
|
||||
if (hasUnappliedChanges) {
|
||||
return i18n.translate(
|
||||
'visualize.topNavMenu.saveVisualizationDisabledButtonTooltip',
|
||||
'visualizations.topNavMenu.saveVisualizationDisabledButtonTooltip',
|
||||
{
|
||||
defaultMessage: 'Apply or Discard your changes before saving',
|
||||
}
|
||||
|
@ -483,26 +492,26 @@ export const getTopNavConfig = (
|
|||
);
|
||||
}
|
||||
|
||||
const useByRefFlow =
|
||||
!!originatingApp || !dashboard.dashboardFeatureFlagConfig.allowByValueEmbeddables;
|
||||
|
||||
let saveModal;
|
||||
|
||||
if (useByRefFlow) {
|
||||
if (originatingApp) {
|
||||
saveModal = (
|
||||
<SavedObjectSaveModalOrigin
|
||||
documentInfo={savedVis || { title: '' }}
|
||||
onSave={onSave}
|
||||
options={tagOptions}
|
||||
getAppNameFromId={stateTransfer.getAppNameFromId}
|
||||
objectType={i18n.translate('visualize.topNavMenu.saveVisualizationObjectType', {
|
||||
defaultMessage: 'visualization',
|
||||
})}
|
||||
objectType={i18n.translate(
|
||||
'visualizations.topNavMenu.saveVisualizationObjectType',
|
||||
{
|
||||
defaultMessage: 'visualization',
|
||||
}
|
||||
)}
|
||||
onClose={() => {}}
|
||||
originatingApp={originatingApp}
|
||||
returnToOriginSwitchLabel={
|
||||
originatingApp && embeddableId
|
||||
? i18n.translate('visualize.topNavMenu.updatePanel', {
|
||||
? i18n.translate('visualizations.topNavMenu.updatePanel', {
|
||||
defaultMessage: 'Update panel on {originatingAppName}',
|
||||
values: {
|
||||
originatingAppName: stateTransfer.getAppNameFromId(originatingApp),
|
||||
|
@ -523,9 +532,12 @@ export const getTopNavConfig = (
|
|||
canSaveByReference={Boolean(visualizeCapabilities.save)}
|
||||
onSave={onSave}
|
||||
tagOptions={tagOptions}
|
||||
objectType={i18n.translate('visualize.topNavMenu.saveVisualizationObjectType', {
|
||||
defaultMessage: 'visualization',
|
||||
})}
|
||||
objectType={i18n.translate(
|
||||
'visualizations.topNavMenu.saveVisualizationObjectType',
|
||||
{
|
||||
defaultMessage: 'visualization',
|
||||
}
|
||||
)}
|
||||
onClose={() => {}}
|
||||
/>
|
||||
);
|
||||
|
@ -534,23 +546,26 @@ export const getTopNavConfig = (
|
|||
showSaveModal(
|
||||
saveModal,
|
||||
I18nContext,
|
||||
!useByRefFlow ? presentationUtil.ContextProvider : React.Fragment
|
||||
!originatingApp ? presentationUtil.ContextProvider : React.Fragment
|
||||
);
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(showSaveAndReturn
|
||||
...(originatingApp
|
||||
? [
|
||||
{
|
||||
id: 'saveAndReturn',
|
||||
label: i18n.translate('visualize.topNavMenu.saveAndReturnVisualizationButtonLabel', {
|
||||
defaultMessage: 'Save and return',
|
||||
}),
|
||||
label: i18n.translate(
|
||||
'visualizations.topNavMenu.saveAndReturnVisualizationButtonLabel',
|
||||
{
|
||||
defaultMessage: 'Save and return',
|
||||
}
|
||||
),
|
||||
emphasize: true,
|
||||
iconType: 'checkInCircleFilled',
|
||||
description: i18n.translate(
|
||||
'visualize.topNavMenu.saveAndReturnVisualizationButtonAriaLabel',
|
||||
'visualizations.topNavMenu.saveAndReturnVisualizationButtonAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Finish editing visualization and return to the last app',
|
||||
}
|
||||
|
@ -560,7 +575,7 @@ export const getTopNavConfig = (
|
|||
tooltip() {
|
||||
if (hasUnappliedChanges) {
|
||||
return i18n.translate(
|
||||
'visualize.topNavMenu.saveAndReturnVisualizationDisabledButtonTooltip',
|
||||
'visualizations.topNavMenu.saveAndReturnVisualizationDisabledButtonTooltip',
|
||||
{
|
||||
defaultMessage: 'Apply or Discard your changes before finishing',
|
||||
}
|
|
@ -18,8 +18,30 @@ import {
|
|||
getVisualizationInstanceFromInput,
|
||||
} from './get_visualization_instance';
|
||||
import { createVisualizeServicesMock } from './mocks';
|
||||
import { VisualizeServices } from '../types';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import type { VisualizeServices } from '../types';
|
||||
|
||||
const commonSerializedVisMock = {
|
||||
type: 'area',
|
||||
aggs: [],
|
||||
};
|
||||
|
||||
jest.mock('../../utils/saved_visualize_utils', () => {
|
||||
const actual = jest.requireActual('../../utils/saved_visualize_utils');
|
||||
return {
|
||||
...actual,
|
||||
getSavedVisualization: jest.fn(),
|
||||
convertToSerializedVis: jest.fn().mockReturnValue(commonSerializedVisMock),
|
||||
};
|
||||
});
|
||||
const { getSavedVisualization, convertToSerializedVis } = jest.requireMock(
|
||||
'../../utils/saved_visualize_utils'
|
||||
);
|
||||
|
||||
jest.mock('../../vis_async', () => ({
|
||||
createVisAsync: jest.fn(),
|
||||
}));
|
||||
const { createVisAsync } = jest.requireMock('../../vis_async');
|
||||
|
||||
jest.mock('../../../../discover/public', () => ({
|
||||
getSavedSearch: jest.fn().mockResolvedValue({
|
||||
|
@ -33,9 +55,6 @@ jest.mock('../../../../discover/public', () => ({
|
|||
let savedVisMock: VisSavedObject;
|
||||
|
||||
describe('getVisualizationInstance', () => {
|
||||
const serializedVisMock = {
|
||||
type: 'area',
|
||||
};
|
||||
let visMock: Vis<VisParams>;
|
||||
let mockServices: jest.Mocked<VisualizeServices>;
|
||||
let subj: BehaviorSubject<any>;
|
||||
|
@ -49,18 +68,10 @@ describe('getVisualizationInstance', () => {
|
|||
} as Vis<VisParams>;
|
||||
savedVisMock = {} as VisSavedObject;
|
||||
|
||||
// @ts-expect-error
|
||||
mockServices.data.search.showError.mockImplementation(() => {});
|
||||
// @ts-expect-error
|
||||
mockServices.visualizations.convertToSerializedVis.mockImplementation(() => serializedVisMock);
|
||||
// @ts-expect-error
|
||||
mockServices.visualizations.getSavedVisualization.mockImplementation(
|
||||
(opts: unknown) => savedVisMock
|
||||
);
|
||||
// @ts-expect-error
|
||||
mockServices.visualizations.createVis.mockImplementation(() => visMock);
|
||||
// @ts-expect-error
|
||||
mockServices.createVisEmbeddableFromObject.mockImplementation(() => ({
|
||||
getSavedVisualization.mockImplementation((opts: unknown) => savedVisMock);
|
||||
createVisAsync.mockImplementation(() => visMock);
|
||||
mockServices.data.search.showError = jest.fn().mockImplementation(() => {});
|
||||
mockServices.createVisEmbeddableFromObject = jest.fn().mockImplementation(() => ({
|
||||
getOutput$: jest.fn(() => subj.asObservable()),
|
||||
}));
|
||||
});
|
||||
|
@ -75,16 +86,14 @@ describe('getVisualizationInstance', () => {
|
|||
opts
|
||||
);
|
||||
|
||||
expect((mockServices.visualizations.getSavedVisualization as jest.Mock).mock.calls[0][0]).toBe(
|
||||
opts
|
||||
);
|
||||
expect(getSavedVisualization.mock.calls[0][1]).toBe(opts);
|
||||
expect(savedVisMock.searchSourceFields).toEqual({
|
||||
index: opts.indexPattern,
|
||||
});
|
||||
expect(mockServices.visualizations.convertToSerializedVis).toHaveBeenCalledWith(savedVisMock);
|
||||
expect(mockServices.visualizations.createVis).toHaveBeenCalledWith(
|
||||
serializedVisMock.type,
|
||||
serializedVisMock
|
||||
expect(convertToSerializedVis).toHaveBeenCalledWith(savedVisMock);
|
||||
expect(createVisAsync).toHaveBeenCalledWith(
|
||||
commonSerializedVisMock.type,
|
||||
commonSerializedVisMock
|
||||
);
|
||||
expect(mockServices.createVisEmbeddableFromObject).toHaveBeenCalledWith(visMock, {
|
||||
searchSessionId: undefined,
|
||||
|
@ -106,9 +115,7 @@ describe('getVisualizationInstance', () => {
|
|||
visMock.type.setup = jest.fn(() => newVisObj);
|
||||
const { vis } = await getVisualizationInstance(mockServices, 'saved_vis_id');
|
||||
|
||||
expect((mockServices.visualizations.getSavedVisualization as jest.Mock).mock.calls[0][0]).toBe(
|
||||
'saved_vis_id'
|
||||
);
|
||||
expect(getSavedVisualization.mock.calls[1][1]).toBe('saved_vis_id');
|
||||
expect(savedVisMock.searchSourceFields).toBeUndefined();
|
||||
expect(visMock.type.setup).toHaveBeenCalledWith(visMock);
|
||||
expect(vis).toBe(newVisObj);
|
||||
|
@ -155,14 +162,10 @@ describe('getVisualizationInstanceInput', () => {
|
|||
data: {},
|
||||
} as Vis<VisParams>;
|
||||
savedVisMock = {} as VisSavedObject;
|
||||
// @ts-expect-error
|
||||
mockServices.visualizations.createVis.mockImplementation(() => visMock);
|
||||
// @ts-expect-error
|
||||
mockServices.visualizations.getSavedVisualization.mockImplementation(
|
||||
(opts: unknown) => savedVisMock
|
||||
);
|
||||
// @ts-expect-error
|
||||
mockServices.createVisEmbeddableFromObject.mockImplementation(() => ({
|
||||
|
||||
createVisAsync.mockImplementation(() => visMock);
|
||||
getSavedVisualization.mockImplementation((opts: unknown) => savedVisMock);
|
||||
mockServices.createVisEmbeddableFromObject = jest.fn().mockImplementation(() => ({
|
||||
getOutput$: jest.fn(() => subj.asObservable()),
|
||||
}));
|
||||
});
|
||||
|
@ -199,11 +202,8 @@ describe('getVisualizationInstanceInput', () => {
|
|||
const { savedVis, savedSearch, vis, embeddableHandler } =
|
||||
await getVisualizationInstanceFromInput(mockServices, input);
|
||||
|
||||
expect(mockServices.visualizations.getSavedVisualization).toHaveBeenCalled();
|
||||
expect(mockServices.visualizations.createVis).toHaveBeenCalledWith(
|
||||
serializedVisMock.type,
|
||||
input.savedVis
|
||||
);
|
||||
expect(getSavedVisualization).toHaveBeenCalled();
|
||||
expect(createVisAsync).toHaveBeenCalledWith(serializedVisMock.type, input.savedVis);
|
||||
expect(mockServices.createVisEmbeddableFromObject).toHaveBeenCalledWith(visMock, {
|
||||
searchSessionId: undefined,
|
||||
timeRange: undefined,
|
|
@ -13,16 +13,18 @@ import {
|
|||
VisualizeEmbeddableContract,
|
||||
VisualizeInput,
|
||||
} from 'src/plugins/visualizations/public';
|
||||
import { SerializedSearchSourceFields } from 'src/plugins/data/public';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { ExpressionValueError } from 'src/plugins/expressions/public';
|
||||
import type { SerializedSearchSourceFields } from 'src/plugins/data/public';
|
||||
import type { ExpressionValueError } from 'src/plugins/expressions/public';
|
||||
import { createVisAsync } from '../../vis_async';
|
||||
import { convertToSerializedVis, getSavedVisualization } from '../../utils/saved_visualize_utils';
|
||||
import { SavedFieldNotFound, SavedFieldTypeInvalidForAgg } from '../../../../kibana_utils/common';
|
||||
import {
|
||||
getSavedSearch,
|
||||
SavedSearch,
|
||||
throwErrorOnSavedSearchUrlConflict,
|
||||
} from '../../../../discover/public';
|
||||
import { SavedFieldNotFound, SavedFieldTypeInvalidForAgg } from '../../../../kibana_utils/common';
|
||||
import { VisualizeServices } from '../types';
|
||||
import type { VisualizeServices } from '../types';
|
||||
|
||||
function isErrorRelatedToRuntimeFields(error: ExpressionValueError['error']) {
|
||||
const originalError = error.original || error;
|
||||
|
@ -72,20 +74,26 @@ export const getVisualizationInstanceFromInput = async (
|
|||
visualizeServices: VisualizeServices,
|
||||
input: VisualizeInput
|
||||
) => {
|
||||
const { visualizations } = visualizeServices;
|
||||
const { data, savedObjects, spaces, savedObjectsTagging } = visualizeServices;
|
||||
const visState = input.savedVis as SerializedVis;
|
||||
|
||||
/**
|
||||
* A saved vis is needed even in by value mode to support 'save to library' which converts the 'by value'
|
||||
* state of the visualization, into a new saved object.
|
||||
*/
|
||||
const savedVis: VisSavedObject = await visualizations.getSavedVisualization();
|
||||
const savedVis: VisSavedObject = await getSavedVisualization({
|
||||
search: data.search,
|
||||
savedObjectsClient: savedObjects.client,
|
||||
dataViews: data.dataViews,
|
||||
spaces,
|
||||
savedObjectsTagging,
|
||||
});
|
||||
|
||||
if (visState.uiState && Object.keys(visState.uiState).length !== 0) {
|
||||
savedVis.uiStateJSON = JSON.stringify(visState.uiState);
|
||||
}
|
||||
|
||||
let vis = await visualizations.createVis(visState.type, cloneDeep(visState));
|
||||
let vis = await createVisAsync(visState.type, cloneDeep(visState));
|
||||
if (vis.type.setup) {
|
||||
try {
|
||||
vis = await vis.type.setup(vis);
|
||||
|
@ -114,14 +122,24 @@ export const getVisualizationInstance = async (
|
|||
*/
|
||||
opts?: Record<string, unknown> | string
|
||||
) => {
|
||||
const { visualizations } = visualizeServices;
|
||||
const savedVis: VisSavedObject = await visualizations.getSavedVisualization(opts);
|
||||
const { data, savedObjects, spaces, savedObjectsTagging } = visualizeServices;
|
||||
|
||||
const savedVis: VisSavedObject = await getSavedVisualization(
|
||||
{
|
||||
search: data.search,
|
||||
savedObjectsClient: savedObjects.client,
|
||||
dataViews: data.dataViews,
|
||||
spaces,
|
||||
savedObjectsTagging,
|
||||
},
|
||||
opts
|
||||
);
|
||||
|
||||
if (typeof opts !== 'string') {
|
||||
savedVis.searchSourceFields = { index: opts?.indexPattern } as SerializedSearchSourceFields;
|
||||
}
|
||||
const serializedVis = visualizations.convertToSerializedVis(savedVis);
|
||||
let vis = await visualizations.createVis(serializedVis.type, serializedVis);
|
||||
const serializedVis = convertToSerializedVis(savedVis);
|
||||
let vis = await createVisAsync(serializedVis.type, serializedVis);
|
||||
if (vis.type.setup) {
|
||||
try {
|
||||
vis = await vis.type.setup(vis);
|
|
@ -11,8 +11,7 @@ import { IKbnUrlStateStorage } from 'src/plugins/kibana_utils/public';
|
|||
import { QueryState } from '../../../../data/public';
|
||||
import { setStateToKbnUrl } from '../../../../kibana_utils/public';
|
||||
import { getUISettings } from '../../services';
|
||||
import { GLOBAL_STATE_STORAGE_KEY } from '../../../common/constants';
|
||||
import { APP_NAME } from '../visualize_constants';
|
||||
import { GLOBAL_STATE_STORAGE_KEY, VISUALIZE_APP_NAME } from '../../../common/constants';
|
||||
|
||||
export const getVisualizeListItemLink = (
|
||||
application: ApplicationStart,
|
||||
|
@ -21,7 +20,7 @@ export const getVisualizeListItemLink = (
|
|||
editUrl: string
|
||||
) => {
|
||||
// for visualizations the editApp is undefined
|
||||
let url = application.getUrlForApp(editApp ?? APP_NAME, {
|
||||
let url = application.getUrlForApp(editApp ?? VISUALIZE_APP_NAME, {
|
||||
path: editApp ? editUrl : `#${editUrl}`,
|
||||
});
|
||||
const useHash = getUISettings().get('state:storeInSessionStorage');
|
|
@ -8,14 +8,12 @@
|
|||
|
||||
import { coreMock } from '../../../../../core/public/mocks';
|
||||
import { dataPluginMock } from '../../../../data/public/mocks';
|
||||
import { visualizationsPluginMock } from '../../../../visualizations/public/mocks';
|
||||
import { VisualizeServices } from '../types';
|
||||
|
||||
export const createVisualizeServicesMock = () => {
|
||||
const coreStartMock = coreMock.createStart();
|
||||
const dataStartMock = dataPluginMock.createStartContract();
|
||||
const toastNotifications = coreStartMock.notifications.toasts;
|
||||
const visualizations = visualizationsPluginMock.createStartContract();
|
||||
|
||||
return {
|
||||
...coreStartMock,
|
||||
|
@ -25,7 +23,5 @@ export const createVisualizeServicesMock = () => {
|
|||
replace: jest.fn(),
|
||||
location: { pathname: '' },
|
||||
},
|
||||
visualizations,
|
||||
createVisEmbeddableFromObject: visualizations.__LEGACY.createVisEmbeddableFromObject,
|
||||
} as unknown as jest.Mocked<VisualizeServices>;
|
||||
};
|
|
@ -15,6 +15,11 @@ import type { IEditorController } from '../../types';
|
|||
import { visualizeAppStateStub } from '../stubs';
|
||||
import { createVisualizeServicesMock } from '../mocks';
|
||||
|
||||
jest.mock('../../../utils/saved_visualize_utils', () => {
|
||||
const stubs = jest.requireActual('../stubs');
|
||||
return { convertFromSerializedVis: () => ({ visState: stubs.visualizeAppStateStub.vis }) };
|
||||
});
|
||||
|
||||
describe('useEditorUpdates', () => {
|
||||
const eventEmitter = new EventEmitter();
|
||||
const setHasUnsavedChangesMock = jest.fn();
|
||||
|
@ -22,10 +27,6 @@ describe('useEditorUpdates', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
mockServices = createVisualizeServicesMock();
|
||||
// @ts-expect-error
|
||||
mockServices.visualizations.convertFromSerializedVis.mockImplementation(() => ({
|
||||
visState: visualizeAppStateStub.vis,
|
||||
}));
|
||||
});
|
||||
|
||||
test('should not create any subscriptions if app state container is not ready', () => {
|
|
@ -17,6 +17,7 @@ import {
|
|||
VisualizeEditorVisInstance,
|
||||
IEditorController,
|
||||
} from '../../types';
|
||||
import { convertFromSerializedVis } from '../../../utils/saved_visualize_utils';
|
||||
|
||||
export const useEditorUpdates = (
|
||||
services: VisualizeServices,
|
||||
|
@ -113,7 +114,7 @@ export const useEditorUpdates = (
|
|||
savedVis &&
|
||||
!isEqual(
|
||||
{
|
||||
...services.visualizations.convertFromSerializedVis(vis.serialize()).visState,
|
||||
...convertFromSerializedVis(vis.serialize()).visState,
|
||||
title: vis.title,
|
||||
},
|
||||
state.vis
|
|
@ -43,7 +43,7 @@ export const useLinkedSearchUpdates = (
|
|||
});
|
||||
|
||||
services.toastNotifications.addSuccess(
|
||||
i18n.translate('visualize.linkedToSearch.unlinkSuccessNotificationText', {
|
||||
i18n.translate('visualizations.linkedToSearch.unlinkSuccessNotificationText', {
|
||||
defaultMessage: `Unlinked from saved search '{searchTitle}'`,
|
||||
values: {
|
||||
searchTitle: savedSearch.title,
|
|
@ -9,15 +9,16 @@
|
|||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
import { setTypes } from '../../../services';
|
||||
import { coreMock } from '../../../../../../core/public/mocks';
|
||||
import { useSavedVisInstance } from './use_saved_vis_instance';
|
||||
import { redirectWhenMissing } from '../../../../../kibana_utils/public';
|
||||
import { getEditBreadcrumbs, getCreateBreadcrumbs } from '../breadcrumbs';
|
||||
import { VisualizeServices } from '../../types';
|
||||
import { VisualizeConstants } from '../../visualize_constants';
|
||||
import { setVisEditorsRegistry } from '../../../services';
|
||||
import { VisualizeConstants } from '../../../../common/constants';
|
||||
import { createVisEditorsRegistry } from '../../../vis_editors_registry';
|
||||
import { createEmbeddableStateTransferMock } from '../../../../../embeddable/public/mocks';
|
||||
import type { VisualizeServices } from '../../types';
|
||||
import type { TypesStart } from '../../../vis_types';
|
||||
|
||||
const mockDefaultEditorControllerDestroy = jest.fn();
|
||||
const mockEmbeddableHandlerDestroy = jest.fn();
|
||||
|
@ -40,6 +41,10 @@ const mockSavedVisInstance = {
|
|||
jest.mock('../get_visualization_instance', () => ({
|
||||
getVisualizationInstance: jest.fn(() => mockSavedVisInstance),
|
||||
}));
|
||||
const mockGetVisualizationInstance = jest.requireMock(
|
||||
'../get_visualization_instance'
|
||||
).getVisualizationInstance;
|
||||
|
||||
jest.mock('../breadcrumbs', () => ({
|
||||
getEditBreadcrumbs: jest.fn((args, title) => title),
|
||||
getCreateBreadcrumbs: jest.fn((text) => text),
|
||||
|
@ -53,28 +58,33 @@ jest.mock('../../../../../kibana_utils/public', () => {
|
|||
};
|
||||
});
|
||||
|
||||
const mockGetVisualizationInstance = jest.requireMock(
|
||||
'../get_visualization_instance'
|
||||
).getVisualizationInstance;
|
||||
|
||||
describe('useSavedVisInstance', () => {
|
||||
const coreStartMock = coreMock.createStart();
|
||||
const toastNotifications = coreStartMock.notifications.toasts;
|
||||
let mockServices: VisualizeServices;
|
||||
const eventEmitter = new EventEmitter();
|
||||
|
||||
beforeEach(() => {
|
||||
const registry = createVisEditorsRegistry();
|
||||
beforeAll(() => {
|
||||
setTypes({
|
||||
all: jest
|
||||
.fn()
|
||||
.mockReturnValue([
|
||||
{ name: 'area', requiresSearch: true, options: { showIndexSelection: true } },
|
||||
]),
|
||||
} as unknown as TypesStart);
|
||||
});
|
||||
|
||||
registry.registerDefault(
|
||||
beforeEach(() => {
|
||||
const visEditorsRegistry = createVisEditorsRegistry();
|
||||
|
||||
visEditorsRegistry.registerDefault(
|
||||
jest.fn().mockImplementation(() => ({ destroy: mockDefaultEditorControllerDestroy }))
|
||||
);
|
||||
|
||||
setVisEditorsRegistry(registry);
|
||||
|
||||
mockServices = {
|
||||
...coreStartMock,
|
||||
toastNotifications,
|
||||
visEditorsRegistry,
|
||||
stateTransferService: createEmbeddableStateTransferMock(),
|
||||
chrome: { setBreadcrumbs: jest.fn(), docTitle: { change: jest.fn() } },
|
||||
history: {
|
||||
|
@ -83,7 +93,6 @@ describe('useSavedVisInstance', () => {
|
|||
},
|
||||
replace: () => {},
|
||||
},
|
||||
dashboard: { dashboardFeatureFlagConfig: { allowByValueEmbeddables: false } },
|
||||
visualizations: {
|
||||
all: jest.fn(() => [
|
||||
{
|
|
@ -14,8 +14,8 @@ import { i18n } from '@kbn/i18n';
|
|||
import { getVisualizationInstance } from '../get_visualization_instance';
|
||||
import { getEditBreadcrumbs, getCreateBreadcrumbs } from '../breadcrumbs';
|
||||
import { SavedVisInstance, VisualizeServices, IEditorController } from '../../types';
|
||||
import { VisualizeConstants } from '../../visualize_constants';
|
||||
import { getVisEditorsRegistry } from '../../../services';
|
||||
import { VisualizeConstants } from '../../../../common/constants';
|
||||
import { getTypes } from '../../../services';
|
||||
import { redirectToSavedObjectPage } from '../utils';
|
||||
|
||||
/**
|
||||
|
@ -41,9 +41,9 @@ export const useSavedVisInstance = (
|
|||
const {
|
||||
chrome,
|
||||
history,
|
||||
dashboard,
|
||||
toastNotifications,
|
||||
stateTransferService,
|
||||
visEditorsRegistry,
|
||||
application: { navigateToApp },
|
||||
} = services;
|
||||
const getSavedVisInstance = async () => {
|
||||
|
@ -51,12 +51,13 @@ export const useSavedVisInstance = (
|
|||
let savedVisInstance: SavedVisInstance;
|
||||
if (history.location.pathname === '/create') {
|
||||
const searchParams = parse(history.location.search);
|
||||
const visTypes = services.visualizations.all();
|
||||
const visType = visTypes.find(({ name }) => name === searchParams.type);
|
||||
const visType = getTypes()
|
||||
.all()
|
||||
.find(({ name }) => name === searchParams.type);
|
||||
|
||||
if (!visType) {
|
||||
throw new Error(
|
||||
i18n.translate('visualize.createVisualization.noVisTypeErrorMessage', {
|
||||
i18n.translate('visualizations.createVisualization.noVisTypeErrorMessage', {
|
||||
defaultMessage: 'You must provide a valid visualization type',
|
||||
})
|
||||
);
|
||||
|
@ -68,7 +69,7 @@ export const useSavedVisInstance = (
|
|||
if (shouldHaveIndex && !hasIndex) {
|
||||
throw new Error(
|
||||
i18n.translate(
|
||||
'visualize.createVisualization.noIndexPatternOrSavedSearchIdErrorMessage',
|
||||
'visualizations.createVisualization.noIndexPatternOrSavedSearchIdErrorMessage',
|
||||
{
|
||||
defaultMessage: 'You must provide either an indexPattern or a savedSearchId',
|
||||
}
|
||||
|
@ -87,8 +88,6 @@ export const useSavedVisInstance = (
|
|||
? stateTransferService.getAppNameFromId(originatingApp)
|
||||
: undefined;
|
||||
const redirectToOrigin = originatingApp ? () => navigateToApp(originatingApp) : undefined;
|
||||
const byValueCreateMode =
|
||||
Boolean(originatingApp) && dashboard.dashboardFeatureFlagConfig.allowByValueEmbeddables;
|
||||
|
||||
if (savedVis.id) {
|
||||
chrome.setBreadcrumbs(
|
||||
|
@ -98,7 +97,7 @@ export const useSavedVisInstance = (
|
|||
} else {
|
||||
chrome.setBreadcrumbs(
|
||||
getCreateBreadcrumbs({
|
||||
byValue: byValueCreateMode,
|
||||
byValue: Boolean(originatingApp),
|
||||
originatingAppName,
|
||||
redirectToOrigin,
|
||||
})
|
||||
|
@ -109,7 +108,7 @@ export const useSavedVisInstance = (
|
|||
// do not create editor in embeded mode
|
||||
if (visEditorRef.current) {
|
||||
if (isChromeVisible) {
|
||||
const Editor = getVisEditorsRegistry().get(vis.type.editorConfig?.editor);
|
||||
const Editor = visEditorsRegistry.get(vis.type.editorConfig?.editor);
|
||||
|
||||
if (Editor) {
|
||||
visEditorController = new Editor(
|
||||
|
@ -132,7 +131,7 @@ export const useSavedVisInstance = (
|
|||
redirectToSavedObjectPage(services, error, visualizationIdFromUrl);
|
||||
} catch (e) {
|
||||
toastNotifications.addWarning({
|
||||
title: i18n.translate('visualize.createVisualization.failedToLoadErrorMessage', {
|
||||
title: i18n.translate('visualizations.createVisualization.failedToLoadErrorMessage', {
|
||||
defaultMessage: 'Failed to load the visualization',
|
||||
}),
|
||||
text: e.message,
|
|
@ -12,7 +12,6 @@ import { VisualizeInput } from 'src/plugins/visualizations/public';
|
|||
import { ByValueVisInstance, VisualizeServices, IEditorController } from '../../types';
|
||||
import { getVisualizationInstanceFromInput } from '../get_visualization_instance';
|
||||
import { getEditBreadcrumbs } from '../breadcrumbs';
|
||||
import { getVisEditorsRegistry } from '../../../services';
|
||||
|
||||
export const useVisByValue = (
|
||||
services: VisualizeServices,
|
||||
|
@ -33,6 +32,7 @@ export const useVisByValue = (
|
|||
chrome,
|
||||
application: { navigateToApp },
|
||||
stateTransferService,
|
||||
visEditorsRegistry,
|
||||
} = services;
|
||||
const getVisInstance = async () => {
|
||||
if (!valueInput || loaded.current || !visEditorRef.current) {
|
||||
|
@ -42,7 +42,7 @@ export const useVisByValue = (
|
|||
const { embeddableHandler, vis } = byValueVisInstance;
|
||||
let visEditorController;
|
||||
|
||||
const Editor = getVisEditorsRegistry().get(vis.type.editorConfig?.editor);
|
||||
const Editor = visEditorsRegistry.get(vis.type.editorConfig?.editor);
|
||||
|
||||
if (Editor) {
|
||||
visEditorController = new Editor(
|
|
@ -13,7 +13,7 @@ import { Observable } from 'rxjs';
|
|||
import { useVisualizeAppState } from './use_visualize_app_state';
|
||||
import { VisualizeServices, SavedVisInstance } from '../../types';
|
||||
import { visualizeAppStateStub } from '../stubs';
|
||||
import { VisualizeConstants } from '../../visualize_constants';
|
||||
import { VisualizeConstants } from '../../../../common/constants';
|
||||
import { createVisualizeServicesMock } from '../mocks';
|
||||
|
||||
jest.mock('../utils');
|
|
@ -26,7 +26,7 @@ import {
|
|||
} from '../../types';
|
||||
import { visStateToEditorState } from '../utils';
|
||||
import { createVisualizeAppState } from '../create_visualize_app_state';
|
||||
import { VisualizeConstants } from '../../visualize_constants';
|
||||
import { VisualizeConstants } from '../../../../common/constants';
|
||||
/**
|
||||
* This effect is responsible for instantiating the visualize app state container,
|
||||
* which is in sync with "_a" url param
|
||||
|
@ -126,7 +126,7 @@ export const useVisualizeAppState = (
|
|||
// if setting new vis state was failed for any reason,
|
||||
// redirect to the listing page with error message
|
||||
services.toastNotifications.addWarning({
|
||||
title: i18n.translate('visualize.visualizationLoadingFailedErrorMessage', {
|
||||
title: i18n.translate('visualizations.visualizationLoadingFailedErrorMessage', {
|
||||
defaultMessage: 'Failed to load the visualization',
|
||||
}),
|
||||
text: toMountPoint(
|
|
@ -8,15 +8,16 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { ChromeStart, DocLinksStart } from 'kibana/public';
|
||||
import { Filter } from '@kbn/es-query';
|
||||
import type { ChromeStart, DocLinksStart } from 'kibana/public';
|
||||
import type { Filter } from '@kbn/es-query';
|
||||
import { redirectWhenMissing } from '../../../../kibana_utils/public';
|
||||
import { VisualizeConstants } from '../visualize_constants';
|
||||
import { VisualizeServices, VisualizeEditorVisInstance } from '../types';
|
||||
import { VisualizeConstants } from '../../../common/constants';
|
||||
import { convertFromSerializedVis } from '../../utils/saved_visualize_utils';
|
||||
import type { VisualizeServices, VisualizeEditorVisInstance } from '../types';
|
||||
|
||||
export const addHelpMenuToAppChrome = (chrome: ChromeStart, docLinks: DocLinksStart) => {
|
||||
chrome.setHelpExtension({
|
||||
appName: i18n.translate('visualize.helpMenu.appName', {
|
||||
appName: i18n.translate('visualizations.helpMenu.appName', {
|
||||
defaultMessage: 'Visualize Library',
|
||||
}),
|
||||
links: [
|
||||
|
@ -30,10 +31,10 @@ export const addHelpMenuToAppChrome = (chrome: ChromeStart, docLinks: DocLinksSt
|
|||
|
||||
export const addBadgeToAppChrome = (chrome: ChromeStart) => {
|
||||
chrome.setBadge({
|
||||
text: i18n.translate('visualize.badge.readOnly.text', {
|
||||
text: i18n.translate('visualizations.badge.readOnly.text', {
|
||||
defaultMessage: 'Read only',
|
||||
}),
|
||||
tooltip: i18n.translate('visualize.badge.readOnly.tooltip', {
|
||||
tooltip: i18n.translate('visualizations.badge.readOnly.tooltip', {
|
||||
defaultMessage: 'Unable to save visualizations to the library',
|
||||
}),
|
||||
iconType: 'glasses',
|
||||
|
@ -49,7 +50,7 @@ export const visStateToEditorState = (
|
|||
services: VisualizeServices
|
||||
) => {
|
||||
const vis = visInstance.vis;
|
||||
const savedVisState = services.visualizations.convertFromSerializedVis(vis.serialize());
|
||||
const savedVisState = convertFromSerializedVis(vis.serialize());
|
||||
const savedVis = 'savedVis' in visInstance ? visInstance.savedVis : undefined;
|
||||
return {
|
||||
uiState:
|
|
@ -12,6 +12,7 @@ import { schema } from '@kbn/config-schema';
|
|||
import { VISUALIZE_ENABLE_LABS_SETTING } from '../common/constants';
|
||||
import { visualizationSavedObjectType } from './saved_objects';
|
||||
import { registerVisualizationsCollector } from './usage_collector';
|
||||
import { capabilitiesProvider } from './capabilities_provider';
|
||||
|
||||
import type { VisualizationsPluginSetup, VisualizationsPluginStart } from './types';
|
||||
import type {
|
||||
|
@ -41,6 +42,7 @@ export class VisualizationsPlugin
|
|||
this.logger.debug('visualizations: Setup');
|
||||
|
||||
core.savedObjects.registerType(visualizationSavedObjectType);
|
||||
core.capabilities.registerProvider(capabilitiesProvider);
|
||||
|
||||
core.uiSettings.register({
|
||||
[VISUALIZE_ENABLE_LABS_SETTING]: {
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
"include": [
|
||||
"common/**/*",
|
||||
"public/**/*",
|
||||
"server/**/*"
|
||||
"server/**/*",
|
||||
"../../../typings/**/*"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../core/tsconfig.json" },
|
||||
|
@ -22,7 +23,13 @@
|
|||
{ "path": "../saved_objects_tagging_oss/tsconfig.json" },
|
||||
{ "path": "../usage_collection/tsconfig.json" },
|
||||
{ "path": "../kibana_utils/tsconfig.json" },
|
||||
{ "path": "../kibana_react/tsconfig.json" },
|
||||
{ "path": "../discover/tsconfig.json" },
|
||||
{ "path": "../../../x-pack/plugins/spaces/tsconfig.json" },
|
||||
{ "path": "../url_forwarding/tsconfig.json" },
|
||||
{ "path": "../navigation/tsconfig.json" },
|
||||
{ "path": "../home/tsconfig.json" },
|
||||
{ "path": "../share/tsconfig.json" },
|
||||
{ "path": "../presentation_util/tsconfig.json" },
|
||||
{ "path": "../../../x-pack/plugins/spaces/tsconfig.json" }
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,23 +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
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export const STATE_STORAGE_KEY = '_a';
|
||||
export const GLOBAL_STATE_STORAGE_KEY = '_g';
|
||||
|
||||
export const APP_NAME = 'visualize';
|
||||
|
||||
export const VisualizeConstants = {
|
||||
VISUALIZE_BASE_PATH: '/app/visualize',
|
||||
LANDING_PAGE_PATH: '/',
|
||||
WIZARD_STEP_1_PAGE_PATH: '/new',
|
||||
WIZARD_STEP_2_PAGE_PATH: '/new/configure',
|
||||
CREATE_PATH: '/create',
|
||||
EDIT_PATH: '/edit',
|
||||
EDIT_BY_VALUE_PATH: '/edit_by_value',
|
||||
APP_ID: 'visualize',
|
||||
};
|
|
@ -1,10 +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
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import type { SavedVisState } from 'src/plugins/visualizations/common/types';
|
||||
|
||||
export type PureVisState = SavedVisState;
|
|
@ -1,16 +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
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
preset: '@kbn/test',
|
||||
rootDir: '../../..',
|
||||
roots: ['<rootDir>/src/plugins/visualize'],
|
||||
coverageDirectory: '<rootDir>/target/kibana-coverage/jest/src/plugins/visualize',
|
||||
coverageReporters: ['text', 'html'],
|
||||
collectCoverageFrom: ['<rootDir>/src/plugins/visualize/{common,public,server}/**/*.{ts,tsx}'],
|
||||
};
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"id": "visualize",
|
||||
"version": "kibana",
|
||||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": [
|
||||
"data",
|
||||
"urlForwarding",
|
||||
"navigation",
|
||||
"savedObjects",
|
||||
"visualizations",
|
||||
"embeddable",
|
||||
"dashboard",
|
||||
"presentationUtil"
|
||||
],
|
||||
"optionalPlugins": [
|
||||
"home",
|
||||
"share",
|
||||
"savedObjectsTaggingOss",
|
||||
"usageCollection",
|
||||
"spaces"
|
||||
],
|
||||
"requiredBundles": [
|
||||
"kibanaUtils",
|
||||
"kibanaReact",
|
||||
"home",
|
||||
"discover"
|
||||
],
|
||||
"owner": {
|
||||
"name": "Vis Editors",
|
||||
"githubTeam": "kibana-vis-editors"
|
||||
},
|
||||
"description": "Contains the visualize application which includes the listing page and the app frame, which will load the visualization's editor."
|
||||
}
|
|
@ -1,9 +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
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export { VisualizeConstants, APP_NAME } from '../../common/constants';
|
|
@ -1,20 +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
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { PluginInitializerContext } from 'kibana/public';
|
||||
import { VisualizePlugin, VisualizePluginSetup } from './plugin';
|
||||
|
||||
export { VisualizeConstants } from './application/visualize_constants';
|
||||
|
||||
export type { IEditorController, EditorRenderProps } from './application/types';
|
||||
|
||||
export type { VisualizePluginSetup };
|
||||
|
||||
export const plugin = (context: PluginInitializerContext) => {
|
||||
return new VisualizePlugin(context);
|
||||
};
|
|
@ -1,271 +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
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { createHashHistory } from 'history';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
|
||||
import {
|
||||
AppMountParameters,
|
||||
AppUpdater,
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
Plugin,
|
||||
PluginInitializerContext,
|
||||
ScopedHistory,
|
||||
DEFAULT_APP_CATEGORIES,
|
||||
} from '../../../core/public';
|
||||
|
||||
import {
|
||||
Storage,
|
||||
createKbnUrlTracker,
|
||||
createKbnUrlStateStorage,
|
||||
withNotifyOnErrors,
|
||||
} from '../../kibana_utils/public';
|
||||
|
||||
import { VisualizeConstants } from './application/visualize_constants';
|
||||
import { DataPublicPluginStart, DataPublicPluginSetup, esFilters } from '../../data/public';
|
||||
import { FeatureCatalogueCategory, HomePublicPluginSetup } from '../../home/public';
|
||||
|
||||
import type { PresentationUtilPluginStart } from '../../../../src/plugins/presentation_util/public';
|
||||
import type { NavigationPublicPluginStart as NavigationStart } from '../../navigation/public';
|
||||
import type { SharePluginStart, SharePluginSetup } from '../../share/public';
|
||||
import type { UrlForwardingSetup, UrlForwardingStart } from '../../url_forwarding/public';
|
||||
import type { VisualizationsStart } from '../../visualizations/public';
|
||||
import type { VisualizeServices } from './application/types';
|
||||
import type { SavedObjectsStart } from '../../saved_objects/public';
|
||||
import type { EmbeddableStart } from '../../embeddable/public';
|
||||
import type { DashboardStart } from '../../dashboard/public';
|
||||
import type { SavedObjectTaggingOssPluginStart } from '../../saved_objects_tagging_oss/public';
|
||||
import type { UsageCollectionStart } from '../../usage_collection/public';
|
||||
import type { SpacesApi } from '../../../../x-pack/plugins/spaces/public';
|
||||
|
||||
import { setVisEditorsRegistry, setUISettings, setUsageCollector } from './services';
|
||||
import { createVisEditorsRegistry, VisEditorsRegistry } from './vis_editors_registry';
|
||||
import { VisualizeLocatorDefinition } from '../common/locator';
|
||||
|
||||
export interface VisualizePluginStartDependencies {
|
||||
data: DataPublicPluginStart;
|
||||
navigation: NavigationStart;
|
||||
share?: SharePluginStart;
|
||||
visualizations: VisualizationsStart;
|
||||
embeddable: EmbeddableStart;
|
||||
urlForwarding: UrlForwardingStart;
|
||||
savedObjects: SavedObjectsStart;
|
||||
dashboard: DashboardStart;
|
||||
savedObjectsTaggingOss?: SavedObjectTaggingOssPluginStart;
|
||||
presentationUtil: PresentationUtilPluginStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
spaces?: SpacesApi;
|
||||
}
|
||||
|
||||
export interface VisualizePluginSetupDependencies {
|
||||
home?: HomePublicPluginSetup;
|
||||
urlForwarding: UrlForwardingSetup;
|
||||
data: DataPublicPluginSetup;
|
||||
share?: SharePluginSetup;
|
||||
}
|
||||
|
||||
export interface VisualizePluginSetup {
|
||||
visEditorsRegistry: VisEditorsRegistry;
|
||||
}
|
||||
|
||||
export class VisualizePlugin
|
||||
implements
|
||||
Plugin<
|
||||
VisualizePluginSetup,
|
||||
void,
|
||||
VisualizePluginSetupDependencies,
|
||||
VisualizePluginStartDependencies
|
||||
>
|
||||
{
|
||||
private appStateUpdater = new BehaviorSubject<AppUpdater>(() => ({}));
|
||||
private stopUrlTracking: (() => void) | undefined = undefined;
|
||||
private currentHistory: ScopedHistory | undefined = undefined;
|
||||
private isLinkedToOriginatingApp: (() => boolean) | undefined = undefined;
|
||||
|
||||
private readonly visEditorsRegistry = createVisEditorsRegistry();
|
||||
|
||||
constructor(private initializerContext: PluginInitializerContext) {}
|
||||
|
||||
public setup(
|
||||
core: CoreSetup<VisualizePluginStartDependencies>,
|
||||
{ home, urlForwarding, data, share }: VisualizePluginSetupDependencies
|
||||
) {
|
||||
const {
|
||||
appMounted,
|
||||
appUnMounted,
|
||||
stop: stopUrlTracker,
|
||||
setActiveUrl,
|
||||
restorePreviousUrl,
|
||||
} = createKbnUrlTracker({
|
||||
baseUrl: core.http.basePath.prepend(VisualizeConstants.VISUALIZE_BASE_PATH),
|
||||
defaultSubUrl: '#/',
|
||||
storageKey: `lastUrl:${core.http.basePath.get()}:visualize`,
|
||||
navLinkUpdater$: this.appStateUpdater,
|
||||
toastNotifications: core.notifications.toasts,
|
||||
stateParams: [
|
||||
{
|
||||
kbnUrlKey: '_g',
|
||||
stateUpdate$: data.query.state$.pipe(
|
||||
filter(
|
||||
({ changes }) => !!(changes.globalFilters || changes.time || changes.refreshInterval)
|
||||
),
|
||||
map(({ state }) => ({
|
||||
...state,
|
||||
filters: state.filters?.filter(esFilters.isFilterPinned),
|
||||
}))
|
||||
),
|
||||
},
|
||||
],
|
||||
getHistory: () => this.currentHistory!,
|
||||
onBeforeNavLinkSaved: (urlToSave: string) => {
|
||||
if (this.isLinkedToOriginatingApp?.()) {
|
||||
return core.http.basePath.prepend(VisualizeConstants.VISUALIZE_BASE_PATH);
|
||||
}
|
||||
return urlToSave;
|
||||
},
|
||||
});
|
||||
this.stopUrlTracking = () => {
|
||||
stopUrlTracker();
|
||||
};
|
||||
|
||||
setUISettings(core.uiSettings);
|
||||
|
||||
core.application.register({
|
||||
id: VisualizeConstants.APP_ID,
|
||||
title: 'Visualize Library',
|
||||
order: 8000,
|
||||
euiIconType: 'logoKibana',
|
||||
defaultPath: '#/',
|
||||
category: DEFAULT_APP_CATEGORIES.kibana,
|
||||
updater$: this.appStateUpdater.asObservable(),
|
||||
// remove all references to visualize
|
||||
mount: async (params: AppMountParameters) => {
|
||||
const [coreStart, pluginsStart] = await core.getStartServices();
|
||||
this.currentHistory = params.history;
|
||||
|
||||
// allows the urlTracker to only save URLs that are not linked to an originatingApp
|
||||
this.isLinkedToOriginatingApp = () => {
|
||||
return Boolean(
|
||||
pluginsStart.embeddable
|
||||
.getStateTransfer()
|
||||
.getIncomingEditorState(VisualizeConstants.APP_ID)?.originatingApp
|
||||
);
|
||||
};
|
||||
|
||||
// make sure the index pattern list is up to date
|
||||
pluginsStart.data.indexPatterns.clearCache();
|
||||
// make sure a default index pattern exists
|
||||
// if not, the page will be redirected to management and visualize won't be rendered
|
||||
await pluginsStart.data.indexPatterns.ensureDefaultDataView();
|
||||
|
||||
appMounted();
|
||||
|
||||
// dispatch synthetic hash change event to update hash history objects
|
||||
// this is necessary because hash updates triggered by using popState won't trigger this event naturally.
|
||||
const unlistenParentHistory = params.history.listen(() => {
|
||||
window.dispatchEvent(new HashChangeEvent('hashchange'));
|
||||
});
|
||||
/**
|
||||
* current implementation uses 2 history objects:
|
||||
* 1. the hash history (used for the react hash router)
|
||||
* 2. and the scoped history (used for url tracking)
|
||||
* this should be replaced to use only scoped history after moving legacy apps to browser routing
|
||||
*/
|
||||
const history = createHashHistory();
|
||||
const services: VisualizeServices = {
|
||||
...coreStart,
|
||||
history,
|
||||
kbnUrlStateStorage: createKbnUrlStateStorage({
|
||||
history,
|
||||
useHash: coreStart.uiSettings.get('state:storeInSessionStorage'),
|
||||
...withNotifyOnErrors(coreStart.notifications.toasts),
|
||||
}),
|
||||
urlForwarding: pluginsStart.urlForwarding,
|
||||
pluginInitializerContext: this.initializerContext,
|
||||
chrome: coreStart.chrome,
|
||||
data: pluginsStart.data,
|
||||
localStorage: new Storage(localStorage),
|
||||
navigation: pluginsStart.navigation,
|
||||
share: pluginsStart.share,
|
||||
toastNotifications: coreStart.notifications.toasts,
|
||||
visualizeCapabilities: coreStart.application.capabilities.visualize,
|
||||
dashboardCapabilities: coreStart.application.capabilities.dashboard,
|
||||
visualizations: pluginsStart.visualizations,
|
||||
embeddable: pluginsStart.embeddable,
|
||||
stateTransferService: pluginsStart.embeddable.getStateTransfer(),
|
||||
setActiveUrl,
|
||||
createVisEmbeddableFromObject:
|
||||
pluginsStart.visualizations.__LEGACY.createVisEmbeddableFromObject,
|
||||
savedObjectsPublic: pluginsStart.savedObjects,
|
||||
scopedHistory: params.history,
|
||||
restorePreviousUrl,
|
||||
dashboard: pluginsStart.dashboard,
|
||||
setHeaderActionMenu: params.setHeaderActionMenu,
|
||||
savedObjectsTagging: pluginsStart.savedObjectsTaggingOss?.getTaggingApi(),
|
||||
presentationUtil: pluginsStart.presentationUtil,
|
||||
usageCollection: pluginsStart.usageCollection,
|
||||
getKibanaVersion: () => this.initializerContext.env.packageInfo.version,
|
||||
spaces: pluginsStart.spaces,
|
||||
};
|
||||
|
||||
params.element.classList.add('visAppWrapper');
|
||||
const { renderApp } = await import('./application');
|
||||
const unmount = renderApp(params, services);
|
||||
return () => {
|
||||
data.search.session.clear();
|
||||
params.element.classList.remove('visAppWrapper');
|
||||
unlistenParentHistory();
|
||||
unmount();
|
||||
appUnMounted();
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
urlForwarding.forwardApp('visualize', 'visualize');
|
||||
|
||||
if (home) {
|
||||
home.featureCatalogue.register({
|
||||
id: 'visualize',
|
||||
title: 'Visualize Library',
|
||||
description: i18n.translate('visualize.visualizeDescription', {
|
||||
defaultMessage:
|
||||
'Create visualizations and aggregate data stores in your Elasticsearch indices.',
|
||||
}),
|
||||
icon: 'visualizeApp',
|
||||
path: `/app/visualize#${VisualizeConstants.LANDING_PAGE_PATH}`,
|
||||
showOnHomePage: false,
|
||||
category: FeatureCatalogueCategory.DATA,
|
||||
});
|
||||
}
|
||||
|
||||
if (share) {
|
||||
share.url.locators.create(new VisualizeLocatorDefinition());
|
||||
}
|
||||
|
||||
return {
|
||||
visEditorsRegistry: this.visEditorsRegistry,
|
||||
} as VisualizePluginSetup;
|
||||
}
|
||||
|
||||
public start(core: CoreStart, { usageCollection }: VisualizePluginStartDependencies) {
|
||||
setVisEditorsRegistry(this.visEditorsRegistry);
|
||||
|
||||
if (usageCollection) {
|
||||
setUsageCollector(usageCollection);
|
||||
}
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this.stopUrlTracking) {
|
||||
this.stopUrlTracking();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +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
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { createGetterSetter } from '../../../plugins/kibana_utils/public';
|
||||
|
||||
import type { IUiSettingsClient } from '../../../core/public';
|
||||
import type { VisEditorsRegistry } from './vis_editors_registry';
|
||||
import type { UsageCollectionStart } from '../../usage_collection/public';
|
||||
|
||||
export const [getUISettings, setUISettings] = createGetterSetter<IUiSettingsClient>('UISettings');
|
||||
|
||||
export const [getUsageCollector, setUsageCollector] = createGetterSetter<UsageCollectionStart>(
|
||||
'UsageCollection',
|
||||
false
|
||||
);
|
||||
|
||||
export const [getVisEditorsRegistry, setVisEditorsRegistry] =
|
||||
createGetterSetter<VisEditorsRegistry>('VisEditorsRegistry');
|
|
@ -1,13 +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
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { PluginInitializerContext } from 'kibana/server';
|
||||
import { VisualizeServerPlugin } from './plugin';
|
||||
|
||||
export const plugin = (initContext: PluginInitializerContext) =>
|
||||
new VisualizeServerPlugin(initContext);
|
|
@ -1,33 +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
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin, Logger } from 'kibana/server';
|
||||
import { capabilitiesProvider } from './capabilities_provider';
|
||||
|
||||
export class VisualizeServerPlugin implements Plugin<object, object> {
|
||||
private readonly logger: Logger;
|
||||
|
||||
constructor(initializerContext: PluginInitializerContext) {
|
||||
this.logger = initializerContext.logger.get();
|
||||
}
|
||||
|
||||
public setup(core: CoreSetup) {
|
||||
this.logger.debug('visualize: Setup');
|
||||
|
||||
core.capabilities.registerProvider(capabilitiesProvider);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
public start(core: CoreStart) {
|
||||
this.logger.debug('visualize: Started');
|
||||
return {};
|
||||
}
|
||||
|
||||
public stop() {}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./target/types",
|
||||
"emitDeclarationOnly": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true
|
||||
},
|
||||
"include": ["common/**/*", "public/**/*", "server/**/*", "../../../typings/**/*"],
|
||||
"references": [
|
||||
{ "path": "../../core/tsconfig.json" },
|
||||
{ "path": "../data/tsconfig.json" },
|
||||
{ "path": "../url_forwarding/tsconfig.json" },
|
||||
{ "path": "../navigation/tsconfig.json" },
|
||||
{ "path": "../saved_objects/tsconfig.json" },
|
||||
{ "path": "../visualizations/tsconfig.json" },
|
||||
{ "path": "../embeddable/tsconfig.json" },
|
||||
{ "path": "../dashboard/tsconfig.json" },
|
||||
{ "path": "../ui_actions/tsconfig.json" },
|
||||
{ "path": "../home/tsconfig.json" },
|
||||
{ "path": "../share/tsconfig.json" },
|
||||
{ "path": "../saved_objects_tagging_oss/tsconfig.json" },
|
||||
{ "path": "../kibana_utils/tsconfig.json" },
|
||||
{ "path": "../kibana_react/tsconfig.json" },
|
||||
{ "path": "../home/tsconfig.json" },
|
||||
{ "path": "../presentation_util/tsconfig.json" },
|
||||
{ "path": "../discover/tsconfig.json" },
|
||||
{ "path": "../../../x-pack/plugins/spaces/tsconfig.json" },
|
||||
]
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import expect from '@kbn/expect';
|
||||
|
||||
import { VisualizeConstants } from '../../../../src/plugins/visualize/public/application/visualize_constants';
|
||||
import { VisualizeConstants } from '../../../../src/plugins/visualizations/common/constants';
|
||||
import { VISUALIZE_ENABLE_LABS_SETTING } from '../../../../src/plugins/visualizations/common/constants';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import expect from '@kbn/expect';
|
||||
import { PIE_CHART_VIS_NAME } from '../../page_objects/dashboard_page';
|
||||
import { VisualizeConstants } from '../../../../src/plugins/visualize/public/application/visualize_constants';
|
||||
import { VisualizeConstants } from '../../../../src/plugins/visualizations/common/constants';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { FtrService } from '../ftr_provider_context';
|
||||
import { VisualizeConstants } from '../../../src/plugins/visualize/public/application/visualize_constants';
|
||||
import { VisualizeConstants } from '../../../src/plugins/visualizations/common/constants';
|
||||
import { FORMATS_UI_SETTINGS } from '../../../src/plugins/field_formats/common';
|
||||
|
||||
// TODO: Remove & Refactor to use the TTV page objects
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
{ "path": "../src/plugins/url_forwarding/tsconfig.json" },
|
||||
{ "path": "../src/plugins/usage_collection/tsconfig.json" },
|
||||
{ "path": "../src/plugins/data_view_management/tsconfig.json" },
|
||||
{ "path": "../src/plugins/visualize/tsconfig.json" },
|
||||
{ "path": "../src/plugins/visualizations/tsconfig.json" },
|
||||
{ "path": "interactive_setup_api_integration/fixtures/test_endpoints/tsconfig.json" },
|
||||
{ "path": "plugin_functional/plugins/core_app_status/tsconfig.json" },
|
||||
{ "path": "plugin_functional/plugins/core_provider_plugin/tsconfig.json" },
|
||||
|
|
|
@ -5145,13 +5145,24 @@
|
|||
"visTypeXy.thresholdLine.style.fullText": "完全",
|
||||
"visualizations.advancedSettings.visualizeEnableLabsText": "ユーザーが実験的なビジュアライゼーションを作成、表示、編集できるようになります。無効の場合、\n ユーザーは本番準備が整ったビジュアライゼーションのみを利用できます。",
|
||||
"visualizations.advancedSettings.visualizeEnableLabsTitle": "実験的なビジュアライゼーションを有効にする",
|
||||
"visualizations.badge.readOnly.text": "読み取り専用",
|
||||
"visualizations.badge.readOnly.tooltip": "ビジュアライゼーションをライブラリに保存できません",
|
||||
"visualizations.byValue_pageHeading": "{originatingApp}アプリに埋め込まれた{chartType}タイプのビジュアライゼーション",
|
||||
"visualizations.confirmModal.confirmTextDescription": "変更を保存せずにVisualizeエディターから移動しますか?",
|
||||
"visualizations.confirmModal.title": "保存されていない変更",
|
||||
"visualizations.createVisualization.failedToLoadErrorMessage": "ビジュアライゼーションを読み込めませんでした",
|
||||
"visualizations.createVisualization.noIndexPatternOrSavedSearchIdErrorMessage": "indexPatternまたはsavedSearchIdが必要です",
|
||||
"visualizations.createVisualization.noVisTypeErrorMessage": "有効なビジュアライゼーションタイプを指定してください",
|
||||
"visualizations.disabledLabVisualizationLink": "ドキュメンテーションを表示",
|
||||
"visualizations.disabledLabVisualizationMessage": "ラボビジュアライゼーションを表示するには、高度な設定でラボモードをオンにしてください。",
|
||||
"visualizations.disabledLabVisualizationTitle": "{title} はラボビジュアライゼーションです。",
|
||||
"visualizations.displayName": "ビジュアライゼーション",
|
||||
"visualizations.editor.createBreadcrumb": "作成",
|
||||
"visualizations.editor.defaultEditBreadcrumbText": "ビジュアライゼーションを編集",
|
||||
"visualizations.embeddable.inspectorTitle": "インスペクター",
|
||||
"visualizations.embeddable.legacyURLConflict.errorMessage": "このビジュアライゼーションにはレガシーエイリアスと同じURLがあります。このエラーを解決するには、エイリアスを無効にしてください:{json}",
|
||||
"visualizations.embeddable.placeholderTitle": "プレースホルダータイトル",
|
||||
"visualizations.experimentalVisInfoText": "このビジュアライゼーションはまだ実験段階であり、オフィシャルGA機能のサポートSLAが適用されません。フィードバックがある場合は、{githubLink}で問題を報告してください。",
|
||||
"visualizations.function.range.from.help": "範囲の開始",
|
||||
"visualizations.function.range.help": "範囲オブジェクトを生成します",
|
||||
"visualizations.function.range.to.help": "範囲の終了",
|
||||
|
@ -5161,11 +5172,29 @@
|
|||
"visualizations.function.visDimension.formatParams.help": "フォーマットパラメーター",
|
||||
"visualizations.function.visDimension.help": "visConfig ディメンションオブジェクトを生成します",
|
||||
"visualizations.function.xyDimension.aggType.help": "集約タイプ",
|
||||
"visualizations.function.xydimension.help": "XYディメンションオブジェクトを生成します",
|
||||
"visualizations.function.xyDimension.label.help": "ラベル",
|
||||
"visualizations.function.xyDimension.params.help": "パラメーター",
|
||||
"visualizations.function.xyDimension.visDimension.help": "ディメンションオブジェクト構成",
|
||||
"visualizations.function.xydimension.help": "XYディメンションオブジェクトを生成します",
|
||||
"visualizations.helpMenu.appName": "Visualizeライブラリ",
|
||||
"visualizations.initializeWithoutIndexPatternErrorMessage": "インデックスパターンなしで集約を初期化しようとしています",
|
||||
"visualizations.legacyUrlConflict.objectNoun": "{visName}ビジュアライゼーション",
|
||||
"visualizations.linkedToSearch.unlinkSuccessNotificationText": "保存された検索「{searchTitle}」からリンクが解除されました",
|
||||
"visualizations.listing.betaTitle": "ベータ",
|
||||
"visualizations.listing.betaTooltip": "このビジュアライゼーションはベータ段階で、変更される可能性があります。デザインとコードはオフィシャルGA機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャルGA機能のSLAが適用されません",
|
||||
"visualizations.listing.breadcrumb": "Visualizeライブラリ",
|
||||
"visualizations.listing.createNew.createButtonLabel": "新規ビジュアライゼーションを追加",
|
||||
"visualizations.listing.createNew.description": "データに基づき異なるビジュアライゼーションを作成できます。",
|
||||
"visualizations.listing.createNew.title": "最初のビジュアライゼーションの作成",
|
||||
"visualizations.listing.experimentalTitle": "実験的",
|
||||
"visualizations.listing.experimentalTooltip": "このビジュアライゼーションは今後のリリースで変更または削除される可能性があり、SLA のサポート対象になりません。",
|
||||
"visualizations.listing.table.descriptionColumnName": "説明",
|
||||
"visualizations.listing.table.entityName": "ビジュアライゼーション",
|
||||
"visualizations.listing.table.entityNamePlural": "ビジュアライゼーション",
|
||||
"visualizations.listing.table.listTitle": "Visualizeライブラリ",
|
||||
"visualizations.listing.table.titleColumnName": "タイトル",
|
||||
"visualizations.listing.table.typeColumnName": "型",
|
||||
"visualizations.listingPageTitle": "Visualizeライブラリ",
|
||||
"visualizations.newVisWizard.aggBasedGroupDescription": "クラシック Visualize ライブラリを使用して、アグリゲーションに基づいてグラフを作成します。",
|
||||
"visualizations.newVisWizard.aggBasedGroupTitle": "アグリゲーションに基づく",
|
||||
"visualizations.newVisWizard.chooseSourceTitle": "ソースの選択",
|
||||
|
@ -5182,69 +5211,40 @@
|
|||
"visualizations.newVisWizard.searchSelection.savedObjectType.search": "保存検索",
|
||||
"visualizations.newVisWizard.title": "新規ビジュアライゼーション",
|
||||
"visualizations.newVisWizard.toolsGroupTitle": "ツール",
|
||||
"visualizations.noMatchRoute.bannerText": "Visualizeアプリケーションはこのルートを認識できません。{route}",
|
||||
"visualizations.noMatchRoute.bannerTitleText": "ページが見つかりません",
|
||||
"visualizations.noResultsFoundTitle": "結果が見つかりませんでした",
|
||||
"visualizations.pageHeading": "{chartName} {chartType}ビジュアライゼーション",
|
||||
"visualizations.reporting.defaultReportTitle": "ビジュアライゼーション[{date}]",
|
||||
"visualizations.savedObjectName": "ビジュアライゼーション",
|
||||
"visualizations.savingVisualizationFailed.errorMsg": "ビジュアライゼーションの保存が失敗しました",
|
||||
"visualizations.topNavMenu.cancelAndReturnButtonTooltip": "完了する前に変更を破棄",
|
||||
"visualizations.topNavMenu.cancelButtonAriaLabel": "変更を保存せずに最後に使用していたアプリに戻る",
|
||||
"visualizations.topNavMenu.cancelButtonLabel": "キャンセル",
|
||||
"visualizations.topNavMenu.openInspectorButtonAriaLabel": "ビジュアライゼーションのインスペクターを開く",
|
||||
"visualizations.topNavMenu.openInspectorButtonLabel": "検査",
|
||||
"visualizations.topNavMenu.openInspectorDisabledButtonTooltip": "このビジュアライゼーションはインスペクターをサポートしていません。",
|
||||
"visualizations.topNavMenu.saveAndReturnVisualizationButtonAriaLabel": "可視化の編集が完了し、前回使用していたアプリに戻ります",
|
||||
"visualizations.topNavMenu.saveAndReturnVisualizationButtonLabel": "保存して戻る",
|
||||
"visualizations.topNavMenu.saveAndReturnVisualizationDisabledButtonTooltip": "完了する前に変更を適用または破棄",
|
||||
"visualizations.topNavMenu.saveVisualization.failureNotificationText": "「{visTitle}」の保存中にエラーが発生しました",
|
||||
"visualizations.topNavMenu.saveVisualization.successNotificationText": "保存された'{visTitle}'",
|
||||
"visualizations.topNavMenu.saveVisualizationAsButtonLabel": "名前を付けて保存",
|
||||
"visualizations.topNavMenu.saveVisualizationButtonAriaLabel": "ビジュアライゼーションを保存",
|
||||
"visualizations.topNavMenu.saveVisualizationButtonLabel": "保存",
|
||||
"visualizations.topNavMenu.saveVisualizationDisabledButtonTooltip": "保存する前に変更を適用または破棄",
|
||||
"visualizations.topNavMenu.saveVisualizationObjectType": "ビジュアライゼーション",
|
||||
"visualizations.topNavMenu.saveVisualizationToLibraryButtonLabel": "ライブラリに保存",
|
||||
"visualizations.topNavMenu.shareVisualizationButtonAriaLabel": "ビジュアライゼーションを共有",
|
||||
"visualizations.topNavMenu.shareVisualizationButtonLabel": "共有",
|
||||
"visualizations.topNavMenu.updatePanel": "{originatingAppName}でパネルを更新",
|
||||
"visualizations.visualizationLoadingFailedErrorMessage": "ビジュアライゼーションを読み込めませんでした",
|
||||
"visualizations.visualizationTypeInvalidMessage": "無効なビジュアライゼーションタイプ \"{visType}\"",
|
||||
"visualize.badge.readOnly.text": "読み取り専用",
|
||||
"visualize.badge.readOnly.tooltip": "ビジュアライゼーションをライブラリに保存できません",
|
||||
"visualize.byValue_pageHeading": "{originatingApp}アプリに埋め込まれた{chartType}タイプのビジュアライゼーション",
|
||||
"visualize.confirmModal.confirmTextDescription": "変更を保存せずにVisualizeエディターから移動しますか?",
|
||||
"visualize.confirmModal.title": "保存されていない変更",
|
||||
"visualize.createVisualization.failedToLoadErrorMessage": "ビジュアライゼーションを読み込めませんでした",
|
||||
"visualize.createVisualization.noIndexPatternOrSavedSearchIdErrorMessage": "indexPatternまたはsavedSearchIdが必要です",
|
||||
"visualize.createVisualization.noVisTypeErrorMessage": "有効なビジュアライゼーションタイプを指定してください",
|
||||
"visualize.editor.createBreadcrumb": "作成",
|
||||
"visualize.editor.defaultEditBreadcrumbText": "ビジュアライゼーションを編集",
|
||||
"visualize.experimentalVisInfoText": "このビジュアライゼーションはまだ実験段階であり、オフィシャルGA機能のサポートSLAが適用されません。フィードバックがある場合は、{githubLink}で問題を報告してください。",
|
||||
"visualize.helpMenu.appName": "Visualizeライブラリ",
|
||||
"visualize.legacyUrlConflict.objectNoun": "{visName}ビジュアライゼーション",
|
||||
"visualize.linkedToSearch.unlinkSuccessNotificationText": "保存された検索「{searchTitle}」からリンクが解除されました",
|
||||
"visualize.listing.betaTitle": "ベータ",
|
||||
"visualize.listing.betaTooltip": "このビジュアライゼーションはベータ段階で、変更される可能性があります。デザインとコードはオフィシャルGA機能よりも完成度が低く、現状のまま保証なしで提供されています。ベータ機能にはオフィシャルGA機能のSLAが適用されません",
|
||||
"visualize.listing.breadcrumb": "Visualizeライブラリ",
|
||||
"visualize.listing.createNew.createButtonLabel": "新規ビジュアライゼーションを追加",
|
||||
"visualize.listing.createNew.description": "データに基づき異なるビジュアライゼーションを作成できます。",
|
||||
"visualize.listing.createNew.title": "最初のビジュアライゼーションの作成",
|
||||
"visualize.listing.experimentalTitle": "実験的",
|
||||
"visualize.listing.experimentalTooltip": "このビジュアライゼーションは今後のリリースで変更または削除される可能性があり、SLA のサポート対象になりません。",
|
||||
"visualize.listing.table.descriptionColumnName": "説明",
|
||||
"visualize.listing.table.entityName": "ビジュアライゼーション",
|
||||
"visualize.listing.table.entityNamePlural": "ビジュアライゼーション",
|
||||
"visualize.listing.table.listTitle": "Visualizeライブラリ",
|
||||
"visualize.listing.table.titleColumnName": "タイトル",
|
||||
"visualize.listing.table.typeColumnName": "型",
|
||||
"visualize.listingPageTitle": "Visualizeライブラリ",
|
||||
"visualize.noMatchRoute.bannerText": "Visualizeアプリケーションはこのルートを認識できません。{route}",
|
||||
"visualize.noMatchRoute.bannerTitleText": "ページが見つかりません",
|
||||
"visualize.pageHeading": "{chartName} {chartType}ビジュアライゼーション",
|
||||
"visualize.reporting.defaultReportTitle": "ビジュアライゼーション[{date}]",
|
||||
"visualize.topNavMenu.cancelAndReturnButtonTooltip": "完了する前に変更を破棄",
|
||||
"visualize.topNavMenu.cancelButtonAriaLabel": "変更を保存せずに最後に使用していたアプリに戻る",
|
||||
"visualize.topNavMenu.cancelButtonLabel": "キャンセル",
|
||||
"visualize.topNavMenu.openInspectorButtonAriaLabel": "ビジュアライゼーションのインスペクターを開く",
|
||||
"visualize.topNavMenu.openInspectorButtonLabel": "検査",
|
||||
"visualize.topNavMenu.openInspectorDisabledButtonTooltip": "このビジュアライゼーションはインスペクターをサポートしていません。",
|
||||
"visualize.topNavMenu.saveAndReturnVisualizationButtonAriaLabel": "可視化の編集が完了し、前回使用していたアプリに戻ります",
|
||||
"visualize.topNavMenu.saveAndReturnVisualizationButtonLabel": "保存して戻る",
|
||||
"visualize.topNavMenu.saveAndReturnVisualizationDisabledButtonTooltip": "完了する前に変更を適用または破棄",
|
||||
"visualize.topNavMenu.saveVisualization.failureNotificationText": "「{visTitle}」の保存中にエラーが発生しました",
|
||||
"visualize.topNavMenu.saveVisualization.successNotificationText": "保存された'{visTitle}'",
|
||||
"visualize.topNavMenu.saveVisualizationAsButtonLabel": "名前を付けて保存",
|
||||
"visualize.topNavMenu.saveVisualizationButtonAriaLabel": "ビジュアライゼーションを保存",
|
||||
"visualize.topNavMenu.saveVisualizationButtonLabel": "保存",
|
||||
"visualize.topNavMenu.saveVisualizationDisabledButtonTooltip": "保存する前に変更を適用または破棄",
|
||||
"visualize.topNavMenu.saveVisualizationObjectType": "ビジュアライゼーション",
|
||||
"visualize.topNavMenu.saveVisualizationToLibraryButtonLabel": "ライブラリに保存",
|
||||
"visualize.topNavMenu.shareVisualizationButtonAriaLabel": "ビジュアライゼーションを共有",
|
||||
"visualize.topNavMenu.shareVisualizationButtonLabel": "共有",
|
||||
"visualize.topNavMenu.updatePanel": "{originatingAppName}でパネルを更新",
|
||||
"visualize.visualizationLoadingFailedErrorMessage": "ビジュアライゼーションを読み込めませんでした",
|
||||
"visualize.visualizeDescription": "ビジュアライゼーションを作成してElasticsearchインデックスに保存されたデータをアグリゲーションします。",
|
||||
"visualize.visualizeListingBreadcrumbsTitle": "Visualizeライブラリ",
|
||||
"visualize.visualizeListingDashboardAppName": "ダッシュボードアプリケーション",
|
||||
"visualize.visualizeListingDashboardFlowDescription": "ダッシュボードを作成しますか?{dashboardApp}から直接ビジュアライゼーションを作成して追加します。",
|
||||
"visualize.visualizeListingDeleteErrorTitle": "ビジュアライゼーションの削除中にエラーが発生",
|
||||
"visualizations.visualizeDescription": "ビジュアライゼーションを作成してElasticsearchインデックスに保存されたデータをアグリゲーションします。",
|
||||
"visualizations.visualizeListingBreadcrumbsTitle": "Visualizeライブラリ",
|
||||
"visualizations.visualizeListingDashboardAppName": "ダッシュボードアプリケーション",
|
||||
"visualizations.visualizeListingDashboardFlowDescription": "ダッシュボードを作成しますか?{dashboardApp}から直接ビジュアライゼーションを作成して追加します。",
|
||||
"visualizations.visualizeListingDeleteErrorTitle": "ビジュアライゼーションの削除中にエラーが発生",
|
||||
"xpack.actions.actionTypeRegistry.get.missingActionTypeErrorMessage": "アクションタイプ「{id}」は登録されていません。",
|
||||
"xpack.actions.actionTypeRegistry.register.duplicateActionTypeErrorMessage": "アクションタイプ「{id}」はすでに登録されています。",
|
||||
"xpack.actions.alertHistoryEsIndexConnector.name": "アラート履歴Elasticsearchインデックス",
|
||||
|
|
|
@ -5178,13 +5178,24 @@
|
|||
"visTypeXy.thresholdLine.style.fullText": "实线",
|
||||
"visualizations.advancedSettings.visualizeEnableLabsText": "允许用户创建、查看和编辑实验性可视化。如果禁用,\n 仅被视为生产就绪的可视化可供用户使用。",
|
||||
"visualizations.advancedSettings.visualizeEnableLabsTitle": "启用实验性可视化",
|
||||
"visualizations.badge.readOnly.text": "只读",
|
||||
"visualizations.badge.readOnly.tooltip": "无法将可视化保存到库",
|
||||
"visualizations.byValue_pageHeading": "已嵌入到 {originatingApp} 应用中的 {chartType} 类型可视化",
|
||||
"visualizations.confirmModal.confirmTextDescription": "离开 Visualize 编辑器而不保存更改?",
|
||||
"visualizations.confirmModal.title": "未保存的更改",
|
||||
"visualizations.createVisualization.failedToLoadErrorMessage": "无法加载可视化",
|
||||
"visualizations.createVisualization.noIndexPatternOrSavedSearchIdErrorMessage": "必须提供 indexPattern 或 savedSearchId",
|
||||
"visualizations.createVisualization.noVisTypeErrorMessage": "必须提供有效的可视化类型",
|
||||
"visualizations.disabledLabVisualizationLink": "阅读文档",
|
||||
"visualizations.disabledLabVisualizationMessage": "请在高级设置中打开实验模式,以查看实验性可视化。",
|
||||
"visualizations.disabledLabVisualizationTitle": "{title} 为实验室可视化。",
|
||||
"visualizations.displayName": "可视化",
|
||||
"visualizations.editor.createBreadcrumb": "创建",
|
||||
"visualizations.editor.defaultEditBreadcrumbText": "编辑可视化",
|
||||
"visualizations.embeddable.inspectorTitle": "检查器",
|
||||
"visualizations.embeddable.legacyURLConflict.errorMessage": "此可视化具有与旧版别名相同的 URL。请禁用别名以解决此错误:{json}",
|
||||
"visualizations.embeddable.placeholderTitle": "占位符标题",
|
||||
"visualizations.experimentalVisInfoText": "此可视化为试验性功能,不受正式发行版功能支持 SLA 的约束。如欲提供反馈,请在 {githubLink} 中创建问题。",
|
||||
"visualizations.function.range.from.help": "范围起始",
|
||||
"visualizations.function.range.help": "生成范围对象",
|
||||
"visualizations.function.range.to.help": "范围结束",
|
||||
|
@ -5194,11 +5205,29 @@
|
|||
"visualizations.function.visDimension.formatParams.help": "格式参数",
|
||||
"visualizations.function.visDimension.help": "生成 visConfig 维度对象",
|
||||
"visualizations.function.xyDimension.aggType.help": "聚合类型",
|
||||
"visualizations.function.xydimension.help": "生成 xy 维度对象",
|
||||
"visualizations.function.xyDimension.label.help": "标签",
|
||||
"visualizations.function.xyDimension.params.help": "参数",
|
||||
"visualizations.function.xyDimension.visDimension.help": "维度对象配置",
|
||||
"visualizations.function.xydimension.help": "生成 xy 维度对象",
|
||||
"visualizations.helpMenu.appName": "Visualize 库",
|
||||
"visualizations.initializeWithoutIndexPatternErrorMessage": "正在尝试在不使用索引模式的情况下初始化聚合",
|
||||
"visualizations.legacyUrlConflict.objectNoun": "{visName} 可视化",
|
||||
"visualizations.linkedToSearch.unlinkSuccessNotificationText": "已取消与已保存搜索“{searchTitle}”的链接",
|
||||
"visualizations.listing.betaTitle": "公测版",
|
||||
"visualizations.listing.betaTooltip": "此可视化为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束",
|
||||
"visualizations.listing.breadcrumb": "Visualize 库",
|
||||
"visualizations.listing.createNew.createButtonLabel": "新建可视化",
|
||||
"visualizations.listing.createNew.description": "可以根据您的数据创建不同的可视化。",
|
||||
"visualizations.listing.createNew.title": "创建您的首个可视化",
|
||||
"visualizations.listing.experimentalTitle": "实验性",
|
||||
"visualizations.listing.experimentalTooltip": "未来版本可能会更改或删除此可视化,其不受支持 SLA 的约束。",
|
||||
"visualizations.listing.table.descriptionColumnName": "描述",
|
||||
"visualizations.listing.table.entityName": "可视化",
|
||||
"visualizations.listing.table.entityNamePlural": "可视化",
|
||||
"visualizations.listing.table.listTitle": "Visualize 库",
|
||||
"visualizations.listing.table.titleColumnName": "标题",
|
||||
"visualizations.listing.table.typeColumnName": "类型",
|
||||
"visualizations.listingPageTitle": "Visualize 库",
|
||||
"visualizations.newVisWizard.aggBasedGroupDescription": "使用我们的经典可视化库,基于聚合创建图表。",
|
||||
"visualizations.newVisWizard.aggBasedGroupTitle": "基于聚合",
|
||||
"visualizations.newVisWizard.chooseSourceTitle": "选择源",
|
||||
|
@ -5216,69 +5245,40 @@
|
|||
"visualizations.newVisWizard.searchSelection.savedObjectType.search": "已保存搜索",
|
||||
"visualizations.newVisWizard.title": "新建可视化",
|
||||
"visualizations.newVisWizard.toolsGroupTitle": "工具",
|
||||
"visualizations.noMatchRoute.bannerText": "Visualize 应用程序无法识别此路由:{route}。",
|
||||
"visualizations.noMatchRoute.bannerTitleText": "未找到页面",
|
||||
"visualizations.noResultsFoundTitle": "找不到结果",
|
||||
"visualizations.pageHeading": "{chartName} {chartType} 可视化",
|
||||
"visualizations.reporting.defaultReportTitle": "可视化 [{date}]",
|
||||
"visualizations.savedObjectName": "可视化",
|
||||
"visualizations.savingVisualizationFailed.errorMsg": "保存可视化失败",
|
||||
"visualizations.topNavMenu.cancelAndReturnButtonTooltip": "完成前放弃所做的更改",
|
||||
"visualizations.topNavMenu.cancelButtonAriaLabel": "返回到上一个应用而不保存更改",
|
||||
"visualizations.topNavMenu.cancelButtonLabel": "取消",
|
||||
"visualizations.topNavMenu.openInspectorButtonAriaLabel": "打开检查器查看可视化",
|
||||
"visualizations.topNavMenu.openInspectorButtonLabel": "检查",
|
||||
"visualizations.topNavMenu.openInspectorDisabledButtonTooltip": "此可视化不支持任何检查器。",
|
||||
"visualizations.topNavMenu.saveAndReturnVisualizationButtonAriaLabel": "完成编辑可视化并返回到最后一个应用",
|
||||
"visualizations.topNavMenu.saveAndReturnVisualizationButtonLabel": "保存并返回",
|
||||
"visualizations.topNavMenu.saveAndReturnVisualizationDisabledButtonTooltip": "完成前应用或放弃所做更改",
|
||||
"visualizations.topNavMenu.saveVisualization.failureNotificationText": "保存“{visTitle}”时出错",
|
||||
"visualizations.topNavMenu.saveVisualization.successNotificationText": "已保存“{visTitle}”",
|
||||
"visualizations.topNavMenu.saveVisualizationAsButtonLabel": "另存为",
|
||||
"visualizations.topNavMenu.saveVisualizationButtonAriaLabel": "保存可视化",
|
||||
"visualizations.topNavMenu.saveVisualizationButtonLabel": "保存",
|
||||
"visualizations.topNavMenu.saveVisualizationDisabledButtonTooltip": "保存前应用或放弃所做更改",
|
||||
"visualizations.topNavMenu.saveVisualizationObjectType": "可视化",
|
||||
"visualizations.topNavMenu.saveVisualizationToLibraryButtonLabel": "保存到库",
|
||||
"visualizations.topNavMenu.shareVisualizationButtonAriaLabel": "共享可视化",
|
||||
"visualizations.topNavMenu.shareVisualizationButtonLabel": "共享",
|
||||
"visualizations.topNavMenu.updatePanel": "更新 {originatingAppName} 中的面板",
|
||||
"visualizations.visualizationLoadingFailedErrorMessage": "无法加载可视化",
|
||||
"visualizations.visualizationTypeInvalidMessage": "无效的可视化类型“{visType}”",
|
||||
"visualize.badge.readOnly.text": "只读",
|
||||
"visualize.badge.readOnly.tooltip": "无法将可视化保存到库",
|
||||
"visualize.byValue_pageHeading": "已嵌入到 {originatingApp} 应用中的 {chartType} 类型可视化",
|
||||
"visualize.confirmModal.confirmTextDescription": "离开 Visualize 编辑器而不保存更改?",
|
||||
"visualize.confirmModal.title": "未保存的更改",
|
||||
"visualize.createVisualization.failedToLoadErrorMessage": "无法加载可视化",
|
||||
"visualize.createVisualization.noIndexPatternOrSavedSearchIdErrorMessage": "必须提供 indexPattern 或 savedSearchId",
|
||||
"visualize.createVisualization.noVisTypeErrorMessage": "必须提供有效的可视化类型",
|
||||
"visualize.editor.createBreadcrumb": "创建",
|
||||
"visualize.editor.defaultEditBreadcrumbText": "编辑可视化",
|
||||
"visualize.experimentalVisInfoText": "此可视化为试验性功能,不受正式发行版功能支持 SLA 的约束。如欲提供反馈,请在 {githubLink} 中创建问题。",
|
||||
"visualize.helpMenu.appName": "Visualize 库",
|
||||
"visualize.legacyUrlConflict.objectNoun": "{visName} 可视化",
|
||||
"visualize.linkedToSearch.unlinkSuccessNotificationText": "已取消与已保存搜索“{searchTitle}”的链接",
|
||||
"visualize.listing.betaTitle": "公测版",
|
||||
"visualize.listing.betaTooltip": "此可视化为公测版,可能会进行更改。设计和代码相对于正式发行版功能还不够成熟,将按原样提供,且不提供任何保证。公测版功能不受正式发行版功能支持 SLA 的约束",
|
||||
"visualize.listing.breadcrumb": "Visualize 库",
|
||||
"visualize.listing.createNew.createButtonLabel": "新建可视化",
|
||||
"visualize.listing.createNew.description": "可以根据您的数据创建不同的可视化。",
|
||||
"visualize.listing.createNew.title": "创建您的首个可视化",
|
||||
"visualize.listing.experimentalTitle": "实验性",
|
||||
"visualize.listing.experimentalTooltip": "未来版本可能会更改或删除此可视化,其不受支持 SLA 的约束。",
|
||||
"visualize.listing.table.descriptionColumnName": "描述",
|
||||
"visualize.listing.table.entityName": "可视化",
|
||||
"visualize.listing.table.entityNamePlural": "可视化",
|
||||
"visualize.listing.table.listTitle": "Visualize 库",
|
||||
"visualize.listing.table.titleColumnName": "标题",
|
||||
"visualize.listing.table.typeColumnName": "类型",
|
||||
"visualize.listingPageTitle": "Visualize 库",
|
||||
"visualize.noMatchRoute.bannerText": "Visualize 应用程序无法识别此路由:{route}。",
|
||||
"visualize.noMatchRoute.bannerTitleText": "未找到页面",
|
||||
"visualize.pageHeading": "{chartName} {chartType} 可视化",
|
||||
"visualize.reporting.defaultReportTitle": "可视化 [{date}]",
|
||||
"visualize.topNavMenu.cancelAndReturnButtonTooltip": "完成前放弃所做的更改",
|
||||
"visualize.topNavMenu.cancelButtonAriaLabel": "返回到上一个应用而不保存更改",
|
||||
"visualize.topNavMenu.cancelButtonLabel": "取消",
|
||||
"visualize.topNavMenu.openInspectorButtonAriaLabel": "打开检查器查看可视化",
|
||||
"visualize.topNavMenu.openInspectorButtonLabel": "检查",
|
||||
"visualize.topNavMenu.openInspectorDisabledButtonTooltip": "此可视化不支持任何检查器。",
|
||||
"visualize.topNavMenu.saveAndReturnVisualizationButtonAriaLabel": "完成编辑可视化并返回到最后一个应用",
|
||||
"visualize.topNavMenu.saveAndReturnVisualizationButtonLabel": "保存并返回",
|
||||
"visualize.topNavMenu.saveAndReturnVisualizationDisabledButtonTooltip": "完成前应用或放弃所做更改",
|
||||
"visualize.topNavMenu.saveVisualization.failureNotificationText": "保存“{visTitle}”时出错",
|
||||
"visualize.topNavMenu.saveVisualization.successNotificationText": "已保存“{visTitle}”",
|
||||
"visualize.topNavMenu.saveVisualizationAsButtonLabel": "另存为",
|
||||
"visualize.topNavMenu.saveVisualizationButtonAriaLabel": "保存可视化",
|
||||
"visualize.topNavMenu.saveVisualizationButtonLabel": "保存",
|
||||
"visualize.topNavMenu.saveVisualizationDisabledButtonTooltip": "保存前应用或放弃所做更改",
|
||||
"visualize.topNavMenu.saveVisualizationObjectType": "可视化",
|
||||
"visualize.topNavMenu.saveVisualizationToLibraryButtonLabel": "保存到库",
|
||||
"visualize.topNavMenu.shareVisualizationButtonAriaLabel": "共享可视化",
|
||||
"visualize.topNavMenu.shareVisualizationButtonLabel": "共享",
|
||||
"visualize.topNavMenu.updatePanel": "更新 {originatingAppName} 中的面板",
|
||||
"visualize.visualizationLoadingFailedErrorMessage": "无法加载可视化",
|
||||
"visualize.visualizeDescription": "创建可视化并聚合在 Elasticsearch 索引中的数据存储。",
|
||||
"visualize.visualizeListingBreadcrumbsTitle": "Visualize 库",
|
||||
"visualize.visualizeListingDashboardAppName": "Dashboard 应用程序",
|
||||
"visualize.visualizeListingDashboardFlowDescription": "构建仪表板?从 {dashboardApp}创建和添加您的可视化。",
|
||||
"visualize.visualizeListingDeleteErrorTitle": "删除可视化时出错",
|
||||
"visualizations.visualizeDescription": "创建可视化并聚合在 Elasticsearch 索引中的数据存储。",
|
||||
"visualizations.visualizeListingBreadcrumbsTitle": "Visualize 库",
|
||||
"visualizations.visualizeListingDashboardAppName": "Dashboard 应用程序",
|
||||
"visualizations.visualizeListingDashboardFlowDescription": "构建仪表板?从 {dashboardApp}创建和添加您的可视化。",
|
||||
"visualizations.visualizeListingDeleteErrorTitle": "删除可视化时出错",
|
||||
"xpack.actions.actionTypeRegistry.get.missingActionTypeErrorMessage": "操作类型“{id}”未注册。",
|
||||
"xpack.actions.actionTypeRegistry.register.duplicateActionTypeErrorMessage": "操作类型“{id}”已注册。",
|
||||
"xpack.actions.alertHistoryEsIndexConnector.name": "告警历史记录 Elasticsearch 索引",
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { VisualizeConstants } from '../../../../../../src/plugins/visualize/public/application/visualize_constants';
|
||||
import { VisualizeConstants } from '../../../../../../src/plugins/visualizations/common/constants';
|
||||
import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
export default function ({ getPageObjects, getService }: FtrProviderContext) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue