diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/accordion_list.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/accordion_list.scss new file mode 100644 index 00000000000000..4772723f5d9277 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/accordion_list.scss @@ -0,0 +1,13 @@ +.appSearchAccordion--bordered { + border: $euiBorderThin; + border-radius: $euiBorderRadius; + padding: $euiSizeM; +} + +.appSearchAccordion--bordered, .appSearchAccordion { + .euiBasicTable { + .euiTableRow > .euiTableRowCell { + border-bottom: none; + } + } +} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/accordion_list.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/accordion_list.test.tsx new file mode 100644 index 00000000000000..2219a50a5e7f37 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/accordion_list.test.tsx @@ -0,0 +1,59 @@ +/* + * 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 '../../../../__mocks__/engine_logic.mock'; + +import React from 'react'; + +import { shallow, ShallowWrapper } from 'enzyme'; + +import { EuiAccordion, EuiIcon, EuiTitle, EuiInMemoryTable } from '@elastic/eui'; + +import { AccordionList } from './accordion_list'; + +const MOCK_PROPS = { + title: 'Test Items', + iconType: 'globe', + items: ['first item', 'second item'], +}; + +describe('AccordionList', () => { + let wrapper: ShallowWrapper; + + beforeAll(() => { + wrapper = shallow(); + }); + + it('renders as an accordion with the passed in title and icon', () => { + expect(wrapper.is(EuiAccordion)).toBe(true); + + const buttonContent = shallow(wrapper.prop('buttonContent')); + + expect(buttonContent.find(EuiIcon).prop('type')).toEqual('globe'); + expect(buttonContent.find(EuiTitle).children().text()).toEqual('Test Items'); + }); + + it('shows the item count', () => { + const extraActionContent = shallow(wrapper.prop('extraAction')); + + expect(extraActionContent.text()).toEqual('2'); + }); + + it('contains an table displaying the items', () => { + const table = wrapper.find(EuiInMemoryTable); + + expect(table.prop('items')).toEqual([{ item: 'first item' }, { item: 'second item' }]); + + expect(table.prop('columns')[0].render({ item: 'first item' })).toEqual('first item'); + }); + + it('is disabled when there are no items', () => { + const disabledWrapper = shallow(); + + expect(disabledWrapper.prop('arrowProps').isDisabled).toEqual(true); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/accordion_list.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/accordion_list.tsx new file mode 100644 index 00000000000000..ba537f712cf271 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/accordion_list.tsx @@ -0,0 +1,92 @@ +/* + * 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 { + EuiAccordion, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiInMemoryTable, + EuiNotificationBadge, + EuiSpacer, + EuiTitle, + IconType, + useGeneratedHtmlId, +} from '@elastic/eui'; + +import './accordion_list.scss'; + +interface Props { + hasBorder?: boolean; + iconType: IconType; + initialIsOpen?: boolean; + items: string[]; + rowCount?: number; + title: string; +} + +export const AccordionList: React.FC = ({ + hasBorder, + iconType, + initialIsOpen, + items, + rowCount = 10, + title, +}) => { + const accordionId = useGeneratedHtmlId({ + prefix: 'accordionList', + }); + + const showPagination = items.length > rowCount; + + return ( + + + + + + +

{title}

+
+
+ + } + id={accordionId} + extraAction={ + 0 ? 'accent' : 'subdued'} size="m"> + {items.length} + + } + > + ({ item }))} + columns={[ + { + render: ({ item }: { item: string }) => item, + }, + ]} + pagination={ + showPagination + ? { + hidePerPageOptions: true, + } + : false + } + /> + {!showPagination && } +
+ ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/crawl_details_flyout.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/crawl_details_flyout.tsx index 8ecd8613044580..9c3c1da534f729 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/crawl_details_flyout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/crawl_details_flyout.tsx @@ -35,7 +35,12 @@ export const CrawlDetailsFlyout: React.FC = () => { } return ( - +

@@ -70,7 +75,7 @@ export const CrawlDetailsFlyout: React.FC = () => { <> {selectedTab === 'preview' && } {selectedTab === 'json' && ( - + {JSON.stringify(crawlRequestFromServer, null, 2)} )} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/crawl_details_preview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/crawl_details_preview.test.tsx index d7c69e54451675..646c611901c7ff 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/crawl_details_preview.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/crawl_details_preview.test.tsx @@ -4,17 +4,77 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { setMockValues } from '../../../../../__mocks__/kea_logic'; import React from 'react'; -import { shallow } from 'enzyme'; +import { shallow, ShallowWrapper } from 'enzyme'; +import { CrawlDetailValues } from '../../crawl_detail_logic'; +import { CrawlerStatus, CrawlType } from '../../types'; + +import { AccordionList } from './accordion_list'; import { CrawlDetailsPreview } from './crawl_details_preview'; +const MOCK_VALUES: Partial = { + crawlRequest: { + id: '507f1f77bcf86cd799439011', + status: CrawlerStatus.Pending, + createdAt: 'Mon, 31 Aug 2020 17:00:00 +0000', + beganAt: null, + completedAt: null, + type: CrawlType.Full, + crawlConfig: { + domainAllowlist: ['https://www.elastic.co', 'https://www.swiftype.com'], + seedUrls: ['https://www.elastic.co/docs', 'https://www.swiftype.com/documentation'], + sitemapUrls: ['https://www.elastic.co/sitemap.xml', 'https://www.swiftype.com/sitemap.xml'], + }, + }, +}; + describe('CrawlDetailsPreview', () => { - it('is empty', () => { - const wrapper = shallow(); + it('is empty when a crawl request has not been loaded', () => { + setMockValues({ + crawlRequest: null, + }); + const wrapper = shallow(); expect(wrapper.isEmptyRender()).toBe(true); }); + + describe('when a crawl request has been loaded', () => { + let wrapper: ShallowWrapper; + + beforeAll(() => { + setMockValues(MOCK_VALUES); + wrapper = shallow(); + }); + + it('contains a list of domains', () => { + const domainList = wrapper.find(AccordionList).at(0); + + expect(domainList.prop('items')).toEqual([ + 'https://www.elastic.co', + 'https://www.swiftype.com', + ]); + }); + + it('contains a list of seed urls', () => { + const seedUrlList = wrapper.find(AccordionList).at(1); + + expect(seedUrlList.prop('items')).toEqual([ + 'https://www.elastic.co/docs', + 'https://www.swiftype.com/documentation', + ]); + }); + + it('contains a list of sitemap urls', () => { + const sitemapUrlList = wrapper.find(AccordionList).at(2); + + expect(sitemapUrlList.prop('items')).toEqual([ + 'https://www.elastic.co/sitemap.xml', + 'https://www.swiftype.com/sitemap.xml', + ]); + }); + }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/crawl_details_preview.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/crawl_details_preview.tsx index 7fa95d920c17bc..6f837d1db26e22 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/crawl_details_preview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_details_flyout/crawl_details_preview.tsx @@ -7,4 +7,62 @@ import React from 'react'; -export const CrawlDetailsPreview: React.FC = () => null; +import { useValues } from 'kea'; + +import { EuiSpacer } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { CrawlDetailLogic } from '../../crawl_detail_logic'; + +import { AccordionList } from './accordion_list'; + +export const CrawlDetailsPreview: React.FC = () => { + const { crawlRequest } = useValues(CrawlDetailLogic); + + if (crawlRequest === null) { + return null; + } + + return ( + <> + 0} + title={i18n.translate( + 'xpack.enterpriseSearch.appSearch.crawler.crawlDetailsPreview.domainsTitle', + { + defaultMessage: 'Domains', + } + )} + iconType="globe" + items={crawlRequest.crawlConfig.domainAllowlist} + /> + + 0} + title={i18n.translate( + 'xpack.enterpriseSearch.appSearch.crawler.crawlDetailsPreview.seedUrlsTitle', + { + defaultMessage: 'Seed URLs', + } + )} + iconType="crosshairs" + items={crawlRequest.crawlConfig.seedUrls} + /> + + 0} + title={i18n.translate( + 'xpack.enterpriseSearch.appSearch.crawler.crawlDetailsPreview.sitemapUrlsTitle', + { + defaultMessage: 'Sitemap URLs', + } + )} + iconType="visMapRegion" + items={crawlRequest.crawlConfig.sitemapUrls} + /> + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_event_type_badge.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_event_type_badge.test.tsx index b0ff75e73e86c6..fd1f03c586f120 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_event_type_badge.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_event_type_badge.test.tsx @@ -29,6 +29,8 @@ const MOCK_EVENT: CrawlEvent = { type: CrawlType.Full, crawlConfig: { domainAllowlist: ['https://www.elastic.co'], + seedUrls: [], + sitemapUrls: [], }, }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_requests_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_requests_table.test.tsx index bc5f8bf87e100c..e11661e4a942eb 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_requests_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/components/crawl_requests_table.test.tsx @@ -33,6 +33,8 @@ const values: { events: CrawlEvent[] } = { type: CrawlType.Full, crawlConfig: { domainAllowlist: ['https://www.elastic.co'], + seedUrls: [], + sitemapUrls: [], }, }, { @@ -45,6 +47,8 @@ const values: { events: CrawlEvent[] } = { type: CrawlType.Full, crawlConfig: { domainAllowlist: ['https://www.elastic.co'], + seedUrls: [], + sitemapUrls: [], }, }, ], diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawl_detail_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawl_detail_logic.test.ts index 57816db01b58cf..a7d795c93e0a7d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawl_detail_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawl_detail_logic.test.ts @@ -33,6 +33,8 @@ const crawlRequestResponse: CrawlRequestWithDetailsFromServer = { type: CrawlType.Full, crawl_config: { domain_allowlist: [], + seed_urls: [], + sitemap_urls: [], }, }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_logic.test.ts index f1e8dc6a6efa4f..5af9b1652c8895 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_logic.test.ts @@ -136,6 +136,8 @@ describe('CrawlerLogic', () => { type: CrawlType.Full, crawlConfig: { domainAllowlist: ['elastic.co'], + seedUrls: [], + sitemapUrls: [], }, }, ], diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_overview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_overview.test.tsx index 7c5510519d2028..0d2c2e60abfa92 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_overview.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/crawler_overview.test.tsx @@ -78,6 +78,8 @@ const events: CrawlEventFromServer[] = [ type: CrawlType.Full, crawl_config: { domain_allowlist: ['moviedatabase.com', 'swiftype.com'], + seed_urls: [], + sitemap_urls: [], }, }, { @@ -90,6 +92,8 @@ const events: CrawlEventFromServer[] = [ type: CrawlType.Partial, crawl_config: { domain_allowlist: ['swiftype.com'], + seed_urls: [], + sitemap_urls: [], }, }, ]; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/types.ts index 6cdccfdc786332..85ebb0032971d1 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/types.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/types.ts @@ -201,10 +201,14 @@ export interface CrawlRequest { export interface CrawlConfig { domainAllowlist: string[]; + seedUrls: string[]; + sitemapUrls: string[]; } export interface CrawlConfigFromServer { domain_allowlist: string[]; + seed_urls: string[]; + sitemap_urls: string[]; } export type CrawlRequestWithDetailsFromServer = CrawlRequestFromServer & { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/utils.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/utils.test.ts index c104312f19edc4..0df1f57eaefa08 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/utils.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/utils.test.ts @@ -139,6 +139,8 @@ describe('crawlRequestWithDetailsServerToClient', () => { type: CrawlType.Full, crawl_config: { domain_allowlist: [], + seed_urls: [], + sitemap_urls: [], }, }; @@ -151,6 +153,8 @@ describe('crawlRequestWithDetailsServerToClient', () => { type: CrawlType.Full, crawlConfig: { domainAllowlist: [], + seedUrls: [], + sitemapUrls: [], }, }; @@ -185,6 +189,8 @@ describe('crawlEventServerToClient', () => { type: CrawlType.Full, crawl_config: { domain_allowlist: [], + seed_urls: [], + sitemap_urls: [], }, stage: 'crawl', }; @@ -198,6 +204,8 @@ describe('crawlEventServerToClient', () => { type: CrawlType.Full, crawlConfig: { domainAllowlist: [], + seedUrls: [], + sitemapUrls: [], }, stage: 'crawl', }; @@ -264,6 +272,8 @@ describe('crawlerDataServerToClient', () => { type: CrawlType.Full, crawl_config: { domain_allowlist: ['https://www.elastic.co'], + seed_urls: [], + sitemap_urls: [], }, }, ], @@ -317,6 +327,8 @@ describe('crawlerDataServerToClient', () => { type: 'full', crawlConfig: { domainAllowlist: ['https://www.elastic.co'], + seedUrls: [], + sitemapUrls: [], }, }, ]); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/utils.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/utils.ts index 16e3dad5f46e92..d1203e19c02085 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/utils.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/crawler/utils.ts @@ -85,10 +85,16 @@ export function crawlRequestServerToClient(crawlRequest: CrawlRequestFromServer) } export function crawlConfigServerToClient(crawlConfig: CrawlConfigFromServer): CrawlConfig { - const { domain_allowlist: domainAllowlist } = crawlConfig; + const { + domain_allowlist: domainAllowlist, + seed_urls: seedUrls, + sitemap_urls: sitemapUrls, + } = crawlConfig; return { domainAllowlist, + seedUrls, + sitemapUrls, }; }