Skip to content

Commit

Permalink
[Portable Dashboards] Export Dashboard Listing Table (#154295)
Browse files Browse the repository at this point in the history
export the Dashboard Listing Page component lazily. This component is a wrapper around the TableListView and can be used as-is.
  • Loading branch information
ThomThomson authored Apr 17, 2023
1 parent 8d9777b commit b689c27
Show file tree
Hide file tree
Showing 26 changed files with 1,195 additions and 1,375 deletions.
112 changes: 95 additions & 17 deletions examples/portable_dashboards_example/public/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
* Side Public License, v 1.
*/

import React from 'react';
import ReactDOM from 'react-dom';
import React, { useMemo } from 'react';
import { useAsync } from 'react-use/lib';
import { Router, Redirect, Switch } from 'react-router-dom';

import { EuiSpacer } from '@elastic/eui';
import { Route } from '@kbn/shared-ux-router';
import { AppMountParameters } from '@kbn/core/public';
import { EuiButton, EuiCallOut, EuiSpacer } from '@elastic/eui';
import { DashboardListingTable } from '@kbn/dashboard-plugin/public';
import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';

import { DualReduxExample } from './dual_redux_example';
Expand All @@ -20,17 +24,70 @@ import { StaticByReferenceExample } from './static_by_reference_example';
import { DynamicByReferenceExample } from './dynamically_add_panels_example';
import { DashboardWithControlsExample } from './dashboard_with_controls_example';

const DASHBOARD_DEMO_PATH = '/dashboardDemo';
const DASHBOARD_LIST_PATH = '/listingDemo';

export const renderApp = async (
{ data, dashboard }: PortableDashboardsExampleStartDeps,
{ element }: AppMountParameters
{ element, history }: AppMountParameters
) => {
const dataViews = await data.dataViews.find('kibana_sample_data_logs');
const findDashboardsService = await dashboard.findDashboardsService();
const logsSampleDashboardId = (await findDashboardsService?.findByTitle('[Logs] Web Traffic'))
?.id;
ReactDOM.render(
<PortableDashboardsDemos data={data} history={history} dashboard={dashboard} />,
element
);
return () => ReactDOM.unmountComponentAtNode(element);
};

const PortableDashboardsDemos = ({
data,
dashboard,
history,
}: {
data: PortableDashboardsExampleStartDeps['data'];
dashboard: PortableDashboardsExampleStartDeps['dashboard'];
history: AppMountParameters['history'];
}) => {
return (
<Router history={history}>
<Switch>
<Route exact path="/">
<Redirect to={DASHBOARD_DEMO_PATH} />
</Route>
<Route path={DASHBOARD_LIST_PATH}>
<PortableDashboardListingDemo history={history} />
</Route>
<Route path={DASHBOARD_DEMO_PATH}>
<DashboardsDemo data={data} dashboard={dashboard} history={history} />
</Route>
</Switch>
</Router>
);
};

const examples =
dataViews.length > 0 ? (
const DashboardsDemo = ({
data,
history,
dashboard,
}: {
history: AppMountParameters['history'];
data: PortableDashboardsExampleStartDeps['data'];
dashboard: PortableDashboardsExampleStartDeps['dashboard'];
}) => {
const { loading, value: dataviewResults } = useAsync(async () => {
const dataViews = await data.dataViews.find('kibana_sample_data_logs');
const findDashboardsService = await dashboard.findDashboardsService();
const logsSampleDashboardId = (await findDashboardsService?.findByTitle('[Logs] Web Traffic'))
?.id;
return { dataViews, logsSampleDashboardId };
}, []);

const usageDemos = useMemo(() => {
if (loading || !dataviewResults) return null;
if (dataviewResults?.dataViews.length === 0) {
<div>{'Install web logs sample data to run the embeddable dashboard examples.'}</div>;
}
const { dataViews, logsSampleDashboardId } = dataviewResults;
return (
<>
<DashboardWithControlsExample dataView={dataViews[0]} />
<EuiSpacer size="xl" />
Expand All @@ -42,16 +99,37 @@ export const renderApp = async (
<EuiSpacer size="xl" />
<StaticByValueExample />
</>
) : (
<div>{'Install web logs sample data to run the embeddable dashboard examples.'}</div>
);
}, [dataviewResults, loading]);

ReactDOM.render(
return (
<KibanaPageTemplate>
<KibanaPageTemplate.Header pageTitle="Portable Dashboards" />
<KibanaPageTemplate.Section>{examples}</KibanaPageTemplate.Section>
</KibanaPageTemplate>,
element
<KibanaPageTemplate.Header pageTitle="Portable dashboards usage" />
<KibanaPageTemplate.Section>
<EuiButton onClick={() => history.push(DASHBOARD_LIST_PATH)}>
View portable dashboard listing page
</EuiButton>
<EuiSpacer size="xl" />
{usageDemos}
</KibanaPageTemplate.Section>
</KibanaPageTemplate>
);
};

const PortableDashboardListingDemo = ({ history }: { history: AppMountParameters['history'] }) => {
return (
<DashboardListingTable
goToDashboard={(dashboardId) =>
alert(`Here's where I would redirect you to ${dashboardId ?? 'a new Dashboard'}`)
}
getDashboardUrl={() => 'https://www.elastic.co/'}
>
<EuiButton onClick={() => history.push(DASHBOARD_DEMO_PATH)}>
Go back to usage demos
</EuiButton>
<EuiSpacer size="xl" />
<EuiCallOut title="You can render something cool here" iconType="search" />
<EuiSpacer size="xl" />
</DashboardListingTable>
);
return () => ReactDOM.unmountComponentAtNode(element);
};
3 changes: 2 additions & 1 deletion examples/portable_dashboards_example/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@kbn/embeddable-examples-plugin",
"@kbn/shared-ux-page-kibana-template",
"@kbn/shared-ux-utility",
"@kbn/controls-plugin"
"@kbn/controls-plugin",
"@kbn/shared-ux-router"
]
}
130 changes: 0 additions & 130 deletions src/plugins/dashboard/public/dashboard_app/_dashboard_app_strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,136 +101,6 @@ export const getPanelTooOldErrorString = () =>
defaultMessage: 'Cannot load panels from a URL created in a version older than 7.3',
});

/*
Dashboard Listing Page
*/
export const discardConfirmStrings = {
getDiscardTitle: () =>
i18n.translate('dashboard.discardChangesConfirmModal.discardChangesTitle', {
defaultMessage: 'Discard changes to dashboard?',
}),
getDiscardSubtitle: () =>
i18n.translate('dashboard.discardChangesConfirmModal.discardChangesDescription', {
defaultMessage: `Once you discard your changes, there's no getting them back.`,
}),
getDiscardConfirmButtonText: () =>
i18n.translate('dashboard.discardChangesConfirmModal.confirmButtonLabel', {
defaultMessage: 'Discard changes',
}),
getDiscardCancelButtonText: () =>
i18n.translate('dashboard.discardChangesConfirmModal.cancelButtonLabel', {
defaultMessage: 'Cancel',
}),
};

export const createConfirmStrings = {
getCreateTitle: () =>
i18n.translate('dashboard.createConfirmModal.unsavedChangesTitle', {
defaultMessage: 'New dashboard already in progress',
}),
getCreateSubtitle: () =>
i18n.translate('dashboard.createConfirmModal.unsavedChangesSubtitle', {
defaultMessage: 'Continue editing or start over with a blank dashboard.',
}),
getStartOverButtonText: () =>
i18n.translate('dashboard.createConfirmModal.confirmButtonLabel', {
defaultMessage: 'Start over',
}),
getContinueButtonText: () =>
i18n.translate('dashboard.createConfirmModal.continueButtonLabel', {
defaultMessage: 'Continue editing',
}),
getCancelButtonText: () =>
i18n.translate('dashboard.createConfirmModal.cancelButtonLabel', {
defaultMessage: 'Cancel',
}),
};

export const dashboardListingErrorStrings = {
getErrorDeletingDashboardToast: () =>
i18n.translate('dashboard.deleteError.toastDescription', {
defaultMessage: 'Error encountered while deleting dashboard',
}),
};

export const dashboardListingTableStrings = {
getEntityName: () =>
i18n.translate('dashboard.listing.table.entityName', {
defaultMessage: 'dashboard',
}),
getEntityNamePlural: () =>
i18n.translate('dashboard.listing.table.entityNamePlural', {
defaultMessage: 'dashboards',
}),
getTableListTitle: () => getDashboardPageTitle(),
};

export const noItemsStrings = {
getReadonlyTitle: () =>
i18n.translate('dashboard.listing.readonlyNoItemsTitle', {
defaultMessage: 'No dashboards to view',
}),
getReadonlyBody: () =>
i18n.translate('dashboard.listing.readonlyNoItemsBody', {
defaultMessage: `There are no available dashboards. To change your permissions to view the dashboards in this space, contact your administrator.`,
}),
getReadEditTitle: () =>
i18n.translate('dashboard.listing.createNewDashboard.title', {
defaultMessage: 'Create your first dashboard',
}),
getReadEditInProgressTitle: () =>
i18n.translate('dashboard.listing.createNewDashboard.inProgressTitle', {
defaultMessage: 'Dashboard in progress',
}),
getReadEditDashboardDescription: () =>
i18n.translate('dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription', {
defaultMessage:
'Analyze all of your Elastic data in one place by creating a dashboard and adding visualizations.',
}),
getSampleDataLinkText: () =>
i18n.translate('dashboard.listing.createNewDashboard.sampleDataInstallLinkText', {
defaultMessage: `Add some sample data`,
}),
getCreateNewDashboardText: () =>
i18n.translate('dashboard.listing.createNewDashboard.createButtonLabel', {
defaultMessage: `Create a dashboard`,
}),
};

export const dashboardUnsavedListingStrings = {
getUnsavedChangesTitle: (plural = false) =>
i18n.translate('dashboard.listing.unsaved.unsavedChangesTitle', {
defaultMessage: 'You have unsaved changes in the following {dash}:',
values: {
dash: plural
? dashboardListingTableStrings.getEntityNamePlural()
: dashboardListingTableStrings.getEntityName(),
},
}),
getLoadingTitle: () =>
i18n.translate('dashboard.listing.unsaved.loading', {
defaultMessage: 'Loading',
}),
getEditAriaLabel: (title: string) =>
i18n.translate('dashboard.listing.unsaved.editAria', {
defaultMessage: 'Continue editing {title}',
values: { title },
}),
getEditTitle: () =>
i18n.translate('dashboard.listing.unsaved.editTitle', {
defaultMessage: 'Continue editing',
}),
getDiscardAriaLabel: (title: string) =>
i18n.translate('dashboard.listing.unsaved.discardAria', {
defaultMessage: 'Discard changes to {title}',
values: { title },
}),
getDiscardTitle: () =>
i18n.translate('dashboard.listing.unsaved.discardTitle', {
defaultMessage: 'Discard changes',
}),
};

/*
Share Modal
*/
Expand Down
Loading

0 comments on commit b689c27

Please sign in to comment.