Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rshen91 committed Oct 11, 2024
1 parent 930f861 commit af0b004
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 15 deletions.
6 changes: 5 additions & 1 deletion src/plugins/dashboard/public/dashboard_app/dashboard_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { ViewMode } from '@kbn/embeddable-plugin/public';
import { useExecutionContext } from '@kbn/kibana-react-plugin/public';
import { createKbnUrlStateStorage, withNotifyOnErrors } from '@kbn/kibana-utils-plugin/public';

import type { Filter } from '@kbn/es-query';
import { DashboardApi, DashboardCreationOptions, DashboardRenderer } from '..';
import { SharedDashboardState } from '../../common';
import {
Expand Down Expand Up @@ -59,6 +60,7 @@ export interface DashboardAppProps {
redirectTo: DashboardRedirect;
embedSettings?: DashboardEmbedSettings;
expandedPanelId?: string;
unsavedFilters?: Filter[];
}

export function DashboardApp({
Expand All @@ -67,6 +69,7 @@ export function DashboardApp({
redirectTo,
history,
expandedPanelId,
unsavedFilters,
}: DashboardAppProps) {
const [showNoDataPage, setShowNoDataPage] = useState<boolean>(false);
const [regenerateId, setRegenerateId] = useState(uuidv4());
Expand Down Expand Up @@ -163,7 +166,7 @@ export function DashboardApp({
getCurrentPath: () => `#${createDashboardEditUrl(dashboardId)}`,
}),
});
}, [history, embedSettings, validateOutcome, getScopedHistory, kbnUrlStateStorage]);
}, [history, kbnUrlStateStorage, validateOutcome, embedSettings, getScopedHistory]);

useEffect(() => {
if (!dashboardApi) return;
Expand Down Expand Up @@ -221,6 +224,7 @@ export function DashboardApp({
savedObjectId={savedDashboardId}
showPlainSpinner={showPlainSpinner}
getCreationOptions={getCreationOptions}
unsavedFilters={unsavedFilters}
/>
</>
);
Expand Down
26 changes: 24 additions & 2 deletions src/plugins/dashboard/public/dashboard_app/dashboard_router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { Route, Routes } from '@kbn/shared-ux-router';
import { parse, ParsedQuery } from 'query-string';
import React from 'react';
import rison from '@kbn/rison';
import { render, unmountComponentAtNode } from 'react-dom';
import { HashRouter, Redirect, RouteComponentProps } from 'react-router-dom';

import type { Filter } from '@kbn/es-query';
import {
CREATE_NEW_DASHBOARD_URL,
createDashboardEditUrl,
Expand All @@ -28,7 +30,12 @@ import {
VIEW_DASHBOARD_URL,
} from '../dashboard_constants';
import { RedirectToProps } from '../dashboard_container/types';
import { coreServices, dataService, embeddableService } from '../services/kibana_services';
import {
coreServices,
dataService,
embeddableService,
spacesService,
} from '../services/kibana_services';
import { getDashboardCapabilities } from '../utils/get_dashboard_capabilities';
import { dashboardReadonlyBadge, getDashboardPageTitle } from './_dashboard_app_strings';
import { DashboardApp } from './dashboard_app';
Expand Down Expand Up @@ -58,6 +65,7 @@ export async function mountApp({
mountContext,
}: DashboardMountProps) {
let globalEmbedSettings: DashboardEmbedSettings | undefined;
const spaceId = (await spacesService?.getActiveSpace())?.id;

const getUrlStateStorage = (history: RouteComponentProps['history']) =>
createKbnUrlStateStorage({
Expand Down Expand Up @@ -95,20 +103,32 @@ export async function mountApp({
};
};

const getDashboardUnsavedFilters = (routeParams: string) => {
return rison.decode(routeParams);
};

const renderDashboard = (
routeProps: RouteComponentProps<{ id?: string; expandedPanelId?: string }>
routeProps: RouteComponentProps<{
id?: string;
expandedPanelId?: string;
unsavedFilters?: string;
}>
) => {
const routeParams = parse(routeProps.history.location.search);
if (routeParams.embed === 'true' && !globalEmbedSettings) {
globalEmbedSettings = getDashboardEmbedSettings(routeParams);
}
const formatUnsavedFilters = routeProps.match.params.unsavedFilters
? (getDashboardUnsavedFilters(routeProps.match.params.unsavedFilters) as Filter[])
: undefined;
return (
<DashboardApp
history={routeProps.history}
embedSettings={globalEmbedSettings}
savedDashboardId={routeProps.match.params.id}
redirectTo={redirect}
expandedPanelId={routeProps.match.params.expandedPanelId}
unsavedFilters={formatUnsavedFilters}
/>
);
};
Expand All @@ -124,6 +144,7 @@ export async function mountApp({
title={title}
kbnUrlStateStorage={getUrlStateStorage(routeProps.history)}
redirectTo={redirect}
spaceId={spaceId}
/>
);
};
Expand Down Expand Up @@ -153,6 +174,7 @@ export async function mountApp({
<Route
path={[
CREATE_NEW_DASHBOARD_URL,
`${VIEW_DASHBOARD_URL}/:id/unsavedFilters=:unsavedFilters`,
`${VIEW_DASHBOARD_URL}/:id/:expandedPanelId`,
`${VIEW_DASHBOARD_URL}/:id`,
]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,22 @@ import {
} from '../no_data/dashboard_app_no_data';
import { getDashboardListItemLink } from './get_dashboard_list_item_link';
import { getDashboardContentManagementService } from '../../services/dashboard_content_management_service';
import { DASHBOARD_STATE_SESSION_KEY } from '../../services/dashboard_backup_service';

export interface DashboardListingPageProps {
kbnUrlStateStorage: IKbnUrlStateStorage;
redirectTo: DashboardRedirect;
initialFilter?: string;
title?: string;
spaceId?: string;
}

export const DashboardListingPage = ({
title,
redirectTo,
initialFilter,
kbnUrlStateStorage,
spaceId,
}: DashboardListingPageProps) => {
const [showNoDataPage, setShowNoDataPage] = useState<boolean | undefined>();
useEffect(() => {
Expand Down Expand Up @@ -93,6 +96,12 @@ export const DashboardListingPage = ({
return null;
}

// pull the filters off the session storage and put in the url if they exist
const unsavedFiltersToUrl = JSON.parse(
sessionStorage.getItem(DASHBOARD_STATE_SESSION_KEY) ?? '[]'
);

const unsavedFilters = spaceId && unsavedFiltersToUrl ? unsavedFiltersToUrl[spaceId] : undefined;
return (
<>
{showNoDataPage && (
Expand All @@ -103,10 +112,14 @@ export const DashboardListingPage = ({
useSessionStorageIntegration={true}
initialFilter={initialFilter ?? titleFilter}
goToDashboard={(id, viewMode) => {
redirectTo({ destination: 'dashboard', id, editMode: viewMode === ViewMode.EDIT });
redirectTo({
destination: 'dashboard',
id,
editMode: viewMode === ViewMode.EDIT,
});
}}
getDashboardUrl={(id, timeRestore) => {
return getDashboardListItemLink(kbnUrlStateStorage, id, timeRestore);
return getDashboardListItemLink(kbnUrlStateStorage, id, timeRestore, unsavedFilters);
}}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

import type { QueryState } from '@kbn/data-plugin/public';
import rison from '@kbn/rison';
import { IKbnUrlStateStorage, setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public';

import {
Expand All @@ -20,12 +21,15 @@ import { coreServices } from '../../services/kibana_services';
export const getDashboardListItemLink = (
kbnUrlStateStorage: IKbnUrlStateStorage,
id: string,
timeRestore: boolean
timeRestore: boolean,
unsavedFilters?: Record<string, { filters: string }>
) => {
const useHash = coreServices.uiSettings.get('state:storeInSessionStorage'); // use hash
const unsavedFiltersForUrl =
unsavedFilters && unsavedFilters[id] ? rison.encode(unsavedFilters[id].filters) : undefined;

let url = coreServices.application.getUrlForApp(DASHBOARD_APP_ID, {
path: `#${createDashboardEditUrl(id)}`,
path: `#${createDashboardEditUrl(id, true, unsavedFiltersForUrl)}`,
});
const globalStateInUrl = kbnUrlStateStorage.get<QueryState>(GLOBAL_STATE_STORAGE_KEY) || {};

Expand Down
10 changes: 8 additions & 2 deletions src/plugins/dashboard/public/dashboard_constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

import { ViewMode } from '@kbn/embeddable-plugin/common';
import { RisonValue } from '@kbn/rison';
import type { DashboardContainerInput } from '../common';

// ------------------------------------------------------------------
Expand All @@ -27,12 +28,17 @@ export const getFullEditPath = (id?: string, editMode?: boolean) => {
return `/app/dashboards#${createDashboardEditUrl(id, editMode)}`;
};

export function createDashboardEditUrl(id?: string, editMode?: boolean) {
export function createDashboardEditUrl(
id?: string,
editMode?: boolean,
unsavedFilters?: RisonValue
) {
if (!id) {
return `${CREATE_NEW_DASHBOARD_URL}`;
}
const edit = editMode ? `?${DASHBOARD_STATE_STORAGE_KEY}=(viewMode:edit)` : '';
return `${VIEW_DASHBOARD_URL}/${id}${edit}`;
const filters = unsavedFilters ? `/unsavedFilters=${unsavedFilters}` : '';
return `${VIEW_DASHBOARD_URL}/${id}${filters}${edit}`;
}

export function createDashboardListingFilterUrl(filter: string | undefined) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export class DashboardContainerFactoryDefinition
dashboardCreationStartTime,
savedObjectId
);
dashboard?.setFilters(initialInput.filters || []);
return dashboard;
} catch (e) {
return new ErrorEmbeddable(e, { id: e.id });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { SavedObjectNotFound } from '@kbn/kibana-utils-plugin/common';
import { useStateFromPublishingSubject } from '@kbn/presentation-publishing';
import { LocatorPublic } from '@kbn/share-plugin/common';

import type { Filter } from '@kbn/es-query';
import { DashboardContainerInput } from '../../../common';
import { DashboardApi } from '../../dashboard_api/types';
import { embeddableService, screenshotModeService } from '../../services/kibana_services';
Expand All @@ -36,6 +37,7 @@ export interface DashboardRendererProps {
dashboardRedirect?: DashboardRedirect;
getCreationOptions?: () => Promise<DashboardCreationOptions>;
locator?: Pick<LocatorPublic<DashboardLocatorParams>, 'navigate' | 'getRedirectUrl'>;
unsavedFilters?: Filter[];
}

export function DashboardRenderer({
Expand All @@ -45,6 +47,7 @@ export function DashboardRenderer({
showPlainSpinner,
locator,
onApiAvailable,
unsavedFilters,
}: DashboardRendererProps) {
const dashboardRoot = useRef(null);
const dashboardViewport = useRef(null);
Expand All @@ -57,8 +60,10 @@ export function DashboardRenderer({

useEffect(() => {
/* In case the locator prop changes, we need to reassign the value in the container */
if (dashboardContainer) dashboardContainer.locator = locator;
}, [dashboardContainer, locator]);
if (dashboardContainer) {
dashboardContainer.locator = locator;
}
}, [dashboardContainer, locator, unsavedFilters]);

useEffect(() => {
/**
Expand Down Expand Up @@ -86,10 +91,9 @@ export function DashboardRenderer({
let canceled = false;
(async () => {
const creationOptions = await getCreationOptions?.();

const dashboardFactory = new DashboardContainerFactoryDefinition(embeddableService);
const container = await dashboardFactory.create(
{ id } as unknown as DashboardContainerInput, // Input from creationOptions is used instead.
{ id, filters: unsavedFilters } as unknown as DashboardContainerInput, // Input from creationOptions is used instead.
undefined,
creationOptions,
savedObjectId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { SavedObjectsFindOptionsReference } from '@kbn/core/public';
import { reportPerformanceMetricEvent } from '@kbn/ebt-tools';
import { ViewMode } from '@kbn/embeddable-plugin/public';

import type { Filter } from '@kbn/es-query';
import { DashboardContainerInput } from '../../../common';
import { DashboardItem } from '../../../common/content_management';
import {
Expand Down Expand Up @@ -89,7 +90,7 @@ export const useDashboardListingTable = ({
dashboardListingId?: string;
disableCreateDashboardButton?: boolean;
getDashboardUrl: (dashboardId: string, usesTimeRestore: boolean) => string;
goToDashboard: (dashboardId?: string, viewMode?: ViewMode) => void;
goToDashboard: (dashboardId?: string, viewMode?: ViewMode, unsavedFilters?: Filter[]) => void;
headingId?: string;
initialFilter?: string;
urlStateEnabled?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const DASHBOARD_PANELS_SESSION_KEY = 'dashboardPanels';
const DASHBOARD_VIEWMODE_LOCAL_KEY = 'dashboardViewMode';

// this key is named `panels` for BWC reasons, but actually contains the entire dashboard state
const DASHBOARD_STATE_SESSION_KEY = 'dashboardStateManagerPanels';
export const DASHBOARD_STATE_SESSION_KEY = 'dashboardStateManagerPanels';

interface DashboardBackupServiceType {
clearState: (id?: string) => void;
Expand Down

0 comments on commit af0b004

Please sign in to comment.