Unifying converting listing pages to new layout (#98651)

Co-authored-by: Caroline Horn <549577+cchaos@users.noreply.github.com>
Co-authored-by: cchaos <caroline.horn@elastic.co>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Michail Yasonik 2021-05-06 18:31:20 -04:00 committed by GitHub
parent 238fc3ac1d
commit 921c942bef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 1049 additions and 656 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

View file

@ -70,6 +70,14 @@ Check out the Map Embeddable if you wish to embed a map in your application.
**Github labels**: `Team:Geo`
### KibanaPageTemplate
All Kibana pages should use KibanaPageTemplate to setup their pages. It's a thin wrapper around [EuiPageTemplate](https://elastic.github.io/eui/#/layout/page) that makes setting up common types of Kibana pages quicker and easier while also adhering to any Kibana-specific requirements.
Check out <DocLink id="kibDevDocsKBTTutorial" text="the KibanaPageTemplate tutorial" /> for more implementation guidance.
**Github labels**: `EUI`
## Searching
### Index Patterns

View file

@ -0,0 +1,86 @@
---
id: kibDevDocsKBLTutorial
slug: /kibana-dev-docs/tutorials/kibana-page-layout
title: KibanaPageLayout component
summary: Learn how to create pages in Kibana
date: 2021-03-20
tags: ['kibana', 'dev', 'ui', 'tutorials']
---
`KibanaPageLayout` is a thin wrapper around [EuiPageTemplate](https://elastic.github.io/eui/#/layout/page) that makes setting up common types of Kibana pages quicker and easier while also adhering to any Kibana-specific requirements and patterns.
Refer to EUI's documentation on [EuiPageTemplate](https://elastic.github.io/eui/#/layout/page) for constructing page layouts.
## `isEmptyState`
Use the `isEmptyState` prop for when there is no page content to show. For example, before the user has created something, when no search results are found, before data is populated, or when permissions aren't met.
The default empty state uses any `pageHeader` info provided to populate an [`EuiEmptyPrompt`](https://elastic.github.io/eui/#/display/empty-prompt) and uses the `centeredBody` template type.
```tsx
<KibanaPageLayout
isEmptyState={true}
pageHeader={{
iconType: 'dashboardApp',
pageTitle: 'Dashboards',
description: "You don't have any dashboards yet.",
rightSideItems: [
<EuiButton fill iconType="plusInCircleFilled">
Create new dashboard
</EuiButton>,
],
}}
/>
```
![Screenshot of demo empty state code. Shows the Kibana navigation bars and a centered empty state with the dashboard app icon, a level 1 heading "Dashboards", body text "You don't have any dashboards yet.", and a button that says "Create new dashboard".](../assets/kibana_default_empty_state.png)
<DocCallOut color="warning" title="Missing page header content can lead to an anemic empty state">
Because all properties of the page header are optional, the empty state has the potential to
render blank. Make sure your empty state doesn't leave the user confused.
</DocCallOut>
### Custom empty state
You can also provide a custom empty prompt to replace the pre-built one. You'll want to remove any `pageHeader` props and pass an [`EuiEmptyPrompt`](https://elastic.github.io/eui/#/display/empty-prompt) directly as the child of KibanaPageLayout.
```tsx
<KibanaPageLayout isEmptyState={true}>
<EuiEmptyPrompt
title={<h1>No data</h1>}
body="You have no data. Would you like some of ours?"
actions={[
<EuiButton fill iconType="plusInCircleFilled">
Get sample data
</EuiButton>,
]}
/>
</KibanaPageLayout>
```
![Screenshot of demo custom empty state code. Shows the Kibana navigation bars and a centered empty state with the a level 1 heading "No data", body text "You have no data. Would you like some of ours?", and a button that says "Get sample data".](../assets/kibana_custom_empty_state.png)
### Empty states with a page header
When passing both a `pageHeader` configuration and `isEmptyState`, the component will render the proper template (`centeredContent`). Be sure to reduce the heading level within your child empty prompt to `<h2>`.
```tsx
<KibanaPageLayout
isEmptyState={true}
pageHeader={{
pageTitle: 'Dashboards',
}}
>
<EuiEmptyPrompt
title={<h2>No data</h2>}
body="You have no data. Would you like some of ours?"
actions={[
<EuiButton fill iconType="plusInCircleFilled">
Get sample data
</EuiButton>,
]}
/>
</KibanaPageLayout>
```
![Screenshot of demo custom empty state code with a page header. Shows the Kibana navigation bars, a level 1 heading "Dashboards", and a centered empty state with the a level 2 heading "No data", body text "You have no data. Would you like some of ours?", and a button that says "Get sample data".](../assets/kibana_header_and_empty_state.png)

View file

@ -25,6 +25,66 @@ exports[`after fetch When given a title that matches multiple dashboards, filter
createItem={[Function]}
deleteItems={[Function]}
editItem={[Function]}
emptyPrompt={
<EuiEmptyPrompt
actions={
<EuiButton
data-test-subj="createDashboardPromptButton"
fill={true}
iconType="plusInCircle"
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Create new dashboard"
id="dashboard.listing.createNewDashboard.createButtonLabel"
values={Object {}}
/>
</EuiButton>
}
body={
<React.Fragment>
<p>
<FormattedMessage
defaultMessage="You can combine data views from any Kibana app into one dashboard and see everything in one place."
id="dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
values={Object {}}
/>
</p>
<p>
<FormattedMessage
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
id="dashboard.listing.createNewDashboard.newToKibanaDescription"
values={
Object {
"sampleDataInstallLink": <EuiLink
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Install some sample data"
id="dashboard.listing.createNewDashboard.sampleDataInstallLinkText"
values={Object {}}
/>
</EuiLink>,
}
}
/>
</p>
</React.Fragment>
}
iconType="dashboardApp"
title={
<h1
id="dashboardListingHeading"
>
<FormattedMessage
defaultMessage="Create your first dashboard"
id="dashboard.listing.createNewDashboard.title"
values={Object {}}
/>
</h1>
}
/>
}
entityName="dashboard"
entityNamePlural="dashboards"
findItems={[Function]}
@ -32,68 +92,6 @@ exports[`after fetch When given a title that matches multiple dashboards, filter
initialFilter="\\"search by title\\""
initialPageSize={20}
listingLimit={100}
noItemsFragment={
<div>
<EuiEmptyPrompt
actions={
<EuiButton
data-test-subj="createDashboardPromptButton"
fill={true}
iconType="plusInCircle"
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Create new dashboard"
id="dashboard.listing.createNewDashboard.createButtonLabel"
values={Object {}}
/>
</EuiButton>
}
body={
<React.Fragment>
<p>
<FormattedMessage
defaultMessage="You can combine data views from any Kibana app into one dashboard and see everything in one place."
id="dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
values={Object {}}
/>
</p>
<p>
<FormattedMessage
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
id="dashboard.listing.createNewDashboard.newToKibanaDescription"
values={
Object {
"sampleDataInstallLink": <EuiLink
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Install some sample data"
id="dashboard.listing.createNewDashboard.sampleDataInstallLinkText"
values={Object {}}
/>
</EuiLink>,
}
}
/>
</p>
</React.Fragment>
}
iconType="dashboardApp"
title={
<h1
id="dashboardListingHeading"
>
<FormattedMessage
defaultMessage="Create your first dashboard"
id="dashboard.listing.createNewDashboard.title"
values={Object {}}
/>
</h1>
}
/>
</div>
}
rowHeader="title"
searchFilters={Array []}
tableCaption="Dashboards"
@ -126,24 +124,7 @@ exports[`after fetch When given a title that matches multiple dashboards, filter
"remove": [MockFunction],
}
}
>
<EuiPage
className="itemListing__page"
data-test-subj="dashboardLandingPage"
restrictWidth={true}
>
<div
className="euiPage euiPage--paddingMedium euiPage--grow euiPage--restrictWidth-default itemListing__page"
data-test-subj="dashboardLandingPage"
>
<EuiPageBody>
<main
className="euiPageBody euiPageBody--borderRadiusNone"
/>
</EuiPageBody>
</div>
</EuiPage>
</TableListView>
/>
</DashboardListing>
`;
@ -168,6 +149,22 @@ exports[`after fetch hideWriteControls 1`] = `
redirectTo={[MockFunction]}
>
<TableListView
emptyPrompt={
<EuiEmptyPrompt
iconType="dashboardApp"
title={
<h1
id="dashboardListingHeading"
>
<FormattedMessage
defaultMessage="Looks like you don't have any dashboards."
id="dashboard.listing.noItemsMessage"
values={Object {}}
/>
</h1>
}
/>
}
entityName="dashboard"
entityNamePlural="dashboards"
findItems={[Function]}
@ -175,24 +172,6 @@ exports[`after fetch hideWriteControls 1`] = `
initialFilter=""
initialPageSize={20}
listingLimit={100}
noItemsFragment={
<div>
<EuiEmptyPrompt
iconType="dashboardApp"
title={
<h1
id="dashboardListingHeading"
>
<FormattedMessage
defaultMessage="Looks like you don't have any dashboards."
id="dashboard.listing.noItemsMessage"
values={Object {}}
/>
</h1>
}
/>
</div>
}
rowHeader="title"
searchFilters={Array []}
tableCaption="Dashboards"
@ -225,24 +204,7 @@ exports[`after fetch hideWriteControls 1`] = `
"remove": [MockFunction],
}
}
>
<EuiPage
className="itemListing__page"
data-test-subj="dashboardLandingPage"
restrictWidth={true}
>
<div
className="euiPage euiPage--paddingMedium euiPage--grow euiPage--restrictWidth-default itemListing__page"
data-test-subj="dashboardLandingPage"
>
<EuiPageBody>
<main
className="euiPageBody euiPageBody--borderRadiusNone"
/>
</EuiPageBody>
</div>
</EuiPage>
</TableListView>
/>
</DashboardListing>
`;
@ -271,6 +233,66 @@ exports[`after fetch initialFilter 1`] = `
createItem={[Function]}
deleteItems={[Function]}
editItem={[Function]}
emptyPrompt={
<EuiEmptyPrompt
actions={
<EuiButton
data-test-subj="createDashboardPromptButton"
fill={true}
iconType="plusInCircle"
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Create new dashboard"
id="dashboard.listing.createNewDashboard.createButtonLabel"
values={Object {}}
/>
</EuiButton>
}
body={
<React.Fragment>
<p>
<FormattedMessage
defaultMessage="You can combine data views from any Kibana app into one dashboard and see everything in one place."
id="dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
values={Object {}}
/>
</p>
<p>
<FormattedMessage
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
id="dashboard.listing.createNewDashboard.newToKibanaDescription"
values={
Object {
"sampleDataInstallLink": <EuiLink
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Install some sample data"
id="dashboard.listing.createNewDashboard.sampleDataInstallLinkText"
values={Object {}}
/>
</EuiLink>,
}
}
/>
</p>
</React.Fragment>
}
iconType="dashboardApp"
title={
<h1
id="dashboardListingHeading"
>
<FormattedMessage
defaultMessage="Create your first dashboard"
id="dashboard.listing.createNewDashboard.title"
values={Object {}}
/>
</h1>
}
/>
}
entityName="dashboard"
entityNamePlural="dashboards"
findItems={[Function]}
@ -278,68 +300,6 @@ exports[`after fetch initialFilter 1`] = `
initialFilter="testFilter"
initialPageSize={20}
listingLimit={100}
noItemsFragment={
<div>
<EuiEmptyPrompt
actions={
<EuiButton
data-test-subj="createDashboardPromptButton"
fill={true}
iconType="plusInCircle"
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Create new dashboard"
id="dashboard.listing.createNewDashboard.createButtonLabel"
values={Object {}}
/>
</EuiButton>
}
body={
<React.Fragment>
<p>
<FormattedMessage
defaultMessage="You can combine data views from any Kibana app into one dashboard and see everything in one place."
id="dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
values={Object {}}
/>
</p>
<p>
<FormattedMessage
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
id="dashboard.listing.createNewDashboard.newToKibanaDescription"
values={
Object {
"sampleDataInstallLink": <EuiLink
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Install some sample data"
id="dashboard.listing.createNewDashboard.sampleDataInstallLinkText"
values={Object {}}
/>
</EuiLink>,
}
}
/>
</p>
</React.Fragment>
}
iconType="dashboardApp"
title={
<h1
id="dashboardListingHeading"
>
<FormattedMessage
defaultMessage="Create your first dashboard"
id="dashboard.listing.createNewDashboard.title"
values={Object {}}
/>
</h1>
}
/>
</div>
}
rowHeader="title"
searchFilters={Array []}
tableCaption="Dashboards"
@ -372,24 +332,7 @@ exports[`after fetch initialFilter 1`] = `
"remove": [MockFunction],
}
}
>
<EuiPage
className="itemListing__page"
data-test-subj="dashboardLandingPage"
restrictWidth={true}
>
<div
className="euiPage euiPage--paddingMedium euiPage--grow euiPage--restrictWidth-default itemListing__page"
data-test-subj="dashboardLandingPage"
>
<EuiPageBody>
<main
className="euiPageBody euiPageBody--borderRadiusNone"
/>
</EuiPageBody>
</div>
</EuiPage>
</TableListView>
/>
</DashboardListing>
`;
@ -417,6 +360,66 @@ exports[`after fetch renders all table rows 1`] = `
createItem={[Function]}
deleteItems={[Function]}
editItem={[Function]}
emptyPrompt={
<EuiEmptyPrompt
actions={
<EuiButton
data-test-subj="createDashboardPromptButton"
fill={true}
iconType="plusInCircle"
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Create new dashboard"
id="dashboard.listing.createNewDashboard.createButtonLabel"
values={Object {}}
/>
</EuiButton>
}
body={
<React.Fragment>
<p>
<FormattedMessage
defaultMessage="You can combine data views from any Kibana app into one dashboard and see everything in one place."
id="dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
values={Object {}}
/>
</p>
<p>
<FormattedMessage
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
id="dashboard.listing.createNewDashboard.newToKibanaDescription"
values={
Object {
"sampleDataInstallLink": <EuiLink
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Install some sample data"
id="dashboard.listing.createNewDashboard.sampleDataInstallLinkText"
values={Object {}}
/>
</EuiLink>,
}
}
/>
</p>
</React.Fragment>
}
iconType="dashboardApp"
title={
<h1
id="dashboardListingHeading"
>
<FormattedMessage
defaultMessage="Create your first dashboard"
id="dashboard.listing.createNewDashboard.title"
values={Object {}}
/>
</h1>
}
/>
}
entityName="dashboard"
entityNamePlural="dashboards"
findItems={[Function]}
@ -424,68 +427,6 @@ exports[`after fetch renders all table rows 1`] = `
initialFilter=""
initialPageSize={20}
listingLimit={100}
noItemsFragment={
<div>
<EuiEmptyPrompt
actions={
<EuiButton
data-test-subj="createDashboardPromptButton"
fill={true}
iconType="plusInCircle"
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Create new dashboard"
id="dashboard.listing.createNewDashboard.createButtonLabel"
values={Object {}}
/>
</EuiButton>
}
body={
<React.Fragment>
<p>
<FormattedMessage
defaultMessage="You can combine data views from any Kibana app into one dashboard and see everything in one place."
id="dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
values={Object {}}
/>
</p>
<p>
<FormattedMessage
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
id="dashboard.listing.createNewDashboard.newToKibanaDescription"
values={
Object {
"sampleDataInstallLink": <EuiLink
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Install some sample data"
id="dashboard.listing.createNewDashboard.sampleDataInstallLinkText"
values={Object {}}
/>
</EuiLink>,
}
}
/>
</p>
</React.Fragment>
}
iconType="dashboardApp"
title={
<h1
id="dashboardListingHeading"
>
<FormattedMessage
defaultMessage="Create your first dashboard"
id="dashboard.listing.createNewDashboard.title"
values={Object {}}
/>
</h1>
}
/>
</div>
}
rowHeader="title"
searchFilters={Array []}
tableCaption="Dashboards"
@ -518,24 +459,7 @@ exports[`after fetch renders all table rows 1`] = `
"remove": [MockFunction],
}
}
>
<EuiPage
className="itemListing__page"
data-test-subj="dashboardLandingPage"
restrictWidth={true}
>
<div
className="euiPage euiPage--paddingMedium euiPage--grow euiPage--restrictWidth-default itemListing__page"
data-test-subj="dashboardLandingPage"
>
<EuiPageBody>
<main
className="euiPageBody euiPageBody--borderRadiusNone"
/>
</EuiPageBody>
</div>
</EuiPage>
</TableListView>
/>
</DashboardListing>
`;
@ -563,6 +487,66 @@ exports[`after fetch renders call to action when no dashboards exist 1`] = `
createItem={[Function]}
deleteItems={[Function]}
editItem={[Function]}
emptyPrompt={
<EuiEmptyPrompt
actions={
<EuiButton
data-test-subj="createDashboardPromptButton"
fill={true}
iconType="plusInCircle"
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Create new dashboard"
id="dashboard.listing.createNewDashboard.createButtonLabel"
values={Object {}}
/>
</EuiButton>
}
body={
<React.Fragment>
<p>
<FormattedMessage
defaultMessage="You can combine data views from any Kibana app into one dashboard and see everything in one place."
id="dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
values={Object {}}
/>
</p>
<p>
<FormattedMessage
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
id="dashboard.listing.createNewDashboard.newToKibanaDescription"
values={
Object {
"sampleDataInstallLink": <EuiLink
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Install some sample data"
id="dashboard.listing.createNewDashboard.sampleDataInstallLinkText"
values={Object {}}
/>
</EuiLink>,
}
}
/>
</p>
</React.Fragment>
}
iconType="dashboardApp"
title={
<h1
id="dashboardListingHeading"
>
<FormattedMessage
defaultMessage="Create your first dashboard"
id="dashboard.listing.createNewDashboard.title"
values={Object {}}
/>
</h1>
}
/>
}
entityName="dashboard"
entityNamePlural="dashboards"
findItems={[Function]}
@ -570,68 +554,6 @@ exports[`after fetch renders call to action when no dashboards exist 1`] = `
initialFilter=""
initialPageSize={20}
listingLimit={100}
noItemsFragment={
<div>
<EuiEmptyPrompt
actions={
<EuiButton
data-test-subj="createDashboardPromptButton"
fill={true}
iconType="plusInCircle"
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Create new dashboard"
id="dashboard.listing.createNewDashboard.createButtonLabel"
values={Object {}}
/>
</EuiButton>
}
body={
<React.Fragment>
<p>
<FormattedMessage
defaultMessage="You can combine data views from any Kibana app into one dashboard and see everything in one place."
id="dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
values={Object {}}
/>
</p>
<p>
<FormattedMessage
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
id="dashboard.listing.createNewDashboard.newToKibanaDescription"
values={
Object {
"sampleDataInstallLink": <EuiLink
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Install some sample data"
id="dashboard.listing.createNewDashboard.sampleDataInstallLinkText"
values={Object {}}
/>
</EuiLink>,
}
}
/>
</p>
</React.Fragment>
}
iconType="dashboardApp"
title={
<h1
id="dashboardListingHeading"
>
<FormattedMessage
defaultMessage="Create your first dashboard"
id="dashboard.listing.createNewDashboard.title"
values={Object {}}
/>
</h1>
}
/>
</div>
}
rowHeader="title"
searchFilters={Array []}
tableCaption="Dashboards"
@ -664,24 +586,7 @@ exports[`after fetch renders call to action when no dashboards exist 1`] = `
"remove": [MockFunction],
}
}
>
<EuiPage
className="itemListing__page"
data-test-subj="dashboardLandingPage"
restrictWidth={true}
>
<div
className="euiPage euiPage--paddingMedium euiPage--grow euiPage--restrictWidth-default itemListing__page"
data-test-subj="dashboardLandingPage"
>
<EuiPageBody>
<main
className="euiPageBody euiPageBody--borderRadiusNone"
/>
</EuiPageBody>
</div>
</EuiPage>
</TableListView>
/>
</DashboardListing>
`;
@ -709,6 +614,66 @@ exports[`after fetch renders warning when listingLimit is exceeded 1`] = `
createItem={[Function]}
deleteItems={[Function]}
editItem={[Function]}
emptyPrompt={
<EuiEmptyPrompt
actions={
<EuiButton
data-test-subj="createDashboardPromptButton"
fill={true}
iconType="plusInCircle"
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Create new dashboard"
id="dashboard.listing.createNewDashboard.createButtonLabel"
values={Object {}}
/>
</EuiButton>
}
body={
<React.Fragment>
<p>
<FormattedMessage
defaultMessage="You can combine data views from any Kibana app into one dashboard and see everything in one place."
id="dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
values={Object {}}
/>
</p>
<p>
<FormattedMessage
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
id="dashboard.listing.createNewDashboard.newToKibanaDescription"
values={
Object {
"sampleDataInstallLink": <EuiLink
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Install some sample data"
id="dashboard.listing.createNewDashboard.sampleDataInstallLinkText"
values={Object {}}
/>
</EuiLink>,
}
}
/>
</p>
</React.Fragment>
}
iconType="dashboardApp"
title={
<h1
id="dashboardListingHeading"
>
<FormattedMessage
defaultMessage="Create your first dashboard"
id="dashboard.listing.createNewDashboard.title"
values={Object {}}
/>
</h1>
}
/>
}
entityName="dashboard"
entityNamePlural="dashboards"
findItems={[Function]}
@ -716,68 +681,6 @@ exports[`after fetch renders warning when listingLimit is exceeded 1`] = `
initialFilter=""
initialPageSize={20}
listingLimit={1}
noItemsFragment={
<div>
<EuiEmptyPrompt
actions={
<EuiButton
data-test-subj="createDashboardPromptButton"
fill={true}
iconType="plusInCircle"
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Create new dashboard"
id="dashboard.listing.createNewDashboard.createButtonLabel"
values={Object {}}
/>
</EuiButton>
}
body={
<React.Fragment>
<p>
<FormattedMessage
defaultMessage="You can combine data views from any Kibana app into one dashboard and see everything in one place."
id="dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
values={Object {}}
/>
</p>
<p>
<FormattedMessage
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
id="dashboard.listing.createNewDashboard.newToKibanaDescription"
values={
Object {
"sampleDataInstallLink": <EuiLink
onClick={[Function]}
>
<FormattedMessage
defaultMessage="Install some sample data"
id="dashboard.listing.createNewDashboard.sampleDataInstallLinkText"
values={Object {}}
/>
</EuiLink>,
}
}
/>
</p>
</React.Fragment>
}
iconType="dashboardApp"
title={
<h1
id="dashboardListingHeading"
>
<FormattedMessage
defaultMessage="Create your first dashboard"
id="dashboard.listing.createNewDashboard.title"
values={Object {}}
/>
</h1>
}
/>
</div>
}
rowHeader="title"
searchFilters={Array []}
tableCaption="Dashboards"
@ -810,23 +713,6 @@ exports[`after fetch renders warning when listingLimit is exceeded 1`] = `
"remove": [MockFunction],
}
}
>
<EuiPage
className="itemListing__page"
data-test-subj="dashboardLandingPage"
restrictWidth={true}
>
<div
className="euiPage euiPage--paddingMedium euiPage--grow euiPage--restrictWidth-default itemListing__page"
data-test-subj="dashboardLandingPage"
>
<EuiPageBody>
<main
className="euiPageBody euiPageBody--borderRadiusNone"
/>
</EuiPageBody>
</div>
</EuiPage>
</TableListView>
/>
</DashboardListing>
`;

View file

@ -113,7 +113,7 @@ export const DashboardListing = ({
}
}, [dashboardPanelStorage, redirectTo, core.overlays]);
const noItemsFragment = useMemo(
const emptyPrompt = useMemo(
() => getNoItemsMessage(hideWriteControls, core.application, createItem),
[createItem, core.application, hideWriteControls]
);
@ -181,7 +181,7 @@ export const DashboardListing = ({
tableCaption={getTableCaption()}
entityName={getEntityName()}
{...{
noItemsFragment,
emptyPrompt,
searchFilters,
listingLimit,
tableColumns,
@ -241,80 +241,76 @@ const getNoItemsMessage = (
) => {
if (hideWriteControls) {
return (
<div>
<EuiEmptyPrompt
iconType="dashboardApp"
title={
<h1 id="dashboardListingHeading">
<FormattedMessage
id="dashboard.listing.noItemsMessage"
defaultMessage="Looks like you don't have any dashboards."
/>
</h1>
}
/>
</div>
);
}
return (
<div>
<EuiEmptyPrompt
iconType="dashboardApp"
title={
<h1 id="dashboardListingHeading">
<FormattedMessage
id="dashboard.listing.createNewDashboard.title"
defaultMessage="Create your first dashboard"
id="dashboard.listing.noItemsMessage"
defaultMessage="Looks like you don't have any dashboards."
/>
</h1>
}
body={
<Fragment>
<p>
<FormattedMessage
id="dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
defaultMessage="You can combine data views from any Kibana app into one dashboard and see everything in one place."
/>
</p>
<p>
<FormattedMessage
id="dashboard.listing.createNewDashboard.newToKibanaDescription"
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
values={{
sampleDataInstallLink: (
<EuiLink
onClick={() =>
application.navigateToApp('home', {
path: '#/tutorial_directory/sampleData',
})
}
>
<FormattedMessage
id="dashboard.listing.createNewDashboard.sampleDataInstallLinkText"
defaultMessage="Install some sample data"
/>
</EuiLink>
),
}}
/>
</p>
</Fragment>
}
actions={
<EuiButton
onClick={createItem}
fill
iconType="plusInCircle"
data-test-subj="createDashboardPromptButton"
>
<FormattedMessage
id="dashboard.listing.createNewDashboard.createButtonLabel"
defaultMessage="Create new dashboard"
/>
</EuiButton>
}
/>
</div>
);
}
return (
<EuiEmptyPrompt
iconType="dashboardApp"
title={
<h1 id="dashboardListingHeading">
<FormattedMessage
id="dashboard.listing.createNewDashboard.title"
defaultMessage="Create your first dashboard"
/>
</h1>
}
body={
<Fragment>
<p>
<FormattedMessage
id="dashboard.listing.createNewDashboard.combineDataViewFromKibanaAppDescription"
defaultMessage="You can combine data views from any Kibana app into one dashboard and see everything in one place."
/>
</p>
<p>
<FormattedMessage
id="dashboard.listing.createNewDashboard.newToKibanaDescription"
defaultMessage="New to Kibana? {sampleDataInstallLink} to take a test drive."
values={{
sampleDataInstallLink: (
<EuiLink
onClick={() =>
application.navigateToApp('home', {
path: '#/tutorial_directory/sampleData',
})
}
>
<FormattedMessage
id="dashboard.listing.createNewDashboard.sampleDataInstallLinkText"
defaultMessage="Install some sample data"
/>
</EuiLink>
),
}}
/>
</p>
</Fragment>
}
actions={
<EuiButton
onClick={createItem}
fill
iconType="plusInCircle"
data-test-subj="createDashboardPromptButton"
>
<FormattedMessage
id="dashboard.listing.createNewDashboard.createButtonLabel"
defaultMessage="Create new dashboard"
/>
</EuiButton>
}
/>
);
};

View file

@ -19,6 +19,7 @@ export * from './table_list_view';
export * from './toolbar_button';
export * from './split_panel';
export * from './react_router_navigate';
export * from './page_template';
export { ValidatedDualRange, Value } from './validated_range';
export * from './notifications';
export { Markdown, MarkdownSimple } from './markdown';

View file

@ -0,0 +1,78 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`KibanaPageTemplate render basic template 1`] = `
<EuiPageTemplate
pageHeader={
Object {
"description": "test",
"iconType": "test",
"rightSideItems": Array [
"test",
],
"title": "test",
}
}
restrictWidth={true}
/>
`;
exports[`KibanaPageTemplate render custom empty prompt only 1`] = `
<EuiPageTemplate
restrictWidth={true}
template="centeredBody"
>
<EuiEmptyPrompt
title={
<h1>
custom test
</h1>
}
/>
</EuiPageTemplate>
`;
exports[`KibanaPageTemplate render custom empty prompt with page header 1`] = `
<EuiPageTemplate
pageHeader={
Object {
"description": "test",
"iconType": "test",
"rightSideItems": Array [
"test",
],
"title": "test",
}
}
restrictWidth={true}
template="centeredContent"
>
<EuiEmptyPrompt
title={
<h1>
custom test
</h1>
}
/>
</EuiPageTemplate>
`;
exports[`KibanaPageTemplate render default empty prompt 1`] = `
<EuiPageTemplate
restrictWidth={true}
template="centeredBody"
>
<EuiEmptyPrompt
actions={
Array [
"test",
]
}
body={
<p>
test
</p>
}
iconType="test"
/>
</EuiPageTemplate>
`;

View file

@ -0,0 +1,9 @@
/*
* 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 { KibanaPageTemplate, KibanaPageTemplateProps } from './page_template';

View file

@ -0,0 +1,69 @@
/*
* 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 React from 'react';
import { shallow } from 'enzyme';
import { KibanaPageTemplate } from './page_template';
import { EuiEmptyPrompt } from '@elastic/eui';
describe('KibanaPageTemplate', () => {
test('render default empty prompt', () => {
const component = shallow(
<KibanaPageTemplate
isEmptyState={true}
pageHeader={{
iconType: 'test',
title: 'test',
description: 'test',
rightSideItems: ['test'],
}}
/>
);
expect(component).toMatchSnapshot();
});
test('render custom empty prompt only', () => {
const component = shallow(
<KibanaPageTemplate isEmptyState={true}>
<EuiEmptyPrompt title={<h1>custom test</h1>} />
</KibanaPageTemplate>
);
expect(component).toMatchSnapshot();
});
test('render custom empty prompt with page header', () => {
const component = shallow(
<KibanaPageTemplate
isEmptyState={true}
pageHeader={{
iconType: 'test',
title: 'test',
description: 'test',
rightSideItems: ['test'],
}}
>
<EuiEmptyPrompt title={<h1>custom test</h1>} />
</KibanaPageTemplate>
);
expect(component).toMatchSnapshot();
});
test('render basic template', () => {
const component = shallow(
<KibanaPageTemplate
pageHeader={{
iconType: 'test',
title: 'test',
description: 'test',
rightSideItems: ['test'],
}}
/>
);
expect(component).toMatchSnapshot();
});
});

View file

@ -0,0 +1,73 @@
/*
* 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 { EuiEmptyPrompt, EuiPageTemplate, EuiPageTemplateProps } from '@elastic/eui';
import React, { FunctionComponent } from 'react';
export type KibanaPageTemplateProps = EuiPageTemplateProps & {
/**
* Changes the template type depending on other props provided.
* With `pageHeader` only: Uses `centeredBody` and fills an EuiEmptyPrompt with `pageHeader` info.
* With `children` only: Uses `centeredBody`
* With `pageHeader` and `children`: Uses `centeredContent`
*/
isEmptyState?: boolean;
};
export const KibanaPageTemplate: FunctionComponent<KibanaPageTemplateProps> = ({
template,
pageHeader,
children,
isEmptyState,
restrictWidth = true,
bottomBar,
bottomBarProps,
...rest
}) => {
// Needed for differentiating between union types
let localBottomBarProps = {};
if (template === 'default') {
localBottomBarProps = {
bottomBar,
bottomBarProps,
};
}
/**
* An easy way to create the right content for empty pages
*/
if (isEmptyState && pageHeader && !children) {
template = template ?? 'centeredBody';
const { iconType, pageTitle, description, rightSideItems } = pageHeader;
pageHeader = undefined;
children = (
<EuiEmptyPrompt
iconType={iconType}
title={pageTitle ? <h1>{pageTitle}</h1> : undefined}
body={description ? <p>{description}</p> : undefined}
actions={rightSideItems}
/>
);
} else if (isEmptyState && pageHeader && children) {
template = template ?? 'centeredContent';
} else if (isEmptyState && !pageHeader) {
template = template ?? 'centeredBody';
}
return (
<EuiPageTemplate
template={template}
pageHeader={pageHeader}
restrictWidth={restrictWidth}
{...localBottomBarProps}
{...rest}
>
{children}
</EuiPageTemplate>
);
};

View file

@ -0,0 +1,117 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TableListView render custom empty prompt 1`] = `
<KibanaPageTemplate
data-test-subj="testLandingPage"
isEmptyState={true}
pageBodyProps={
Object {
"aria-labelledby": undefined,
}
}
>
<EuiEmptyPrompt />
</KibanaPageTemplate>
`;
exports[`TableListView render default empty prompt 1`] = `
<KibanaPageTemplate
data-test-subj="testLandingPage"
isEmptyState={true}
pageBodyProps={
Object {
"aria-labelledby": undefined,
}
}
>
<EuiEmptyPrompt
title={
<h1>
<FormattedMessage
defaultMessage="No {entityNamePlural} available."
id="kibana-react.tableListView.listing.noAvailableItemsMessage"
values={
Object {
"entityNamePlural": "tests",
}
}
/>
</h1>
}
/>
</KibanaPageTemplate>
`;
exports[`TableListView render list view 1`] = `
<KibanaPageTemplate
data-test-subj="testLandingPage"
pageBodyProps={
Object {
"aria-labelledby": undefined,
}
}
pageHeader={
Object {
"data-test-subj": "top-nav",
"pageTitle": <span>
test title
</span>,
"rightSideItems": Array [
undefined,
],
}
}
>
<EuiInMemoryTable
columns={Array []}
data-test-subj="itemsInMemTable"
itemId="id"
items={
Array [
Object {},
]
}
loading={false}
message={
<FormattedMessage
defaultMessage="No {entityNamePlural} matched your search."
id="kibana-react.tableListView.listing.noMatchedItemsMessage"
values={
Object {
"entityNamePlural": "tests",
}
}
/>
}
pagination={
Object {
"initialPageIndex": 0,
"initialPageSize": 5,
"pageSizeOptions": Array [
10,
20,
5,
50,
],
}
}
responsive={true}
rowHeader="name"
search={
Object {
"box": Object {
"data-test-subj": "tableListSearchBox",
"incremental": true,
},
"defaultQuery": "",
"filters": Array [],
"onChange": [Function],
"toolsLeft": undefined,
}
}
sorting={true}
tableCaption="test caption"
tableLayout="fixed"
/>
</KibanaPageTemplate>
`;

View file

@ -0,0 +1,68 @@
/*
* 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 { EuiEmptyPrompt } from '@elastic/eui';
import { shallowWithIntl } from '@kbn/test/jest';
import { ToastsStart } from 'kibana/public';
import React from 'react';
import { TableListView } from './table_list_view';
const requiredProps = {
entityName: 'test',
entityNamePlural: 'tests',
listingLimit: 5,
initialFilter: '',
initialPageSize: 5,
tableColumns: [],
tableListTitle: 'test title',
rowHeader: 'name',
tableCaption: 'test caption',
toastNotifications: {} as ToastsStart,
findItems: jest.fn(() => Promise.resolve({ total: 0, hits: [] })),
};
describe('TableListView', () => {
test('render default empty prompt', async () => {
const component = shallowWithIntl(<TableListView {...requiredProps} />);
// Using setState to check the final render while sidestepping the debounced promise management
component.setState({
hasInitialFetchReturned: true,
isFetchingItems: false,
});
expect(component).toMatchSnapshot();
});
test('render custom empty prompt', () => {
const component = shallowWithIntl(
<TableListView {...requiredProps} emptyPrompt={<EuiEmptyPrompt />} />
);
// Using setState to check the final render while sidestepping the debounced promise management
component.setState({
hasInitialFetchReturned: true,
isFetchingItems: false,
});
expect(component).toMatchSnapshot();
});
test('render list view', () => {
const component = shallowWithIntl(<TableListView {...requiredProps} />);
// Using setState to check the final render while sidestepping the debounced promise management
component.setState({
hasInitialFetchReturned: true,
isFetchingItems: false,
items: [{}],
});
expect(component).toMatchSnapshot();
});
});

View file

@ -6,29 +6,24 @@
* Side Public License, v 1.
*/
import React from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { debounce, keyBy, sortBy, uniq } from 'lodash';
import {
EuiTitle,
EuiInMemoryTable,
EuiPage,
EuiPageBody,
EuiPageContent,
EuiLink,
EuiFlexGroup,
EuiFlexItem,
EuiButton,
EuiSpacer,
EuiConfirmModal,
EuiCallOut,
EuiBasicTableColumn,
EuiButton,
EuiCallOut,
EuiConfirmModal,
EuiEmptyPrompt,
EuiInMemoryTable,
EuiLink,
EuiSpacer,
EuiTableActionsColumnType,
SearchFilterConfig,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { HttpFetchError, ToastsStart } from 'kibana/public';
import { debounce, keyBy, sortBy, uniq } from 'lodash';
import React from 'react';
import { KibanaPageTemplate } from '../page_template';
import { toMountPoint } from '../util';
interface Item {
@ -45,7 +40,10 @@ export interface TableListViewProps {
listingLimit: number;
initialFilter: string;
initialPageSize: number;
noItemsFragment?: JSX.Element;
/**
* Should be an EuiEmptyPrompt (but TS doesn't support this typing)
*/
emptyPrompt?: JSX.Element;
tableColumns: Array<EuiBasicTableColumn<any>>;
tableListTitle: string;
toastNotifications: ToastsStart;
@ -61,7 +59,7 @@ export interface TableListViewProps {
/**
* Describes the content of the table. If not specified, the caption will be "This table contains {itemCount} rows."
*/
tableCaption?: string;
tableCaption: string;
searchFilters?: SearchFilterConfig[];
}
@ -347,6 +345,28 @@ class TableListView extends React.Component<TableListViewProps, TableListViewSta
}
}
renderNoItemsMessage() {
if (this.props.emptyPrompt) {
return this.props.emptyPrompt;
} else {
return (
<EuiEmptyPrompt
title={
<h1>
{
<FormattedMessage
id="kibana-react.tableListView.listing.noAvailableItemsMessage"
defaultMessage="No {entityNamePlural} available."
values={{ entityNamePlural: this.props.entityNamePlural }}
/>
}
</h1>
}
/>
);
}
}
renderToolsLeft() {
const selection = this.state.selectedIds;
@ -458,83 +478,66 @@ class TableListView extends React.Component<TableListViewProps, TableListViewSta
);
}
renderListingOrEmptyState() {
if (this.props.noItemsFragment && !this.state.fetchError && this.hasNoItems()) {
return this.props.noItemsFragment;
}
return this.renderListing();
}
renderListing() {
let createButton;
renderCreateButton() {
if (this.props.createItem) {
createButton = (
<EuiFlexItem grow={false}>
<EuiButton
onClick={this.props.createItem}
data-test-subj="newItemButton"
iconType="plusInCircle"
fill
>
<FormattedMessage
id="kibana-react.tableListView.listing.createNewItemButtonLabel"
defaultMessage="Create {entityName}"
values={{ entityName: this.props.entityName }}
/>
</EuiButton>
</EuiFlexItem>
return (
<EuiButton
onClick={this.props.createItem}
data-test-subj="newItemButton"
iconType="plusInCircleFilled"
fill
>
<FormattedMessage
id="kibana-react.tableListView.listing.createNewItemButtonLabel"
defaultMessage="Create {entityName}"
values={{ entityName: this.props.entityName }}
/>
</EuiButton>
);
}
return (
<div>
{this.state.showDeleteModal && this.renderConfirmDeleteModal()}
<EuiFlexGroup justifyContent="spaceBetween" alignItems="flexEnd" data-test-subj="top-nav">
<EuiFlexItem grow={false}>
<EuiTitle size="l">
<h1 id={this.props.headingId}>{this.props.tableListTitle}</h1>
</EuiTitle>
</EuiFlexItem>
{createButton}
</EuiFlexGroup>
<EuiSpacer size="m" />
{this.props.children}
{this.renderListingLimitWarning()}
{this.renderFetchError()}
{this.renderTable()}
</div>
);
}
renderPageContent() {
if (!this.state.hasInitialFetchReturned) {
return;
}
return (
<EuiPageContent horizontalPosition="center">
{this.renderListingOrEmptyState()}
</EuiPageContent>
);
}
render() {
return (
<EuiPage
data-test-subj={this.props.entityName + 'LandingPage'}
className="itemListing__page"
restrictWidth
>
<EuiPageBody
aria-labelledby={this.state.hasInitialFetchReturned ? this.props.headingId : undefined}
const pageDTS = `${this.props.entityName}LandingPage`;
if (!this.state.hasInitialFetchReturned) {
return <></>;
}
if (!this.state.fetchError && this.hasNoItems()) {
return (
<KibanaPageTemplate
data-test-subj={pageDTS}
pageBodyProps={{
'aria-labelledby': this.state.hasInitialFetchReturned
? this.props.headingId
: undefined,
}}
isEmptyState={true}
>
{this.renderPageContent()}
</EuiPageBody>
</EuiPage>
{this.renderNoItemsMessage()}
</KibanaPageTemplate>
);
}
return (
<KibanaPageTemplate
data-test-subj={pageDTS}
pageHeader={{
pageTitle: <span id={this.props.headingId}>{this.props.tableListTitle}</span>,
rightSideItems: [this.renderCreateButton()],
'data-test-subj': 'top-nav',
}}
pageBodyProps={{
'aria-labelledby': this.state.hasInitialFetchReturned ? this.props.headingId : undefined,
}}
>
{this.state.showDeleteModal && this.renderConfirmDeleteModal()}
{this.props.children}
{this.renderListingLimitWarning()}
{this.renderFetchError()}
{this.renderTable()}
</KibanaPageTemplate>
);
}
}

View file

@ -196,7 +196,7 @@ export const VisualizeListing = () => {
initialPageSize={savedObjectsPublic.settings.getPerPage()}
initialFilter={''}
rowHeader="title"
noItemsFragment={noItemsFragment}
emptyPrompt={noItemsFragment}
entityName={i18n.translate('visualize.listing.table.entityName', {
defaultMessage: 'visualization',
})}

View file

@ -45,7 +45,7 @@ export function Listing(props: ListingProps) {
listingLimit={props.listingLimit}
initialFilter={props.initialFilter}
initialPageSize={props.initialPageSize}
noItemsFragment={getNoItemsMessage(
emptyPrompt={getNoItemsMessage(
props.capabilities.save === false,
props.createItem,
props.coreStart.application
@ -72,77 +72,73 @@ function getNoItemsMessage(
) {
if (hideWriteControls) {
return (
<div>
<EuiEmptyPrompt
iconType="graphApp"
title={
<h1 id="graphListingHeading">
<FormattedMessage
id="xpack.graph.listing.noItemsMessage"
defaultMessage="Looks like you don't have any graphs."
/>
</h1>
}
/>
</div>
<EuiEmptyPrompt
iconType="graphApp"
title={
<h1 id="graphListingHeading">
<FormattedMessage
id="xpack.graph.listing.noItemsMessage"
defaultMessage="Looks like you don't have any graphs."
/>
</h1>
}
/>
);
}
const sampleDataUrl = `${application.getUrlForApp('home')}#/tutorial_directory/sampleData`;
return (
<div>
<EuiEmptyPrompt
iconType="graphApp"
title={
<h1 id="graphListingHeading">
<EuiEmptyPrompt
iconType="graphApp"
title={
<h1 id="graphListingHeading">
<FormattedMessage
id="xpack.graph.listing.createNewGraph.title"
defaultMessage="Create your first graph"
/>
</h1>
}
body={
<Fragment>
<p>
<FormattedMessage
id="xpack.graph.listing.createNewGraph.title"
defaultMessage="Create your first graph"
id="xpack.graph.listing.createNewGraph.combineDataViewFromKibanaAppDescription"
defaultMessage="Discover patterns and relationships in your Elasticsearch indices."
/>
</h1>
}
body={
<Fragment>
<p>
<FormattedMessage
id="xpack.graph.listing.createNewGraph.combineDataViewFromKibanaAppDescription"
defaultMessage="Discover patterns and relationships in your Elasticsearch indices."
/>
</p>
<p>
<FormattedMessage
id="xpack.graph.listing.createNewGraph.newToKibanaDescription"
defaultMessage="New to Kibana? Get started with {sampleDataInstallLink}."
values={{
sampleDataInstallLink: (
<EuiLink href={sampleDataUrl}>
<FormattedMessage
id="xpack.graph.listing.createNewGraph.sampleDataInstallLinkText"
defaultMessage="sample data"
/>
</EuiLink>
),
}}
/>
</p>
</Fragment>
}
actions={
<EuiButton
onClick={createItem}
fill
iconType="plusInCircle"
data-test-subj="graphCreateGraphPromptButton"
>
</p>
<p>
<FormattedMessage
id="xpack.graph.listing.createNewGraph.createButtonLabel"
defaultMessage="Create graph"
id="xpack.graph.listing.createNewGraph.newToKibanaDescription"
defaultMessage="New to Kibana? Get started with {sampleDataInstallLink}."
values={{
sampleDataInstallLink: (
<EuiLink href={sampleDataUrl}>
<FormattedMessage
id="xpack.graph.listing.createNewGraph.sampleDataInstallLinkText"
defaultMessage="sample data"
/>
</EuiLink>
),
}}
/>
</EuiButton>
}
/>
</div>
</p>
</Fragment>
}
actions={
<EuiButton
onClick={createItem}
fill
iconType="plusInCircle"
data-test-subj="graphCreateGraphPromptButton"
>
<FormattedMessage
id="xpack.graph.listing.createNewGraph.createButtonLabel"
defaultMessage="Create graph"
/>
</EuiButton>
}
/>
);
}

View file

@ -142,6 +142,9 @@ export function MapsListView() {
entityNamePlural={i18n.translate('xpack.maps.mapListing.entityNamePlural', {
defaultMessage: 'maps',
})}
tableCaption={i18n.translate('xpack.maps.mapListing.tableCaption', {
defaultMessage: 'Maps',
})}
tableListTitle={getAppTitle()}
toastNotifications={getToasts()}
searchFilters={searchFilters}