Skip to content

Commit

Permalink
Add getSerializedState method to dashboard API
Browse files Browse the repository at this point in the history
  • Loading branch information
nickpeihl committed Dec 12, 2024
1 parent cca4f65 commit a9159a4
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 169 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ export function getDashboardApi({
unifiedSearchManager.internalApi.controlGroupReload$,
unifiedSearchManager.internalApi.panelsReload$
).pipe(debounceTime(0)),
getDashboardState: async () => {
getSerializedState: async () => {
const { controlGroupReferences, dashboardState, panelReferences } = await getState();
return getDashboardContentManagementService().getDashboardState({
controlGroupReferences,
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/dashboard/public/dashboard_api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ export type DashboardApi = CanExpandPanels &
focusedPanelId$: PublishingSubject<string | undefined>;
forceRefresh: () => void;
getSettings: () => DashboardStateFromSettingsFlyout;
getDashboardState: () => Promise<{
getSerializedState: () => Promise<{
attributes: DashboardAttributes;
references: SavedObjectReference[];
}>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,6 @@ export const topNavStrings = {
defaultMessage: 'Switch to edit mode',
}),
},
export: {
label: i18n.translate('dashboard.topNav.exportButtonAriaLabel', {
defaultMessage: 'export',
}),
description: i18n.translate('dashboard.topNav.exportConfigDescription', {
defaultMessage: 'Export Dashboard',
}),
},
quickSave: {
label: i18n.translate('dashboard.topNave.saveButtonAriaLabel', {
defaultMessage: 'save',
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import React, { Dispatch, SetStateAction, useCallback, useMemo, useState } from 'react';
import { Dispatch, SetStateAction, useCallback, useMemo, useState } from 'react';

import { ViewMode } from '@kbn/embeddable-plugin/public';
import type { TopNavMenuData } from '@kbn/navigation-plugin/public';
import useMountedState from 'react-use/lib/useMountedState';

import { useBatchedPublishingSubjects } from '@kbn/presentation-publishing';
import { toMountPoint } from '@kbn/react-kibana-mount';
import { UI_SETTINGS } from '../../../common';
import { useDashboardApi } from '../../dashboard_api/use_dashboard_api';
import { CHANGE_CHECK_DEBOUNCE } from '../../dashboard_constants';
Expand All @@ -26,7 +25,6 @@ import { coreServices, shareService } from '../../services/kibana_services';
import { getDashboardCapabilities } from '../../utils/get_dashboard_capabilities';
import { topNavStrings } from '../_dashboard_app_strings';
import { ShowShareModal } from './share/show_share_modal';
import { DashboardExportFlyout } from './export/show_export_flyout';

export const useDashboardMenuItems = ({
isLabsShown,
Expand Down Expand Up @@ -71,34 +69,6 @@ export const useDashboardMenuItems = ({
[dashboardTitle, hasUnsavedChanges, lastSavedId, dashboardApi]
);

/**
* Show Export flyout
*/
const showExport = useCallback(() => {
dashboardApi.openOverlay(
coreServices.overlays.openFlyout(
toMountPoint(
<DashboardExportFlyout
getDashboardState={dashboardApi.getDashboardState}
close={() => dashboardApi.clearOverlays()}
/>,
{
i18n: coreServices.i18n,
theme: coreServices.theme,
}
),
{
size: 'm',
'data-test-subj': 'dashboardExportFlyout',
onClose: (flyout) => {
dashboardApi.clearOverlays();
flyout.close();
},
}
)
);
}, [dashboardApi]);

/**
* Save the dashboard without any UI or popups.
*/
Expand Down Expand Up @@ -229,14 +199,6 @@ export const useDashboardMenuItems = ({
run: showShare,
} as TopNavMenuData,

export: {
...topNavStrings.export,
id: 'export',
testId: 'dashboardExportMenuItem',
disableButton: disableTopNav,
run: showExport,
},

settings: {
...topNavStrings.settings,
id: 'settings',
Expand All @@ -253,7 +215,6 @@ export const useDashboardMenuItems = ({
dashboardInteractiveSave,
viewMode,
showShare,
showExport,
dashboardApi,
setIsLabsShown,
isLabsShown,
Expand Down Expand Up @@ -303,7 +264,6 @@ export const useDashboardMenuItems = ({
...labsMenuItem,
menuItems.fullScreen,
...shareMenuItem,
menuItems.export,
...duplicateMenuItem,
...mayberesetChangesMenuItem,
...editMenuItem,
Expand All @@ -326,13 +286,7 @@ export const useDashboardMenuItems = ({
} else {
editModeItems.push(menuItems.switchToViewMode, menuItems.interactiveSave);
}
return [
...labsMenuItem,
menuItems.settings,
...shareMenuItem,
menuItems.export,
...editModeItems,
];
return [...labsMenuItem, menuItems.settings, ...shareMenuItem, ...editModeItems];
}, [isLabsEnabled, menuItems, lastSavedId, showResetChange, resetChangesMenuItem]);

return { viewModeTopNavConfig, editModeTopNavConfig };
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { dataService, embeddableService, savedObjectsTaggingService } from '../../kibana_services';
import { getSampleDashboardState } from '../../../mocks';
import { DashboardState } from '../../../dashboard_api/types';
import { getDashboardState } from './get_dashboard_state';

dataService.search.searchSource.create = jest.fn().mockResolvedValue({
setField: jest.fn(),
getSerializedFields: jest.fn().mockReturnValue({}),
});

dataService.query.timefilter.timefilter.getTime = jest
.fn()
.mockReturnValue({ from: 'now-15m', to: 'now' });

dataService.query.timefilter.timefilter.getRefreshInterval = jest
.fn()
.mockReturnValue({ pause: true, value: 0 });

embeddableService.extract = jest
.fn()
.mockImplementation((attributes) => ({ state: attributes, references: [] }));

if (savedObjectsTaggingService) {
savedObjectsTaggingService.getTaggingApi = jest.fn().mockReturnValue({
ui: {
updateTagsReferences: jest.fn((references, tags) => references),
},
});
}

describe('getDashboardState', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('should return the current state attributes and references', async () => {
const currentState = getSampleDashboardState();
const result = await getDashboardState({
controlGroupReferences: [],
generateNewIds: false,
currentState,
panelReferences: [],
});

expect(result.attributes.panels).toEqual([]);
expect(result.references).toEqual([]);
});

it('should generate new IDs for panels and references when generateNewIds is true', async () => {
const currentState = {
...getSampleDashboardState(),
panels: { oldPanelId: { type: 'visualization' } },
} as unknown as DashboardState;
const result = await getDashboardState({
controlGroupReferences: [],
generateNewIds: true,
currentState,
panelReferences: [
{
name: 'oldPanelId:indexpattern_foobar',
type: 'index-pattern',
id: 'bizzbuzz',
},
],
});

expect(result.attributes.panels).toEqual(
expect.arrayContaining([
expect.objectContaining({
panelIndex: expect.not.stringMatching('oldPanelId'),
type: 'visualization',
}),
])
);
expect(result.references).toEqual(
expect.arrayContaining([
{
name: expect.not.stringMatching(/^oldPanelId:/),
id: 'bizzbuzz',
type: 'index-pattern',
},
])
);
});

it('should include control group references', async () => {
const currentState = getSampleDashboardState();
const controlGroupReferences = [
{ name: 'control1:indexpattern', type: 'index-pattern', id: 'foobar' },
];
const result = await getDashboardState({
controlGroupReferences,
generateNewIds: false,
currentState,
panelReferences: [],
});

expect(result.references).toEqual(controlGroupReferences);
});

it('should include panel references', async () => {
const currentState = getSampleDashboardState();
const panelReferences = [
{ name: 'panel1:boogiewoogie', type: 'index-pattern', id: 'fizzbuzz' },
];
const result = await getDashboardState({
controlGroupReferences: [],
generateNewIds: false,
currentState,
panelReferences,
});

expect(result.references).toEqual(panelReferences);
});
});

0 comments on commit a9159a4

Please sign in to comment.