Skip to content

Commit

Permalink
Merge branch 'master' into 114785-use-latest-version-extension-point
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Oct 20, 2021
2 parents 1d4f414 + c6fcde9 commit 859a333
Show file tree
Hide file tree
Showing 141 changed files with 1,614 additions and 603 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@
"@types/reduce-reducers": "^1.0.0",
"@types/redux-actions": "^2.6.1",
"@types/seedrandom": ">=2.0.0 <4.0.0",
"@types/selenium-webdriver": "^4.0.9",
"@types/selenium-webdriver": "^4.0.15",
"@types/semver": "^7",
"@types/set-value": "^2.0.0",
"@types/sinon": "^7.0.13",
Expand Down Expand Up @@ -780,7 +780,7 @@
"rxjs-marbles": "^5.0.6",
"sass-loader": "^10.2.0",
"sass-resources-loader": "^2.0.1",
"selenium-webdriver": "^4.0.0-alpha.7",
"selenium-webdriver": "^4.0.0",
"serve-static": "1.14.1",
"shelljs": "^0.8.4",
"simple-git": "1.116.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
* Side Public License, v 1.
*/

import { convertSavedDashboardPanelToPanelState } from '../../../common/embeddable/embeddable_saved_object_converters';
import {
convertSavedDashboardPanelToPanelState,
convertPanelStateToSavedDashboardPanel,
} from '../../../common/embeddable/embeddable_saved_object_converters';
import type { SavedDashboardPanel, DashboardPanelMap } from '../../types';

export const convertSavedPanelsToPanelMap = (panels?: SavedDashboardPanel[]): DashboardPanelMap => {
Expand All @@ -16,3 +19,9 @@ export const convertSavedPanelsToPanelMap = (panels?: SavedDashboardPanel[]): Da
});
return panelsMap;
};

export const convertPanelMapToSavedPanels = (panels: DashboardPanelMap, version: string) => {
return Object.values(panels).map((panel) =>
convertPanelStateToSavedDashboardPanel(panel, version)
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
DashboardContainerInput,
DashboardBuildContext,
} from '../../types';
import { convertSavedPanelsToPanelMap } from './convert_saved_panels_to_panel_map';
import { convertSavedPanelsToPanelMap } from './convert_dashboard_panels';

interface SavedObjectToDashboardStateProps {
version: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import { ForwardedDashboardState } from '../../locator';
import { DashboardState } from '../../types';
import { convertSavedPanelsToPanelMap } from './convert_saved_panels_to_panel_map';
import { convertSavedPanelsToPanelMap } from './convert_dashboard_panels';

export const loadDashboardHistoryLocationState = (
state?: ForwardedDashboardState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import type {
DashboardState,
RawDashboardState,
} from '../../types';
import { convertSavedPanelsToPanelMap } from './convert_saved_panels_to_panel_map';
import { convertSavedPanelsToPanelMap } from './convert_dashboard_panels';

type SyncDashboardUrlStateProps = DashboardBuildContext & { savedDashboard: DashboardSavedObject };

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,16 +407,24 @@ export function DashboardTopNav({
const timeRange = timefilter.getTime();
ShowShareModal({
share,
timeRange,
kibanaVersion,
anchorElement,
dashboardCapabilities,
dashboardSessionStorage,
currentDashboardState: currentState,
savedDashboard: dashboardAppState.savedDashboard,
isDirty: Boolean(dashboardAppState.hasUnsavedChanges),
timeRange,
});
},
[dashboardAppState, dashboardCapabilities, share, kibanaVersion, timefilter]
[
share,
timefilter,
kibanaVersion,
dashboardAppState,
dashboardCapabilities,
dashboardSessionStorage,
]
);

const dashboardTopNavActions = useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@
* Side Public License, v 1.
*/

import { Capabilities } from 'src/core/public';
import { showPublicUrlSwitch } from './show_share_modal';
import { DashboardState } from '../../types';
import { DashboardAppLocatorParams } from '../..';
import { Capabilities } from '../../services/core';
import { SharePluginStart } from '../../services/share';
import { stateToRawDashboardState } from '../lib/convert_dashboard_state';
import { getSavedDashboardMock, makeDefaultServices } from '../test_helpers';
import { showPublicUrlSwitch, ShowShareModal, ShowShareModalProps } from './show_share_modal';

describe('showPublicUrlSwitch', () => {
test('returns false if "dashboard" app is not available', () => {
Expand Down Expand Up @@ -49,3 +54,100 @@ describe('showPublicUrlSwitch', () => {
expect(result).toBe(true);
});
});

describe('ShowShareModal', () => {
const unsavedStateKeys = ['query', 'filters', 'options', 'savedQuery', 'panels'] as Array<
keyof DashboardAppLocatorParams
>;

const getPropsAndShare = (
unsavedState?: Partial<DashboardState>
): { share: SharePluginStart; showModalProps: ShowShareModalProps } => {
const services = makeDefaultServices();
const share = {} as unknown as SharePluginStart;
share.toggleShareContextMenu = jest.fn();
services.dashboardSessionStorage.getState = jest.fn().mockReturnValue(unsavedState);
return {
showModalProps: {
share,
isDirty: true,
kibanaVersion: 'testKibanaVersion',
savedDashboard: getSavedDashboardMock(),
anchorElement: document.createElement('div'),
dashboardCapabilities: services.dashboardCapabilities,
currentDashboardState: { panels: {} } as unknown as DashboardState,
dashboardSessionStorage: services.dashboardSessionStorage,
timeRange: {
from: '2021-10-07T00:00:00.000Z',
to: '2021-10-10T00:00:00.000Z',
},
},
share,
};
};

it('locatorParams is missing all unsaved state when none is given', () => {
const { share, showModalProps } = getPropsAndShare();
const toggleShareMenuSpy = jest.spyOn(share, 'toggleShareContextMenu');
ShowShareModal(showModalProps);
expect(share.toggleShareContextMenu).toHaveBeenCalledTimes(1);
const shareLocatorParams = (
toggleShareMenuSpy.mock.calls[0][0].sharingData as {
locatorParams: { params: DashboardAppLocatorParams };
}
).locatorParams.params;
unsavedStateKeys.forEach((key) => {
expect(shareLocatorParams[key]).toBeUndefined();
});
});

it('locatorParams unsaved state is properly propagated to locator', () => {
const unsavedDashboardState: DashboardState = {
panels: {
panel_1: {
type: 'panel_type',
gridData: { w: 0, h: 0, x: 0, y: 0, i: '0' },
panelRefName: 'superPanel',
explicitInput: {
id: 'superPanel',
},
},
},
options: {
hidePanelTitles: true,
useMargins: true,
syncColors: true,
},
filters: [
{
meta: {
alias: null,
disabled: false,
negate: false,
},
query: { query: 'hi' },
},
],
query: { query: 'bye', language: 'kuery' },
savedQuery: 'amazingSavedQuery',
} as unknown as DashboardState;
const { share, showModalProps } = getPropsAndShare(unsavedDashboardState);
const toggleShareMenuSpy = jest.spyOn(share, 'toggleShareContextMenu');
ShowShareModal(showModalProps);
expect(share.toggleShareContextMenu).toHaveBeenCalledTimes(1);
const shareLocatorParams = (
toggleShareMenuSpy.mock.calls[0][0].sharingData as {
locatorParams: { params: DashboardAppLocatorParams };
}
).locatorParams.params;
const rawDashboardState = stateToRawDashboardState({
state: unsavedDashboardState,
version: 'testKibanaVersion',
});
unsavedStateKeys.forEach((key) => {
expect(shareLocatorParams[key]).toStrictEqual(
(rawDashboardState as Partial<DashboardAppLocatorParams>)[key]
);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,21 @@ import { SharePluginStart } from '../../services/share';
import { DashboardAppCapabilities, DashboardState } from '../../types';
import { dashboardUrlParams } from '../dashboard_router';
import { stateToRawDashboardState } from '../lib/convert_dashboard_state';
import { convertPanelMapToSavedPanels } from '../lib/convert_dashboard_panels';
import { DashboardSessionStorage } from '../lib';

const showFilterBarId = 'showFilterBar';

interface ShowShareModalProps {
export interface ShowShareModalProps {
isDirty: boolean;
timeRange: TimeRange;
kibanaVersion: string;
share: SharePluginStart;
anchorElement: HTMLElement;
savedDashboard: DashboardSavedObject;
currentDashboardState: DashboardState;
dashboardCapabilities: DashboardAppCapabilities;
timeRange: TimeRange;
dashboardSessionStorage: DashboardSessionStorage;
}

export const showPublicUrlSwitch = (anonymousUserCapabilities: Capabilities) => {
Expand All @@ -46,12 +49,13 @@ export const showPublicUrlSwitch = (anonymousUserCapabilities: Capabilities) =>
export function ShowShareModal({
share,
isDirty,
timeRange,
kibanaVersion,
anchorElement,
savedDashboard,
dashboardCapabilities,
currentDashboardState,
timeRange,
dashboardSessionStorage,
}: ShowShareModalProps) {
const EmbedUrlParamExtension = ({
setParamValue,
Expand Down Expand Up @@ -110,23 +114,31 @@ export function ShowShareModal({
);
};

const rawDashboardState = stateToRawDashboardState({
state: currentDashboardState,
version: kibanaVersion,
});
let unsavedStateForLocator: Pick<
DashboardAppLocatorParams,
'options' | 'query' | 'savedQuery' | 'filters' | 'panels'
> = {};
const unsavedDashboardState = dashboardSessionStorage.getState(savedDashboard.id);
if (unsavedDashboardState) {
unsavedStateForLocator = {
query: unsavedDashboardState.query,
filters: unsavedDashboardState.filters,
options: unsavedDashboardState.options,
savedQuery: unsavedDashboardState.savedQuery,
panels: unsavedDashboardState.panels
? convertPanelMapToSavedPanels(unsavedDashboardState.panels, kibanaVersion)
: undefined,
};
}

const locatorParams: DashboardAppLocatorParams = {
dashboardId: savedDashboard.id,
filters: rawDashboardState.filters,
preserveSavedFilters: true,
query: rawDashboardState.query,
savedQuery: rawDashboardState.savedQuery,
refreshInterval: undefined, // We don't share refresh interval externally
viewMode: ViewMode.VIEW, // For share locators we always load the dashboard in view mode
useHash: false,
panels: rawDashboardState.panels,
timeRange,
viewMode: ViewMode.VIEW, // For share locators we always load the dashboard in view mode
refreshInterval: undefined, // We don't share refresh interval externally
options: rawDashboardState.options,
...unsavedStateForLocator,
};

share.toggleShareContextMenu({
Expand All @@ -136,7 +148,10 @@ export function ShowShareModal({
allowShortUrl: dashboardCapabilities.createShortUrl,
shareableUrl: setStateToKbnUrl(
'_a',
rawDashboardState,
stateToRawDashboardState({
state: currentDashboardState,
version: kibanaVersion,
}),
{ useHash: false, storeInHashQuery: true },
unhashUrl(window.location.href)
),
Expand Down
1 change: 1 addition & 0 deletions src/plugins/dashboard/public/services/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
export {
AppMountParameters,
CoreSetup,
Capabilities,
PluginInitializerContext,
ScopedHistory,
NotificationsStart,
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/data_views/server/fetcher/lib/es_api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe('server/index_patterns/service/lib/es_api', () => {
expect(resp).toBe(football);
});

it('sets ignoreUnavailable and allowNoIndices params', async () => {
it('sets ignore_unavailable and allow_no_indices params', async () => {
const getAlias = sinon.stub();
const callCluster = {
indices: {
Expand Down Expand Up @@ -149,7 +149,7 @@ describe('server/index_patterns/service/lib/es_api', () => {
expect(resp).toBe(football);
});

it('sets ignoreUnavailable, allowNoIndices, and fields params', async () => {
it('sets ignore_unavailable, allow_no_indices, and fields params', async () => {
const fieldCaps = sinon.stub();
const callCluster = {
indices: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ describe('getSavedObjectsCounts', () => {
expect(results).toStrictEqual([]);
expect(esClient.search).toHaveBeenCalledWith({
index: '.kibana',
ignoreUnavailable: true,
filterPath: 'aggregations.types.buckets',
ignore_unavailable: true,
filter_path: 'aggregations.types.buckets',
body: {
size: 0,
query: { match_all: {} },
Expand All @@ -41,8 +41,8 @@ describe('getSavedObjectsCounts', () => {
await getSavedObjectsCounts(esClient, '.kibana');
expect(esClient.search).toHaveBeenCalledWith({
index: '.kibana',
ignoreUnavailable: true,
filterPath: 'aggregations.types.buckets',
ignore_unavailable: true,
filter_path: 'aggregations.types.buckets',
body: {
size: 0,
query: { match_all: {} },
Expand All @@ -56,8 +56,8 @@ describe('getSavedObjectsCounts', () => {
await getSavedObjectsCounts(esClient, '.kibana', ['type_one', 'type_two']);
expect(esClient.search).toHaveBeenCalledWith({
index: '.kibana',
ignoreUnavailable: true,
filterPath: 'aggregations.types.buckets',
ignore_unavailable: true,
filter_path: 'aggregations.types.buckets',
body: {
size: 0,
query: { terms: { type: ['type_one', 'type_two'] } },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ export async function getSavedObjectsCounts(

const savedObjectCountSearchParams = {
index: kibanaIndex,
ignoreUnavailable: true,
filterPath: 'aggregations.types.buckets',
ignore_unavailable: true,
filter_path: 'aggregations.types.buckets',
body: {
size: 0,
query,
Expand Down
Loading

0 comments on commit 859a333

Please sign in to comment.