From d54f5667558c55d33e3529eed1ef30ee752fbf65 Mon Sep 17 00:00:00 2001 From: Davey Holler Date: Wed, 24 Feb 2021 15:15:01 -0800 Subject: [PATCH 01/12] WIP analytics polish --- .../analytics/components/analytics_cards.tsx | 4 +- .../components/analytics_section.tsx | 29 ++- .../analytics_tables/analytics_table.scss | 5 + .../analytics_tables/analytics_table.tsx | 3 + .../analytics_tables/inline_tags_list.tsx | 37 ++-- .../analytics_tables/shared_columns.tsx | 6 +- .../components/analytics/views/analytics.tsx | 170 +++++++++++------- .../components/data_panel/data_panel.tsx | 62 +++++++ .../components/engines/engines_overview.tsx | 3 +- .../app_search/icons/cursor_icon.tsx | 22 +++ .../engines/assets => icons}/engine_icon.tsx | 0 .../engines/assets => icons}/icons.test.tsx | 0 .../applications/app_search/icons/index.ts | 10 ++ .../assets => icons}/meta_engine_icon.tsx | 0 .../applications/shared/icons/cursor.svg | 3 + 15 files changed, 263 insertions(+), 91 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.scss create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/icons/cursor_icon.tsx rename x-pack/plugins/enterprise_search/public/applications/app_search/{components/engines/assets => icons}/engine_icon.tsx (100%) rename x-pack/plugins/enterprise_search/public/applications/app_search/{components/engines/assets => icons}/icons.test.tsx (100%) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/icons/index.ts rename x-pack/plugins/enterprise_search/public/applications/app_search/{components/engines/assets => icons}/meta_engine_icon.tsx (100%) create mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/icons/cursor.svg diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_cards.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_cards.tsx index b08e391f845e6..ba71549455409 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_cards.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_cards.tsx @@ -17,10 +17,10 @@ interface Props { }>; } export const AnalyticsCards: React.FC = ({ stats }) => ( - + {stats.map(({ text, stat, dataTestSubj }) => ( - + ; } -export const AnalyticsSection: React.FC = ({ title, subtitle, children }) => ( +export const AnalyticsSection: React.FC = ({ title, subtitle, iconType, children }) => (
- -

{title}

-
+ + {iconType ? ( + + + + ) : null} + + +

{title}

+
+
+
+

{subtitle}

diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.scss new file mode 100644 index 0000000000000..f87101faf2460 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.scss @@ -0,0 +1,5 @@ +.entSearch__table--noBackground { + .euiTable { + background-color: transparent; + } +} \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx index a580047f1f635..e057b9ba4b2df 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx @@ -19,6 +19,8 @@ import { ACTIONS_COLUMN, } from './shared_columns'; +import './analytics_table.scss'; + interface Props { items: Query[]; hasClicks?: boolean; @@ -53,6 +55,7 @@ export const AnalyticsTable: React.FC = ({ items, hasClicks }) => { return ( = ({ tags }) => { +export const InlineTagsList: React.FC = ({ displayCountOnly, tags }) => { if (!tags?.length) return null; const displayedTags = tags.slice(0, 2); - const tooltipTags = tags.slice(2); + const tooltipTags = tags.slice(displayCountOnly ? 0 : 2); + const moreTagsMessage = displayCountOnly + ? `${tooltipTags.length} tags` + : `and ${tooltipTags.length} more`; - return ( + const TagToolTip = () => ( + + + {i18n.translate('xpack.enterpriseSearch.appSearch.engine.analytics.table.moreTagsBadge', { + defaultMessage: moreTagsMessage, + values: { moreTagsCount: tooltipTags.length }, + })} + + + ); + + const TagList = () => ( {displayedTags.map((tag: string) => ( {tag} ))} - {tooltipTags.length > 0 && ( - - - {i18n.translate( - 'xpack.enterpriseSearch.appSearch.engine.analytics.table.moreTagsBadge', - { - defaultMessage: 'and {moreTagsCount} more', - values: { moreTagsCount: tooltipTags.length }, - } - )} - - - )} + {tooltipTags.length > 0 && } ); + + return displayCountOnly ? : ; }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx index 6c3d2539035ae..cf6a07a547a9e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/shared_columns.tsx @@ -76,10 +76,10 @@ export const ACTIONS_COLUMN = { }), description: i18n.translate( 'xpack.enterpriseSearch.appSearch.engine.analytics.table.editTooltip', - { defaultMessage: 'Edit query' } + { defaultMessage: 'Manage curation' } ), type: 'icon', - icon: 'pencil', + icon: 'package', onClick: async (item: Query | RecentQuery) => { const { http } = HttpLogic.values; const { navigateToUrl } = KibanaLogic.values; @@ -107,7 +107,7 @@ export const TAGS_COLUMN = { defaultMessage: 'Analytics tags', }), truncateText: true, - render: (tags: Query['tags']) => , + render: (tags: Query['tags']) => , }; export const COUNT_COLUMN_PROPS = { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx index a4f0bc356ac78..6530fc9a623c2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx @@ -9,10 +9,12 @@ import React from 'react'; import { useValues } from 'kea'; -import { EuiSpacer, EuiTitle } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { EuiButtonTo } from '../../../../shared/react_router_helpers'; +import { EuiButtonEmptyTo } from '../../../../shared/react_router_helpers'; +import { CursorIcon } from '../../../icons'; + import { ENGINE_ANALYTICS_TOP_QUERIES_PATH, ENGINE_ANALYTICS_TOP_QUERIES_NO_RESULTS_PATH, @@ -20,6 +22,7 @@ import { ENGINE_ANALYTICS_TOP_QUERIES_WITH_CLICKS_PATH, ENGINE_ANALYTICS_RECENT_QUERIES_PATH, } from '../../../routes'; +import { DataPanel } from '../../data_panel/data_panel'; import { generateEnginePath } from '../../engine'; import { AnalyticsLayout } from '../analytics_layout'; @@ -55,45 +58,54 @@ export const Analytics: React.FC = () => { return ( - + + + + + + {/* TODO: Update this panel to use the bordered version once available */} + + + + + - { 'Gain insight into the most frequent queries, and which queries returned no results.', } )} + iconType="search" > - -

{TOP_QUERIES}

-
- - - - -

{TOP_QUERIES_NO_RESULTS}

-
- - + + + } + > + + + + + + } + > + + + +
@@ -134,18 +160,36 @@ export const Analytics: React.FC = () => { defaultMessage: 'Discover which queries generated the most and least amount of clicks.', } )} + iconType={CursorIcon} > - -

{TOP_QUERIES_WITH_CLICKS}

-
- - - - -

{TOP_QUERIES_NO_CLICKS}

-
- - + + + + } + > + + + + + + } + > + + + + @@ -164,9 +208,9 @@ export const Analytics: React.FC = () => { }; export const ViewAllButton: React.FC<{ to: string }> = ({ to }) => ( - + {i18n.translate('xpack.enterpriseSearch.appSearch.engine.analytics.table.viewAllButtonLabel', { defaultMessage: 'View all', })} - + ); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx new file mode 100644 index 0000000000000..f2a10b0c29b60 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx @@ -0,0 +1,62 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiPanel, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; + +interface Props { + title: string; + subtitle?: string; + iconType?: string; + action?: React.ReactNode; + filled?: boolean; +} + +export const DataPanel: React.FC = ({ + title, + subtitle, + iconType, + action, + filled, + children, +}) => ( + + + + + {iconType ? ( + + + + ) : null} + + +

{title}

+
+
+
+
+ {action} +
+ {subtitle ? ( + +

{subtitle}

+
+ ) : null} + + {children} +
+); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx index a26fe87365536..076e8ba6da649 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx @@ -24,10 +24,9 @@ import { LicensingLogic } from '../../../shared/licensing'; import { EuiButtonTo } from '../../../shared/react_router_helpers'; import { convertMetaToPagination, handlePageChange } from '../../../shared/table_pagination'; import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; +import { EngineIcon, MetaEngineIcon } from '../../icons'; import { ENGINE_CREATION_PATH } from '../../routes'; -import { EngineIcon } from './assets/engine_icon'; -import { MetaEngineIcon } from './assets/meta_engine_icon'; import { EnginesOverviewHeader, LoadingState, EmptyState } from './components'; import { CREATE_AN_ENGINE_BUTTON_LABEL, ENGINES_TITLE, META_ENGINES_TITLE } from './constants'; import { EnginesLogic } from './engines_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/icons/cursor_icon.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/icons/cursor_icon.tsx new file mode 100644 index 0000000000000..991db0eb3ecee --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/icons/cursor_icon.tsx @@ -0,0 +1,22 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +export const CursorIcon: React.FC = ({ ...props }) => ( + +); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/engine_icon.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/icons/engine_icon.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/engine_icon.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/icons/engine_icon.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/icons.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/icons/icons.test.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/icons.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/icons/icons.test.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/icons/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/icons/index.ts new file mode 100644 index 0000000000000..1669fdab5ec4e --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/icons/index.ts @@ -0,0 +1,10 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { CursorIcon } from './cursor_icon'; +export { EngineIcon } from './engine_icon'; +export { MetaEngineIcon } from './meta_engine_icon'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/meta_engine_icon.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/icons/meta_engine_icon.tsx similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/assets/meta_engine_icon.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/icons/meta_engine_icon.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/icons/cursor.svg b/x-pack/plugins/enterprise_search/public/applications/shared/icons/cursor.svg new file mode 100644 index 0000000000000..e5d76a3c6e352 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/icons/cursor.svg @@ -0,0 +1,3 @@ + + + From ea28e0341cd80b7dada3d5e2a7f1826860edd01a Mon Sep 17 00:00:00 2001 From: Davey Holler Date: Thu, 25 Feb 2021 14:38:53 -0800 Subject: [PATCH 02/12] Working on tests. --- .../components/analytics_section.tsx | 3 +- .../analytics_tables/analytics_table.test.tsx | 8 +- .../analytics_tables/inline_tags_list.tsx | 3 +- .../query_clicks_table.test.tsx | 6 +- .../recent_queries_table.test.tsx | 8 +- .../components/data_panel/data_panel.test.tsx | 73 +++++++++++++++++++ .../components/data_panel/data_panel.tsx | 12 ++- 7 files changed, 96 insertions(+), 17 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.test.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.tsx index c1bfb69ea3dcc..640526c3ed952 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.tsx @@ -15,12 +15,13 @@ import { EuiSpacer, EuiText, EuiTitle, + IconType, } from '@elastic/eui'; interface Props { title: string; subtitle: string; - iconType?: React.ComponentProps; + iconType?: IconType; } export const AnalyticsSection: React.FC = ({ title, subtitle, iconType, children }) => (
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.test.tsx index 593f70cda404c..129bc0503afb2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.test.tsx @@ -26,7 +26,7 @@ describe('AnalyticsTable', () => { }, { key: 'another search', - tags: ['tagB'], + tags: ['tagB', 'tagC'], searches: { doc_count: 99 }, clicks: { doc_count: 9 }, }, @@ -48,9 +48,9 @@ describe('AnalyticsTable', () => { expect(tableContent).toContain('""'); expect(tableContent).toContain('Analytics tags'); - expect(tableContent).toContain('tagA'); - expect(tableContent).toContain('tagB'); - expect(wrapper.find(EuiBadge)).toHaveLength(4); + expect(tableContent).toContain('1 tag'); + expect(tableContent).toContain('2 tags'); + expect(wrapper.find(EuiBadge)).toHaveLength(3); expect(tableContent).toContain('Queries'); expect(tableContent).toContain('100'); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx index 8ad8af5c7fcf7..915003a91b880 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx @@ -21,8 +21,9 @@ export const InlineTagsList: React.FC = ({ displayCountOnly, tags }) => { const displayedTags = tags.slice(0, 2); const tooltipTags = tags.slice(displayCountOnly ? 0 : 2); + const tagsText = tags.length === 1 ? 'tag' : 'tags'; const moreTagsMessage = displayCountOnly - ? `${tooltipTags.length} tags` + ? `${tooltipTags.length} ${tagsText}` : `and ${tooltipTags.length} more`; const TagToolTip = () => ( diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.test.tsx index cc8f13299c57f..e8adb5702a977 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.test.tsx @@ -31,7 +31,7 @@ describe('QueryClicksTable', () => { engine: 'another-engine', id: 'another-document', }, - tags: ['tagB'], + tags: ['tagB', 'tagC'], doc_count: 5, }, { @@ -59,8 +59,8 @@ describe('QueryClicksTable', () => { // deleted-document should not have a link expect(tableContent).toContain('Analytics tags'); - expect(tableContent).toContain('tagA'); - expect(tableContent).toContain('tagB'); + expect(tableContent).toContain('1 tag'); + expect(tableContent).toContain('2 tags'); expect(wrapper.find(EuiBadge)).toHaveLength(2); expect(tableContent).toContain('Clicks'); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.test.tsx index 0670624492db5..6b172e92de264 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.test.tsx @@ -27,7 +27,7 @@ describe('RecentQueriesTable', () => { { query_string: 'another search', timestamp: '1970-01-02T12:00:00Z', - tags: ['tagB'], + tags: ['tagB', 'tagC'], document_ids: ['documentC'], }, { @@ -53,9 +53,9 @@ describe('RecentQueriesTable', () => { expect(tableContent).toContain('Jan 1, 1970'); expect(tableContent).toContain('Analytics tags'); - expect(tableContent).toContain('tagA'); - expect(tableContent).toContain('tagB'); - expect(wrapper.find(EuiBadge)).toHaveLength(4); + expect(tableContent).toContain('1 tag'); + expect(tableContent).toContain('2 tags'); + expect(wrapper.find(EuiBadge)).toHaveLength(3); expect(tableContent).toContain('Results'); expect(tableContent).toContain('2'); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.test.tsx new file mode 100644 index 0000000000000..6489561f1946f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.test.tsx @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiButton } from '@elastic/eui'; + +import { DataPanel } from './data_panel'; + +describe('DataPanel', () => { + it('Renders without an icon or a subtitle', () => { + const wrapper = shallow(Look at this graph); + + expect(wrapper.find('[data-test-subj="dataPanelTitle"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="dataPanelIcon"]')).toHaveLength(0); + expect(wrapper.find('[data-test-subj="dataPanelSubtitle"]')).toHaveLength(0); + expect(wrapper.find('[data-test-subj="dataPanelAction"]')).toHaveLength(0); + }); + + it('Renders with an icon, without a subtitle', () => { + const wrapper = shallow( + + Look at this graph + + ); + + expect(wrapper.find('[data-test-subj="dataPanelTitle"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="dataPanelIcon"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="dataPanelSubtitle"]')).toHaveLength(0); + expect(wrapper.find('[data-test-subj="dataPanelAction"]')).toHaveLength(0); + }); + + it('Renders with an icon and a subtitle', () => { + const wrapper = shallow( + + ); + + expect(wrapper.find('[data-test-subj="dataPanelTitle"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="dataPanelSubtitle"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="dataPanelIcon"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="dataPanelAction"]')).toHaveLength(0); + }); + + it('Renders without an icon, with a subtitle', () => { + const wrapper = shallow( + + ); + expect(wrapper.find('[data-test-subj="dataPanelTitle"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="dataPanelIcon"]')).toHaveLength(0); + expect(wrapper.find('[data-test-subj="dataPanelSubtitle"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="dataPanelAction"]')).toHaveLength(0); + }); + + it('Renders with a button', () => { + const wrapper = shallow( + Book flight} /> + ); + expect(wrapper.find('[data-test-subj="dataPanelTitle"]')).toHaveLength(1); + expect(wrapper.find('[data-test-subj="dataPanelIcon"]')).toHaveLength(0); + expect(wrapper.find('[data-test-subj="dataPanelSubtitle"]')).toHaveLength(0); + expect(wrapper.find('[data-test-subj="dataPanelAction"]')).toHaveLength(1); + }); +}); \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx index f2a10b0c29b60..6fe3f95912515 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx @@ -39,20 +39,24 @@ export const DataPanel: React.FC = ({ {iconType ? ( - + ) : null} - +

{title}

- {action} + {action ? ( + + {action} + + ) : null} {subtitle ? ( - +

{subtitle}

) : null} From 00cdaf5b01dc6ea40cf47ebfabacd65901f593c1 Mon Sep 17 00:00:00 2001 From: Davey Holler Date: Thu, 25 Feb 2021 14:57:53 -0800 Subject: [PATCH 03/12] Finishing up tests. --- .../analytics_tables/inline_tags_list.test.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.test.tsx index 9204fa6e75fa7..0fea002919711 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow, mount } from 'enzyme'; import { EuiBadge, EuiToolTip } from '@elastic/eui'; @@ -15,14 +15,14 @@ import { InlineTagsList } from './inline_tags_list'; describe('InlineTagsList', () => { it('renders', () => { - const wrapper = shallow(); + const wrapper = mount(); expect(wrapper.find(EuiBadge)).toHaveLength(1); expect(wrapper.find(EuiBadge).prop('children')).toEqual('test'); }); it('renders >2 badges in a tooltip list', () => { - const wrapper = shallow(); + const wrapper = mount(); expect(wrapper.find(EuiBadge)).toHaveLength(3); expect(wrapper.find(EuiToolTip)).toHaveLength(1); @@ -33,6 +33,15 @@ describe('InlineTagsList', () => { expect(wrapper.find(EuiToolTip).prop('content')).toEqual('3, 4, 5'); }); + it('renders a count and all tags in a tooltip', () => { + const wrapper = mount(); + + expect(wrapper.find(EuiToolTip)).toHaveLength(1); + expect(wrapper.find(EuiBadge)).toHaveLength(1); + expect(wrapper.find(EuiBadge).at(0).prop('children')).toEqual('3 tags'); + expect(wrapper.find(EuiToolTip).prop('content')).toEqual('1, 2, 3'); + }); + it('does not render with no tags', () => { const wrapper = shallow(); From 9ae5a3d05def92aa246697449c8d62ce39a329eb Mon Sep 17 00:00:00 2001 From: Davey Holler Date: Thu, 25 Feb 2021 15:30:05 -0800 Subject: [PATCH 04/12] Updating the engine overview page. --- .../components/total_charts.test.tsx | 17 ++- .../components/total_charts.tsx | 110 +++++++----------- .../engine_overview_metrics.tsx | 13 ++- 3 files changed, 62 insertions(+), 78 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx index a2f35b4709939..7f4fe471d5817 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx @@ -10,16 +10,15 @@ import '../../../__mocks__/engine_logic.mock'; import React from 'react'; -import { shallow, ShallowWrapper } from 'enzyme'; +import { mount, ReactWrapper } from 'enzyme'; -import { EuiButtonTo } from '../../../../shared/react_router_helpers'; +import { EuiButtonEmptyTo } from '../../../../shared/react_router_helpers'; import { AnalyticsChart } from '../../analytics'; import { TotalCharts } from './total_charts'; describe('TotalCharts', () => { - let wrapper: ShallowWrapper; - + let wrapper: ReactWrapper, React.Component<{}, {}, any>>; beforeAll(() => { jest.clearAllMocks(); setMockValues({ @@ -27,22 +26,22 @@ describe('TotalCharts', () => { queriesPerDay: [0, 1, 2, 3, 5, 10, 50], operationsPerDay: [0, 0, 0, 0, 0, 0, 0], }); - wrapper = shallow(); + wrapper = mount(); }); it('renders the total queries chart', () => { const chart = wrapper.find('[data-test-subj="TotalQueriesChart"]'); - expect(chart.find('h2').text()).toEqual('Total queries'); - expect(chart.find(EuiButtonTo).prop('to')).toEqual('/engines/some-engine/analytics'); + expect(chart.find('h4').text()).toEqual('Total queries'); + expect(chart.find(EuiButtonEmptyTo).prop('to')).toEqual('/engines/some-engine/analytics'); expect(chart.find(AnalyticsChart)).toHaveLength(1); }); it('renders the total API operations chart', () => { const chart = wrapper.find('[data-test-subj="TotalApiOperationsChart"]'); - expect(chart.find('h2').text()).toEqual('Total API operations'); - expect(chart.find(EuiButtonTo).prop('to')).toEqual('/engines/some-engine/api-logs'); + expect(chart.find('h4').text()).toEqual('Total API operations'); + expect(chart.find(EuiButtonEmptyTo).prop('to')).toEqual('/engines/some-engine/api-logs'); expect(chart.find(AnalyticsChart)).toHaveLength(1); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx index 6bd973ae142a8..4f7094b6e6cc3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx @@ -9,21 +9,13 @@ import React from 'react'; import { useValues } from 'kea'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiPageContent, - EuiPageContentHeader, - EuiPageContentHeaderSection, - EuiPageContentBody, - EuiTitle, - EuiText, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { EuiButtonTo } from '../../../../shared/react_router_helpers'; +import { EuiButtonEmptyTo } from '../../../../shared/react_router_helpers'; import { ENGINE_ANALYTICS_PATH, ENGINE_API_LOGS_PATH } from '../../../routes'; import { AnalyticsChart, convertToChartData } from '../../analytics'; import { TOTAL_QUERIES, TOTAL_API_OPERATIONS } from '../../analytics/constants'; +import { DataPanel } from '../../data_panel/data_panel'; import { generateEnginePath } from '../../engine'; import { VIEW_ANALYTICS, VIEW_API_LOGS, LAST_7_DAYS } from '../constants'; @@ -35,62 +27,50 @@ export const TotalCharts: React.FC = () => { return ( - - - - -

{TOTAL_QUERIES}

-
- - {LAST_7_DAYS} - -
- - - {VIEW_ANALYTICS} - - -
- - - -
+ + {VIEW_ANALYTICS} + + } + > + +
- - - - -

{TOTAL_API_OPERATIONS}

-
- - {LAST_7_DAYS} - -
- - - {VIEW_API_LOGS} - - -
- - - -
+ + {VIEW_API_LOGS} + + } + > + +
); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.tsx index c33431354eafc..c60cf70f435c5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { useValues } from 'kea'; -import { EuiPageHeader, EuiTitle, EuiSpacer } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiPageHeader, EuiTitle, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FlashMessages } from '../../../shared/flash_messages'; @@ -37,9 +37,14 @@ export const EngineOverviewMetrics: React.FC = () => { ) : ( <> - - - + + + + + + + + From 32f2b068fbd907455038bc5cfd66d6b8e3694593 Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Tue, 2 Mar 2021 10:50:17 -0800 Subject: [PATCH 05/12] eslint fixes --- .../analytics/components/analytics_tables/analytics_table.scss | 2 +- .../app_search/components/data_panel/data_panel.test.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.scss index f87101faf2460..2a1288eb2c272 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.scss +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.scss @@ -2,4 +2,4 @@ .euiTable { background-color: transparent; } -} \ No newline at end of file +} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.test.tsx index 6489561f1946f..4592f6b7a311d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.test.tsx @@ -70,4 +70,4 @@ describe('DataPanel', () => { expect(wrapper.find('[data-test-subj="dataPanelSubtitle"]')).toHaveLength(0); expect(wrapper.find('[data-test-subj="dataPanelAction"]')).toHaveLength(1); }); -}); \ No newline at end of file +}); From b3a8b4f9eaf881965defb7bdcfea01443adc9562 Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Tue, 2 Mar 2021 10:51:19 -0800 Subject: [PATCH 06/12] i18n fixes --- .../analytics_tables/inline_tags_list.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx index 915003a91b880..142235d080d02 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx @@ -21,19 +21,19 @@ export const InlineTagsList: React.FC = ({ displayCountOnly, tags }) => { const displayedTags = tags.slice(0, 2); const tooltipTags = tags.slice(displayCountOnly ? 0 : 2); - const tagsText = tags.length === 1 ? 'tag' : 'tags'; const moreTagsMessage = displayCountOnly - ? `${tooltipTags.length} ${tagsText}` - : `and ${tooltipTags.length} more`; + ? i18n.translate('xpack.enterpriseSearch.appSearch.engine.analytics.table.tagsCountBadge', { + defaultMessage: '{tagsCount, plural, one {# tag} other {# tags}}', + values: { tagsCount: tags.length }, + }) + : i18n.translate('xpack.enterpriseSearch.appSearch.engine.analytics.table.moreTagsBadge', { + defaultMessage: 'and {moreTagsCount} more', + values: { moreTagsCount: tooltipTags.length }, + }); const TagToolTip = () => ( - - {i18n.translate('xpack.enterpriseSearch.appSearch.engine.analytics.table.moreTagsBadge', { - defaultMessage: moreTagsMessage, - values: { moreTagsCount: tooltipTags.length }, - })} - + {moreTagsMessage} ); From f9fa1ace4cda0fe3e5b669de883ecaadcbc6e3aa Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Tue, 2 Mar 2021 10:55:12 -0800 Subject: [PATCH 07/12] Icons feedback - Remove unused svg file - Add TODO comment - Add test coverage --- .../public/applications/app_search/icons/cursor_icon.tsx | 1 + .../public/applications/app_search/icons/icons.test.tsx | 8 +++++++- .../public/applications/shared/icons/cursor.svg | 3 --- 3 files changed, 8 insertions(+), 4 deletions(-) delete mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/icons/cursor.svg diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/icons/cursor_icon.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/icons/cursor_icon.tsx index 991db0eb3ecee..c874f135563ec 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/icons/cursor_icon.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/icons/cursor_icon.tsx @@ -7,6 +7,7 @@ import React from 'react'; +// TODO: This icon will be added to EUI soon - we should remove this custom SVG when once it's available in EUI export const CursorIcon: React.FC = ({ ...props }) => ( { +describe('shared App Search icons', () => { + it('renders a cursor icon', () => { + const wrapper = shallow(); + expect(wrapper.hasClass('euiIcon')).toBe(true); + }); + it('renders an engine icon', () => { const wrapper = shallow(); expect(wrapper.hasClass('engineIcon')).toBe(true); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/icons/cursor.svg b/x-pack/plugins/enterprise_search/public/applications/shared/icons/cursor.svg deleted file mode 100644 index e5d76a3c6e352..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/icons/cursor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - From 71a5d661148b1bb17ef57b1a48355606c6587c3a Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Tue, 2 Mar 2021 11:30:34 -0800 Subject: [PATCH 08/12] linting - unnecessary ternaries --- .../analytics/components/analytics_section.tsx | 4 ++-- .../app_search/components/data_panel/data_panel.tsx | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.tsx index 640526c3ed952..829afcf238d26 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.tsx @@ -27,11 +27,11 @@ export const AnalyticsSection: React.FC = ({ title, subtitle, iconType, c
- {iconType ? ( + {iconType && ( - ) : null} + )}

{title}

diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx index 6fe3f95912515..09cbf36434972 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx @@ -37,11 +37,11 @@ export const DataPanel: React.FC = ({ - {iconType ? ( + {iconType && ( - ) : null} + )}

{title}

@@ -49,17 +49,17 @@ export const DataPanel: React.FC = ({
- {action ? ( + {action && ( {action} - ) : null} + )}
- {subtitle ? ( + {subtitle && (

{subtitle}

- ) : null} + )} {children} From 9782526e982dd2ca32d8630efca8ef59d5d479fb Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Tue, 2 Mar 2021 12:38:22 -0800 Subject: [PATCH 09/12] EnginesOverview feedback TotalCharts - adjust chart height - tests: simplify / convert back to shallow RecentApiLogs - switch to DataPanel --- .../components/recent_api_logs.tsx | 40 ++++++------------- .../components/total_charts.test.tsx | 22 +++++----- .../components/total_charts.tsx | 2 + 3 files changed, 25 insertions(+), 39 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.tsx index 625ba2e905840..f807ee57a3ea2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.tsx @@ -7,40 +7,26 @@ import React from 'react'; -import { - EuiPageContent, - EuiPageContentHeader, - EuiPageContentHeaderSection, - EuiPageContentBody, - EuiTitle, -} from '@elastic/eui'; - -import { EuiButtonTo } from '../../../../shared/react_router_helpers'; +import { EuiButtonEmptyTo } from '../../../../shared/react_router_helpers'; import { ENGINE_API_LOGS_PATH } from '../../../routes'; import { RECENT_API_EVENTS } from '../../api_logs/constants'; +import { DataPanel } from '../../data_panel/data_panel'; import { generateEnginePath } from '../../engine'; import { VIEW_API_LOGS } from '../constants'; export const RecentApiLogs: React.FC = () => { return ( - - - - -

{RECENT_API_EVENTS}

-
-
- - - {VIEW_API_LOGS} - - -
- - TODO: API Logs Table - {/* */} - -
+ + {VIEW_API_LOGS} + + } + > + TODO: API Logs Table + {/* */} + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx index 7f4fe471d5817..ca1c4588eb534 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx @@ -10,15 +10,15 @@ import '../../../__mocks__/engine_logic.mock'; import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; +import { shallow, ShallowWrapper } from 'enzyme'; -import { EuiButtonEmptyTo } from '../../../../shared/react_router_helpers'; import { AnalyticsChart } from '../../analytics'; import { TotalCharts } from './total_charts'; describe('TotalCharts', () => { - let wrapper: ReactWrapper, React.Component<{}, {}, any>>; + let wrapper: ShallowWrapper; + beforeAll(() => { jest.clearAllMocks(); setMockValues({ @@ -26,22 +26,20 @@ describe('TotalCharts', () => { queriesPerDay: [0, 1, 2, 3, 5, 10, 50], operationsPerDay: [0, 0, 0, 0, 0, 0, 0], }); - wrapper = mount(); + wrapper = shallow(); }); it('renders the total queries chart', () => { - const chart = wrapper.find('[data-test-subj="TotalQueriesChart"]'); + const panel = wrapper.find('[data-test-subj="TotalQueriesChart"]'); - expect(chart.find('h4').text()).toEqual('Total queries'); - expect(chart.find(EuiButtonEmptyTo).prop('to')).toEqual('/engines/some-engine/analytics'); - expect(chart.find(AnalyticsChart)).toHaveLength(1); + expect(panel.prop('title')).toEqual('Total queries'); + expect(panel.find(AnalyticsChart)).toHaveLength(1); }); it('renders the total API operations chart', () => { - const chart = wrapper.find('[data-test-subj="TotalApiOperationsChart"]'); + const panel = wrapper.find('[data-test-subj="TotalApiOperationsChart"]'); - expect(chart.find('h4').text()).toEqual('Total API operations'); - expect(chart.find(EuiButtonEmptyTo).prop('to')).toEqual('/engines/some-engine/api-logs'); - expect(chart.find(AnalyticsChart)).toHaveLength(1); + expect(panel.prop('title')).toEqual('Total API operations'); + expect(panel.find(AnalyticsChart)).toHaveLength(1); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx index 4f7094b6e6cc3..ca101cfa8e247 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx @@ -48,6 +48,7 @@ export const TotalCharts: React.FC = () => { data: convertToChartData({ startDate, data: queriesPerDay }), }, ]} + height={240} />
@@ -69,6 +70,7 @@ export const TotalCharts: React.FC = () => { data: convertToChartData({ startDate, data: operationsPerDay }), }, ]} + height={240} />
From a98160c802d311dfe56a2c06243479e9ff54bfbf Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Tue, 2 Mar 2021 14:36:30 -0800 Subject: [PATCH 10/12] DataPanel feedback Component - move CSS table bg override out from being an AnalyticsTable concern to a DataPanel concern + bem naming, todo comment - add responsive={false} for better mobile UX - add className and data-test-subj prop passing - change title to pass full heading tags rather than a string - move subtitle below title for better screen reader order - add index.ts export Tests - capitalization for consistency, ordering/describe - remove data-test-subjs on source code (simpler to grab & inspect tags directly so we can more easily call .text() on passed content) - add new tests for props (fliled/className/data-test-subj) Usage - update other files using DataPanel to start passing heading tags + use index export - fix RecentApiLogs tests - change RecentQueries section to use a DataPanel (per Davey) --- .../analytics_tables/analytics_table.scss | 5 - .../analytics_tables/analytics_table.tsx | 3 - .../analytics/views/analytics.test.tsx | 2 +- .../components/analytics/views/analytics.tsx | 18 +-- .../components/data_panel/data_panel.scss | 8 ++ .../components/data_panel/data_panel.test.tsx | 114 +++++++++++------- .../components/data_panel/data_panel.tsx | 67 +++++----- .../app_search/components/data_panel/index.ts | 8 ++ .../components/recent_api_logs.test.tsx | 5 +- .../components/recent_api_logs.tsx | 4 +- .../components/total_charts.test.tsx | 4 +- .../components/total_charts.tsx | 6 +- 12 files changed, 139 insertions(+), 105 deletions(-) delete mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.scss create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.scss create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/index.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.scss deleted file mode 100644 index 2a1288eb2c272..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.scss +++ /dev/null @@ -1,5 +0,0 @@ -.entSearch__table--noBackground { - .euiTable { - background-color: transparent; - } -} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx index e057b9ba4b2df..a580047f1f635 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx @@ -19,8 +19,6 @@ import { ACTIONS_COLUMN, } from './shared_columns'; -import './analytics_table.scss'; - interface Props { items: Query[]; hasClicks?: boolean; @@ -55,7 +53,6 @@ export const AnalyticsTable: React.FC = ({ items, hasClicks }) => { return ( { expect(wrapper.find(AnalyticsCards)).toHaveLength(1); expect(wrapper.find(AnalyticsChart)).toHaveLength(1); - expect(wrapper.find(AnalyticsSection)).toHaveLength(3); + expect(wrapper.find(AnalyticsSection)).toHaveLength(2); expect(wrapper.find(AnalyticsTable)).toHaveLength(4); expect(wrapper.find(RecentQueriesTable)).toHaveLength(1); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx index 6530fc9a623c2..7e004df5e01d8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx @@ -22,7 +22,7 @@ import { ENGINE_ANALYTICS_TOP_QUERIES_WITH_CLICKS_PATH, ENGINE_ANALYTICS_RECENT_QUERIES_PATH, } from '../../../routes'; -import { DataPanel } from '../../data_panel/data_panel'; +import { DataPanel } from '../../data_panel'; import { generateEnginePath } from '../../engine'; import { AnalyticsLayout } from '../analytics_layout'; @@ -125,7 +125,7 @@ export const Analytics: React.FC = () => { {TOP_QUERIES}} filled action={} > @@ -134,7 +134,7 @@ export const Analytics: React.FC = () => { {TOP_QUERIES_NO_RESULTS}} filled action={ { {TOP_QUERIES_WITH_CLICKS}} filled action={ { {TOP_QUERIES_NO_CLICKS}} filled action={ { - {RECENT_QUERIES}} subtitle={i18n.translate( 'xpack.enterpriseSearch.appSearch.engine.analytics.recentQueriesDescription', { defaultMessage: 'A view into queries happening right now.' } )} + action={} > - - + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.scss new file mode 100644 index 0000000000000..f05e029ec8f8b --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.scss @@ -0,0 +1,8 @@ +.dataPanel { + // TODO: This CSS can be removed once EUI supports tables in `subdued` panels + &--filled { + .euiTable { + background-color: transparent; + } + } +} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.test.tsx index 4592f6b7a311d..e8f480bce9ee7 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.test.tsx @@ -9,65 +9,87 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { EuiButton } from '@elastic/eui'; +import { EuiIcon, EuiButton } from '@elastic/eui'; import { DataPanel } from './data_panel'; describe('DataPanel', () => { - it('Renders without an icon or a subtitle', () => { - const wrapper = shallow(Look at this graph); - - expect(wrapper.find('[data-test-subj="dataPanelTitle"]')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="dataPanelIcon"]')).toHaveLength(0); - expect(wrapper.find('[data-test-subj="dataPanelSubtitle"]')).toHaveLength(0); - expect(wrapper.find('[data-test-subj="dataPanelAction"]')).toHaveLength(0); - }); - - it('Renders with an icon, without a subtitle', () => { + it('renders with a title and children', () => { const wrapper = shallow( - - Look at this graph + Tabula Rasa}> +
Look at this graph
); - expect(wrapper.find('[data-test-subj="dataPanelTitle"]')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="dataPanelIcon"]')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="dataPanelSubtitle"]')).toHaveLength(0); - expect(wrapper.find('[data-test-subj="dataPanelAction"]')).toHaveLength(0); + expect(wrapper.find('[data-test-subj="title"]').text()).toEqual('Tabula Rasa'); + expect(wrapper.find('[data-test-subj="children"]').text()).toEqual('Look at this graph'); }); - it('Renders with an icon and a subtitle', () => { - const wrapper = shallow( - - ); + describe('components', () => { + it('renders with an icon', () => { + const wrapper = shallow(The Smoke Monster} iconType="eye" />); - expect(wrapper.find('[data-test-subj="dataPanelTitle"]')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="dataPanelSubtitle"]')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="dataPanelIcon"]')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="dataPanelAction"]')).toHaveLength(0); - }); + expect(wrapper.find(EuiIcon).prop('type')).toEqual('eye'); + }); - it('Renders without an icon, with a subtitle', () => { - const wrapper = shallow( - - ); - expect(wrapper.find('[data-test-subj="dataPanelTitle"]')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="dataPanelIcon"]')).toHaveLength(0); - expect(wrapper.find('[data-test-subj="dataPanelSubtitle"]')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="dataPanelAction"]')).toHaveLength(0); + it('renders with a subtitle', () => { + const wrapper = shallow( + Hugo Reyes} subtitle="Hurley was typically happy-go-lucky" /> + ); + + expect(wrapper.find('p').text()).toEqual('Hurley was typically happy-go-lucky'); + }); + + it('renders with an icon and a subtitle', () => { + const wrapper = shallow( + Flight 815} + iconType="package" + subtitle="Oceanic Airlines Flight 815 was a scheduled flight from Sydney, Australia to Los Angeles, California" + /> + ); + + expect(wrapper.find(EuiIcon).prop('type')).toEqual('package'); + expect(wrapper.find('p').text()).toEqual( + 'Oceanic Airlines Flight 815 was a scheduled flight from Sydney, Australia to Los Angeles, California' + ); + }); + + it('renders with a button', () => { + const wrapper = shallow( + Board Flight 815} + action={Book flight} + /> + ); + + expect(wrapper.find('[data-test-subj="action"]')).toHaveLength(1); + }); }); - it('Renders with a button', () => { - const wrapper = shallow( - Book flight} /> - ); - expect(wrapper.find('[data-test-subj="dataPanelTitle"]')).toHaveLength(1); - expect(wrapper.find('[data-test-subj="dataPanelIcon"]')).toHaveLength(0); - expect(wrapper.find('[data-test-subj="dataPanelSubtitle"]')).toHaveLength(0); - expect(wrapper.find('[data-test-subj="dataPanelAction"]')).toHaveLength(1); + describe('props', () => { + it('renders panel color based on filled flag', () => { + const wrapper = shallow(Test} />); + + expect(wrapper.prop('color')).toEqual('plain'); + expect(wrapper.prop('className')).toEqual('dataPanel'); + + wrapper.setProps({ filled: true }); + + expect(wrapper.prop('color')).toEqual('subdued'); + expect(wrapper.prop('className')).toEqual('dataPanel dataPanel--filled'); + }); + + it('passes class names', () => { + const wrapper = shallow(Test} className="testing" />); + + expect(wrapper.prop('className')).toEqual('dataPanel testing'); + }); + + it('passes arbitrary props', () => { + const wrapper = shallow(Test} data-test-subj="testing" />); + + expect(wrapper.find('[data-test-subj="testing"]')).toHaveLength(1); + }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx index 09cbf36434972..f6a474689b3af 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/data_panel.tsx @@ -7,6 +7,8 @@ import React from 'react'; +import classNames from 'classnames'; + import { EuiFlexGroup, EuiFlexItem, @@ -17,12 +19,15 @@ import { EuiTitle, } from '@elastic/eui'; +import './data_panel.scss'; + interface Props { - title: string; + title: React.ReactElement; // e.g., h2 tag subtitle?: string; iconType?: string; action?: React.ReactNode; filled?: boolean; + className?: string; } export const DataPanel: React.FC = ({ @@ -31,36 +36,38 @@ export const DataPanel: React.FC = ({ iconType, action, filled, + className, children, -}) => ( - - - - - {iconType && ( + ...props // e.g., data-test-subj +}) => { + const classes = classNames('dataPanel', className, { + 'dataPanel--filled': filled, + }); + + return ( + + + + + {iconType && ( + + + + )} - + {title} + {subtitle && ( + +

{subtitle}

+
+ )}
- )} - - -

{title}

-
-
-
-
- {action && ( - - {action} +
- )} -
- {subtitle && ( - -

{subtitle}

-
- )} - - {children} -
-); + {action && {action}} +
+ + {children} + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/index.ts new file mode 100644 index 0000000000000..092a86180e95d --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/data_panel/index.ts @@ -0,0 +1,8 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { DataPanel } from './data_panel'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.test.tsx index 42fa9777563db..ceda3ab92f589 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.test.tsx @@ -11,8 +11,6 @@ import React from 'react'; import { shallow, ShallowWrapper } from 'enzyme'; -import { EuiButtonTo } from '../../../../shared/react_router_helpers'; - import { RecentApiLogs } from './recent_api_logs'; describe('RecentApiLogs', () => { @@ -24,8 +22,7 @@ describe('RecentApiLogs', () => { }); it('renders the recent API logs table', () => { - expect(wrapper.find('h2').text()).toEqual('Recent API events'); - expect(wrapper.find(EuiButtonTo).prop('to')).toEqual('/engines/some-engine/api-logs'); + expect(wrapper.prop('title')).toEqual(

Recent API events

); // TODO: expect(wrapper.find(ApiLogsTable)).toHaveLength(1) }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.tsx index f807ee57a3ea2..1c7f43a592536 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/recent_api_logs.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { EuiButtonEmptyTo } from '../../../../shared/react_router_helpers'; import { ENGINE_API_LOGS_PATH } from '../../../routes'; import { RECENT_API_EVENTS } from '../../api_logs/constants'; -import { DataPanel } from '../../data_panel/data_panel'; +import { DataPanel } from '../../data_panel'; import { generateEnginePath } from '../../engine'; import { VIEW_API_LOGS } from '../constants'; @@ -18,7 +18,7 @@ import { VIEW_API_LOGS } from '../constants'; export const RecentApiLogs: React.FC = () => { return ( {RECENT_API_EVENTS}} action={ {VIEW_API_LOGS} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx index ca1c4588eb534..74ce770205ffe 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.test.tsx @@ -32,14 +32,14 @@ describe('TotalCharts', () => { it('renders the total queries chart', () => { const panel = wrapper.find('[data-test-subj="TotalQueriesChart"]'); - expect(panel.prop('title')).toEqual('Total queries'); + expect(panel.prop('title')).toEqual(

Total queries

); expect(panel.find(AnalyticsChart)).toHaveLength(1); }); it('renders the total API operations chart', () => { const panel = wrapper.find('[data-test-subj="TotalApiOperationsChart"]'); - expect(panel.prop('title')).toEqual('Total API operations'); + expect(panel.prop('title')).toEqual(

Total API operations

); expect(panel.find(AnalyticsChart)).toHaveLength(1); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx index ca101cfa8e247..77ba9ad0f9514 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/components/total_charts.tsx @@ -15,7 +15,7 @@ import { EuiButtonEmptyTo } from '../../../../shared/react_router_helpers'; import { ENGINE_ANALYTICS_PATH, ENGINE_API_LOGS_PATH } from '../../../routes'; import { AnalyticsChart, convertToChartData } from '../../analytics'; import { TOTAL_QUERIES, TOTAL_API_OPERATIONS } from '../../analytics/constants'; -import { DataPanel } from '../../data_panel/data_panel'; +import { DataPanel } from '../../data_panel'; import { generateEnginePath } from '../../engine'; import { VIEW_ANALYTICS, VIEW_API_LOGS, LAST_7_DAYS } from '../constants'; @@ -29,7 +29,7 @@ export const TotalCharts: React.FC = () => { {TOTAL_QUERIES}} subtitle={LAST_7_DAYS} action={ { {TOTAL_API_OPERATIONS}} subtitle={LAST_7_DAYS} action={ From 5e1fc00cbe99501d544745a78beb9b295d5b7074 Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Tue, 2 Mar 2021 17:46:50 -0800 Subject: [PATCH 11/12] Analytics tags - updates & responsive tweaks Tags - Rename to more general tags.tsx file - Add CSS limiting width of variable length tags - Break up into two separate components for easier readability & testing - Split up tags column constants so that the wider tables can use the old tags list component Tables - add isSmall flag to AnalyticsTable to use new tag count component - reduce actions column width - revert unnecessary table test changes Analytics - add custom CSS that switches tables/panels into full-width earlier --- .../analytics_tables/analytics_table.test.tsx | 18 ++++-- .../analytics_tables/analytics_table.tsx | 8 ++- .../analytics_tables/inline_tags_list.tsx | 52 --------------- .../query_clicks_table.test.tsx | 6 +- .../analytics_tables/query_clicks_table.tsx | 4 +- .../recent_queries_table.test.tsx | 8 +-- .../analytics_tables/recent_queries_table.tsx | 6 +- .../analytics_tables/shared_columns.tsx | 15 +++-- .../components/analytics_tables/tags.scss | 3 + ...nline_tags_list.test.tsx => tags.test.tsx} | 35 +++++++--- .../components/analytics_tables/tags.tsx | 64 +++++++++++++++++++ .../components/analytics/views/analytics.scss | 5 ++ .../components/analytics/views/analytics.tsx | 14 ++-- 13 files changed, 150 insertions(+), 88 deletions(-) delete mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/tags.scss rename x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/{inline_tags_list.test.tsx => tags.test.tsx} (54%) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/tags.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.scss diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.test.tsx index 129bc0503afb2..a0b0e4402c1e4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.test.tsx @@ -26,7 +26,7 @@ describe('AnalyticsTable', () => { }, { key: 'another search', - tags: ['tagB', 'tagC'], + tags: ['tagB'], searches: { doc_count: 99 }, clicks: { doc_count: 9 }, }, @@ -48,9 +48,9 @@ describe('AnalyticsTable', () => { expect(tableContent).toContain('""'); expect(tableContent).toContain('Analytics tags'); - expect(tableContent).toContain('1 tag'); - expect(tableContent).toContain('2 tags'); - expect(wrapper.find(EuiBadge)).toHaveLength(3); + expect(tableContent).toContain('tagA'); + expect(tableContent).toContain('tagB'); + expect(wrapper.find(EuiBadge)).toHaveLength(4); expect(tableContent).toContain('Queries'); expect(tableContent).toContain('100'); @@ -69,6 +69,16 @@ describe('AnalyticsTable', () => { expect(tableContent).toContain('0'); }); + it('renders tag counts instead of tag names if isSmall is passed', () => { + const wrapper = mountWithIntl(); + const tableContent = wrapper.find(EuiBasicTable).text(); + + expect(tableContent).toContain('Analytics tags'); + expect(tableContent).toContain('1 tag'); + expect(tableContent).toContain('2 tags'); + expect(wrapper.find(EuiBadge)).toHaveLength(3); + }); + describe('renders an action column', () => { const wrapper = mountWithIntl(); runActionColumnTests(wrapper); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx index a580047f1f635..737b87816ba46 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx @@ -14,7 +14,8 @@ import { Query } from '../../types'; import { TERM_COLUMN_PROPS, - TAGS_COLUMN, + TAGS_LIST_COLUMN, + TAGS_COUNT_COLUMN, COUNT_COLUMN_PROPS, ACTIONS_COLUMN, } from './shared_columns'; @@ -22,15 +23,18 @@ import { interface Props { items: Query[]; hasClicks?: boolean; + isSmall?: boolean; } type Columns = Array>; -export const AnalyticsTable: React.FC = ({ items, hasClicks }) => { +export const AnalyticsTable: React.FC = ({ items, hasClicks, isSmall }) => { const TERM_COLUMN = { field: 'key', ...TERM_COLUMN_PROPS, }; + const TAGS_COLUMN = isSmall ? TAGS_COUNT_COLUMN : TAGS_LIST_COLUMN; + const COUNT_COLUMNS = [ { field: 'searches.doc_count', diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx deleted file mode 100644 index 142235d080d02..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.tsx +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -import { EuiBadgeGroup, EuiBadge, EuiToolTip } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { Query } from '../../types'; - -interface Props { - tags?: Query['tags']; - displayCountOnly?: boolean; -} -export const InlineTagsList: React.FC = ({ displayCountOnly, tags }) => { - if (!tags?.length) return null; - - const displayedTags = tags.slice(0, 2); - const tooltipTags = tags.slice(displayCountOnly ? 0 : 2); - const moreTagsMessage = displayCountOnly - ? i18n.translate('xpack.enterpriseSearch.appSearch.engine.analytics.table.tagsCountBadge', { - defaultMessage: '{tagsCount, plural, one {# tag} other {# tags}}', - values: { tagsCount: tags.length }, - }) - : i18n.translate('xpack.enterpriseSearch.appSearch.engine.analytics.table.moreTagsBadge', { - defaultMessage: 'and {moreTagsCount} more', - values: { moreTagsCount: tooltipTags.length }, - }); - - const TagToolTip = () => ( - - {moreTagsMessage} - - ); - - const TagList = () => ( - - {displayedTags.map((tag: string) => ( - - {tag} - - ))} - {tooltipTags.length > 0 && } - - ); - - return displayCountOnly ? : ; -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.test.tsx index e8adb5702a977..cc8f13299c57f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.test.tsx @@ -31,7 +31,7 @@ describe('QueryClicksTable', () => { engine: 'another-engine', id: 'another-document', }, - tags: ['tagB', 'tagC'], + tags: ['tagB'], doc_count: 5, }, { @@ -59,8 +59,8 @@ describe('QueryClicksTable', () => { // deleted-document should not have a link expect(tableContent).toContain('Analytics tags'); - expect(tableContent).toContain('1 tag'); - expect(tableContent).toContain('2 tags'); + expect(tableContent).toContain('tagA'); + expect(tableContent).toContain('tagB'); expect(wrapper.find(EuiBadge)).toHaveLength(2); expect(tableContent).toContain('Clicks'); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.tsx index 4a93724ff5245..ba8fd1f17f816 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/query_clicks_table.tsx @@ -17,7 +17,7 @@ import { generateEnginePath } from '../../../engine'; import { QueryClick } from '../../types'; -import { FIRST_COLUMN_PROPS, TAGS_COLUMN, COUNT_COLUMN_PROPS } from './shared_columns'; +import { FIRST_COLUMN_PROPS, TAGS_LIST_COLUMN, COUNT_COLUMN_PROPS } from './shared_columns'; interface Props { items: QueryClick[]; @@ -55,7 +55,7 @@ export const QueryClicksTable: React.FC = ({ items }) => { return ( { { query_string: 'another search', timestamp: '1970-01-02T12:00:00Z', - tags: ['tagB', 'tagC'], + tags: ['tagB'], document_ids: ['documentC'], }, { @@ -53,9 +53,9 @@ describe('RecentQueriesTable', () => { expect(tableContent).toContain('Jan 1, 1970'); expect(tableContent).toContain('Analytics tags'); - expect(tableContent).toContain('1 tag'); - expect(tableContent).toContain('2 tags'); - expect(wrapper.find(EuiBadge)).toHaveLength(3); + expect(tableContent).toContain('tagA'); + expect(tableContent).toContain('tagB'); + expect(wrapper.find(EuiBadge)).toHaveLength(4); expect(tableContent).toContain('Results'); expect(tableContent).toContain('2'); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.tsx index 39b0e3e7165b1..55da07c6a79ee 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/recent_queries_table.tsx @@ -15,7 +15,7 @@ import { RecentQuery } from '../../types'; import { TERM_COLUMN_PROPS, - TAGS_COLUMN, + TAGS_LIST_COLUMN, COUNT_COLUMN_PROPS, ACTIONS_COLUMN, } from './shared_columns'; @@ -53,7 +53,9 @@ export const RecentQueriesTable: React.FC = ({ items }) => { return ( , +}; +export const TAGS_LIST_COLUMN = { + ...TAGS_COLUMN_PROPS, + render: (tags: Query['tags']) => , +}; +export const TAGS_COUNT_COLUMN = { + ...TAGS_COLUMN_PROPS, + render: (tags: Query['tags']) => , }; export const COUNT_COLUMN_PROPS = { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/tags.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/tags.scss new file mode 100644 index 0000000000000..4de1c5e6226fa --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/tags.scss @@ -0,0 +1,3 @@ +.tagsList .euiBadge { + max-width: $euiSize * 9; +} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/tags.test.tsx similarity index 54% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/tags.test.tsx index 0fea002919711..9a42da7461e0c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/inline_tags_list.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/tags.test.tsx @@ -7,22 +7,22 @@ import React from 'react'; -import { shallow, mount } from 'enzyme'; +import { shallow } from 'enzyme'; import { EuiBadge, EuiToolTip } from '@elastic/eui'; -import { InlineTagsList } from './inline_tags_list'; +import { TagsList, TagsCount } from './tags'; -describe('InlineTagsList', () => { +describe('TagsList', () => { it('renders', () => { - const wrapper = mount(); + const wrapper = shallow(); expect(wrapper.find(EuiBadge)).toHaveLength(1); expect(wrapper.find(EuiBadge).prop('children')).toEqual('test'); }); it('renders >2 badges in a tooltip list', () => { - const wrapper = mount(); + const wrapper = shallow(); expect(wrapper.find(EuiBadge)).toHaveLength(3); expect(wrapper.find(EuiToolTip)).toHaveLength(1); @@ -33,17 +33,34 @@ describe('InlineTagsList', () => { expect(wrapper.find(EuiToolTip).prop('content')).toEqual('3, 4, 5'); }); + it('does not render if missing tags', () => { + const wrapper = shallow(); + + expect(wrapper.isEmptyRender()).toBe(true); + }); +}); + +describe('TagsCount', () => { it('renders a count and all tags in a tooltip', () => { - const wrapper = mount(); + const wrapper = shallow(); expect(wrapper.find(EuiToolTip)).toHaveLength(1); expect(wrapper.find(EuiBadge)).toHaveLength(1); - expect(wrapper.find(EuiBadge).at(0).prop('children')).toEqual('3 tags'); + expect(wrapper.find(EuiBadge).prop('children')).toEqual('3 tags'); expect(wrapper.find(EuiToolTip).prop('content')).toEqual('1, 2, 3'); }); - it('does not render with no tags', () => { - const wrapper = shallow(); + it('handles pluralization correctly', () => { + const wrapper = shallow(); + + expect(wrapper.find(EuiToolTip)).toHaveLength(1); + expect(wrapper.find(EuiBadge)).toHaveLength(1); + expect(wrapper.find(EuiBadge).prop('children')).toEqual('1 tag'); + expect(wrapper.find(EuiToolTip).prop('content')).toEqual('1'); + }); + + it('does not render if missing tags', () => { + const wrapper = shallow(); expect(wrapper.isEmptyRender()).toBe(true); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/tags.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/tags.tsx new file mode 100644 index 0000000000000..241abfabfab4c --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/tags.tsx @@ -0,0 +1,64 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { EuiBadgeGroup, EuiBadge, EuiToolTip } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { Query } from '../../types'; + +import './tags.scss'; + +interface Props { + tags?: Query['tags']; +} + +export const TagsCount: React.FC = ({ tags }) => { + if (!tags?.length) return null; + + return ( + + + {i18n.translate('xpack.enterpriseSearch.appSearch.engine.analytics.table.tagsCountBadge', { + defaultMessage: '{tagsCount, plural, one {# tag} other {# tags}}', + values: { tagsCount: tags.length }, + })} + + + ); +}; + +export const TagsList: React.FC = ({ tags }) => { + if (!tags?.length) return null; + + const displayedTags = tags.slice(0, 2); + const tooltipTags = tags.slice(2); + + return ( + + {displayedTags.map((tag: string) => ( + + {tag} + + ))} + {tooltipTags.length > 0 && ( + + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.analytics.table.moreTagsBadge', + { + defaultMessage: 'and {moreTagsCount} more', + values: { moreTagsCount: tooltipTags.length }, + } + )} + + + )} + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.scss new file mode 100644 index 0000000000000..9b24a64390d4f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.scss @@ -0,0 +1,5 @@ +.analyticsOverviewTables { + @include euiBreakpoint('xs', 's', 'm', 'l') { + flex-direction: column; // Force full width on table panels earlier to ensure content stays legible + } +} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx index 7e004df5e01d8..82b0d9a318f1d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/views/analytics.tsx @@ -40,6 +40,8 @@ import { } from '../constants'; import { AnalyticsLogic, AnalyticsCards, AnalyticsChart, convertToChartData } from '../index'; +import './analytics.scss'; + export const Analytics: React.FC = () => { const { totalQueries, @@ -122,14 +124,14 @@ export const Analytics: React.FC = () => { )} iconType="search" > - + {TOP_QUERIES}} filled action={} > - + @@ -142,7 +144,7 @@ export const Analytics: React.FC = () => { /> } > - +
@@ -162,7 +164,7 @@ export const Analytics: React.FC = () => { )} iconType={CursorIcon} > - + {TOP_QUERIES_WITH_CLICKS}} @@ -173,7 +175,7 @@ export const Analytics: React.FC = () => { /> } > - + @@ -186,7 +188,7 @@ export const Analytics: React.FC = () => { /> } > - +
From 833476b9486adeaca0127bef883a66836e8cfd31 Mon Sep 17 00:00:00 2001 From: Constance Chen Date: Tue, 2 Mar 2021 17:52:01 -0800 Subject: [PATCH 12/12] AnalyticsSection fixes - fix responsive behavior with icon - add missing AnalyticsSection branch coverage --- .../analytics/components/analytics_section.test.tsx | 10 ++++++++++ .../analytics/components/analytics_section.tsx | 7 ++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.test.tsx index 56e30e6061173..b561a57120440 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.test.tsx @@ -9,6 +9,8 @@ import React from 'react'; import { shallow } from 'enzyme'; +import { EuiIcon } from '@elastic/eui'; + import { AnalyticsSection } from './'; describe('AnalyticsSection', () => { @@ -23,4 +25,12 @@ describe('AnalyticsSection', () => { expect(wrapper.find('p').text()).toEqual('Dolor sit amet.'); expect(wrapper.find('[data-test-subj="HelloWorld"]')).toHaveLength(1); }); + + it('renders an optional icon', () => { + const wrapper = shallow( + + ); + + expect(wrapper.find(EuiIcon).prop('type')).toEqual('eye'); + }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.tsx index 829afcf238d26..065eecf76ad43 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_section.tsx @@ -26,7 +26,12 @@ interface Props { export const AnalyticsSection: React.FC = ({ title, subtitle, iconType, children }) => (
- + {iconType && (