forked from elastic/kibana
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[App Search] Migrate Crawler Status Indicator, Crawler Status Banner,…
… and Crawl Request polling (elastic#107603) (elastic#107810) Co-authored-by: Byron Hulcher <[email protected]>
- Loading branch information
1 parent
c33dc8d
commit 3520109
Showing
14 changed files
with
1,045 additions
and
64 deletions.
There are no files selected for viewing
59 changes: 59 additions & 0 deletions
59
...blic/applications/app_search/components/crawler/components/crawler_status_banner.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 { setMockValues } from '../../../../__mocks__/kea_logic'; | ||
|
||
import React from 'react'; | ||
|
||
import { shallow } from 'enzyme'; | ||
|
||
import { EuiCallOut } from '@elastic/eui'; | ||
|
||
import { CrawlerStatus } from '../types'; | ||
|
||
import { CrawlerStatusBanner } from './crawler_status_banner'; | ||
|
||
describe('CrawlerStatusBanner', () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
[(CrawlerStatus.Starting, CrawlerStatus.Running, CrawlerStatus.Canceling)].forEach((status) => { | ||
describe(`when the status is ${status}`, () => { | ||
it('renders a callout', () => { | ||
setMockValues({ | ||
mostRecentCrawlRequestStatus: status, | ||
}); | ||
|
||
const wrapper = shallow(<CrawlerStatusBanner />); | ||
|
||
expect(wrapper.find(EuiCallOut)).toHaveLength(1); | ||
}); | ||
}); | ||
}); | ||
|
||
[ | ||
CrawlerStatus.Success, | ||
CrawlerStatus.Failed, | ||
CrawlerStatus.Canceled, | ||
CrawlerStatus.Pending, | ||
CrawlerStatus.Suspended, | ||
CrawlerStatus.Suspending, | ||
].forEach((status) => { | ||
describe(`when the status is ${status}`, () => { | ||
it('does not render a banner/callout', () => { | ||
setMockValues({ | ||
mostRecentCrawlRequestStatus: status, | ||
}); | ||
|
||
const wrapper = shallow(<CrawlerStatusBanner />); | ||
|
||
expect(wrapper.isEmptyRender()).toBe(true); | ||
}); | ||
}); | ||
}); | ||
}); |
40 changes: 40 additions & 0 deletions
40
...ch/public/applications/app_search/components/crawler/components/crawler_status_banner.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/* | ||
* 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 { useValues } from 'kea'; | ||
|
||
import { EuiCallOut } from '@elastic/eui'; | ||
|
||
import { i18n } from '@kbn/i18n'; | ||
|
||
import { CrawlerOverviewLogic } from '../crawler_overview_logic'; | ||
import { CrawlerStatus } from '../types'; | ||
|
||
export const CrawlerStatusBanner: React.FC = () => { | ||
const { mostRecentCrawlRequestStatus } = useValues(CrawlerOverviewLogic); | ||
if ( | ||
mostRecentCrawlRequestStatus === CrawlerStatus.Running || | ||
mostRecentCrawlRequestStatus === CrawlerStatus.Starting || | ||
mostRecentCrawlRequestStatus === CrawlerStatus.Canceling | ||
) { | ||
return ( | ||
<EuiCallOut | ||
iconType="iInCircle" | ||
title={i18n.translate( | ||
'xpack.enterpriseSearch.appSearch.crawler.crawlerStatusBanner.changesCalloutTitle', | ||
{ | ||
defaultMessage: | ||
"Changes you make now won't take effect until the start of your next crawl.", | ||
} | ||
)} | ||
/> | ||
); | ||
} | ||
return null; | ||
}; |
156 changes: 156 additions & 0 deletions
156
.../components/crawler/components/crawler_status_indicator/crawler_status_indicator.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
/* | ||
* 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 { setMockActions, setMockValues } from '../../../../../__mocks__/kea_logic'; | ||
|
||
import React from 'react'; | ||
|
||
import { shallow } from 'enzyme'; | ||
|
||
import { EuiButton } from '@elastic/eui'; | ||
|
||
import { CrawlerDomain, CrawlerStatus } from '../../types'; | ||
|
||
import { CrawlerStatusIndicator } from './crawler_status_indicator'; | ||
import { StopCrawlPopoverContextMenu } from './stop_crawl_popover_context_menu'; | ||
|
||
const MOCK_VALUES = { | ||
domains: [{}, {}] as CrawlerDomain[], | ||
mostRecentCrawlRequestStatus: CrawlerStatus.Success, | ||
}; | ||
|
||
const MOCK_ACTIONS = { | ||
startCrawl: jest.fn(), | ||
stopCrawl: jest.fn(), | ||
}; | ||
|
||
describe('CrawlerStatusIndicator', () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
setMockActions(MOCK_ACTIONS); | ||
}); | ||
|
||
describe('when status is not a valid status', () => { | ||
it('is disabled', () => { | ||
// this tests a codepath that should be impossible to reach, status should always be a CrawlerStatus | ||
// but we use a switch statement and need to test the default case for this to recieve 100% coverage | ||
setMockValues({ | ||
...MOCK_VALUES, | ||
mostRecentCrawlRequestStatus: null, | ||
}); | ||
|
||
const wrapper = shallow(<CrawlerStatusIndicator />); | ||
expect(wrapper.is(EuiButton)).toEqual(true); | ||
expect(wrapper.render().text()).toContain('Start a crawl'); | ||
expect(wrapper.prop('disabled')).toEqual(true); | ||
}); | ||
}); | ||
|
||
describe('when there are no domains', () => { | ||
it('is disabled', () => { | ||
setMockValues({ | ||
...MOCK_VALUES, | ||
domains: [], | ||
}); | ||
|
||
const wrapper = shallow(<CrawlerStatusIndicator />); | ||
expect(wrapper.is(EuiButton)).toEqual(true); | ||
expect(wrapper.render().text()).toContain('Start a crawl'); | ||
expect(wrapper.prop('disabled')).toEqual(true); | ||
}); | ||
}); | ||
|
||
describe('when the status is success', () => { | ||
it('renders an CrawlerStatusIndicator with a start crawl button', () => { | ||
setMockValues({ | ||
...MOCK_VALUES, | ||
mostRecentCrawlRequestStatus: CrawlerStatus.Success, | ||
}); | ||
|
||
const wrapper = shallow(<CrawlerStatusIndicator />); | ||
expect(wrapper.is(EuiButton)).toEqual(true); | ||
expect(wrapper.render().text()).toContain('Start a crawl'); | ||
expect(wrapper.prop('onClick')).toEqual(MOCK_ACTIONS.startCrawl); | ||
}); | ||
}); | ||
|
||
[CrawlerStatus.Failed, CrawlerStatus.Canceled].forEach((status) => { | ||
describe(`when the status is ready for retry: ${status}`, () => { | ||
it('renders an CrawlerStatusIndicator with a retry crawl button', () => { | ||
setMockValues({ | ||
...MOCK_VALUES, | ||
mostRecentCrawlRequestStatus: status, | ||
}); | ||
|
||
const wrapper = shallow(<CrawlerStatusIndicator />); | ||
expect(wrapper.is(EuiButton)).toEqual(true); | ||
expect(wrapper.render().text()).toContain('Retry crawl'); | ||
expect(wrapper.prop('onClick')).toEqual(MOCK_ACTIONS.startCrawl); | ||
}); | ||
}); | ||
}); | ||
|
||
[CrawlerStatus.Pending, CrawlerStatus.Suspended].forEach((status) => { | ||
describe(`when the status is ${status}`, () => { | ||
it('renders an CrawlerStatusIndicator with a pending indicator', () => { | ||
setMockValues({ | ||
...MOCK_VALUES, | ||
mostRecentCrawlRequestStatus: status, | ||
}); | ||
|
||
const wrapper = shallow(<CrawlerStatusIndicator />); | ||
expect(wrapper.is(EuiButton)).toEqual(true); | ||
expect(wrapper.render().text()).toContain('Pending...'); | ||
expect(wrapper.prop('disabled')).toEqual(true); | ||
expect(wrapper.prop('isLoading')).toEqual(true); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('when the status is Starting', () => { | ||
it('renders an appropriate CrawlerStatusIndicator', () => { | ||
setMockValues({ | ||
...MOCK_VALUES, | ||
mostRecentCrawlRequestStatus: CrawlerStatus.Starting, | ||
}); | ||
|
||
const wrapper = shallow(<CrawlerStatusIndicator />); | ||
expect(wrapper.is(EuiButton)).toEqual(true); | ||
expect(wrapper.render().text()).toContain('Starting...'); | ||
expect(wrapper.prop('isLoading')).toEqual(true); | ||
}); | ||
}); | ||
|
||
describe('when the status is Running', () => { | ||
it('renders a stop crawl popover menu', () => { | ||
setMockValues({ | ||
...MOCK_VALUES, | ||
mostRecentCrawlRequestStatus: CrawlerStatus.Running, | ||
}); | ||
|
||
const wrapper = shallow(<CrawlerStatusIndicator />); | ||
expect(wrapper.is(StopCrawlPopoverContextMenu)).toEqual(true); | ||
expect(wrapper.prop('stopCrawl')).toEqual(MOCK_ACTIONS.stopCrawl); | ||
}); | ||
}); | ||
|
||
[CrawlerStatus.Canceling, CrawlerStatus.Suspending].forEach((status) => { | ||
describe(`when the status is ${status}`, () => { | ||
it('renders an CrawlerStatusIndicator with a stopping indicator', () => { | ||
setMockValues({ | ||
...MOCK_VALUES, | ||
mostRecentCrawlRequestStatus: status, | ||
}); | ||
|
||
const wrapper = shallow(<CrawlerStatusIndicator />); | ||
expect(wrapper.is(EuiButton)).toEqual(true); | ||
expect(wrapper.render().text()).toContain('Stopping...'); | ||
expect(wrapper.prop('isLoading')).toEqual(true); | ||
}); | ||
}); | ||
}); | ||
}); |
106 changes: 106 additions & 0 deletions
106
...earch/components/crawler/components/crawler_status_indicator/crawler_status_indicator.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* | ||
* 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 { useActions, useValues } from 'kea'; | ||
|
||
import { EuiButton } from '@elastic/eui'; | ||
|
||
import { i18n } from '@kbn/i18n'; | ||
|
||
import { CrawlerOverviewLogic } from '../../crawler_overview_logic'; | ||
import { CrawlerStatus } from '../../types'; | ||
|
||
import { StopCrawlPopoverContextMenu } from './stop_crawl_popover_context_menu'; | ||
|
||
export const CrawlerStatusIndicator: React.FC = () => { | ||
const { domains, mostRecentCrawlRequestStatus } = useValues(CrawlerOverviewLogic); | ||
const { startCrawl, stopCrawl } = useActions(CrawlerOverviewLogic); | ||
|
||
const disabledButton = ( | ||
<EuiButton disabled> | ||
{i18n.translate( | ||
'xpack.enterpriseSearch.appSearch.crawler.crawlerStatusIndicator.startACrawlButtonLabel', | ||
{ | ||
defaultMessage: 'Start a crawl', | ||
} | ||
)} | ||
</EuiButton> | ||
); | ||
|
||
if (domains.length === 0) { | ||
return disabledButton; | ||
} | ||
|
||
switch (mostRecentCrawlRequestStatus) { | ||
case CrawlerStatus.Success: | ||
return ( | ||
<EuiButton fill onClick={startCrawl}> | ||
{i18n.translate( | ||
'xpack.enterpriseSearch.appSearch.crawler.crawlerStatusIndicator.startACrawlButtonLabel', | ||
{ | ||
defaultMessage: 'Start a crawl', | ||
} | ||
)} | ||
</EuiButton> | ||
); | ||
case CrawlerStatus.Failed: | ||
case CrawlerStatus.Canceled: | ||
return ( | ||
<EuiButton fill onClick={startCrawl}> | ||
{i18n.translate( | ||
'xpack.enterpriseSearch.appSearch.crawler.crawlerStatusIndicator.retryCrawlButtonLabel', | ||
{ | ||
defaultMessage: 'Retry crawl', | ||
} | ||
)} | ||
</EuiButton> | ||
); | ||
case CrawlerStatus.Pending: | ||
case CrawlerStatus.Suspended: | ||
return ( | ||
<EuiButton disabled isLoading> | ||
{i18n.translate( | ||
'xpack.enterpriseSearch.appSearch.crawler.crawlerStatusIndicator.pendingButtonLabel', | ||
{ | ||
defaultMessage: 'Pending...', | ||
} | ||
)} | ||
</EuiButton> | ||
); | ||
case CrawlerStatus.Starting: | ||
return ( | ||
<EuiButton isLoading> | ||
{i18n.translate( | ||
'xpack.enterpriseSearch.appSearch.crawler.crawlerStatusIndicator.startingButtonLabel', | ||
{ | ||
defaultMessage: 'Starting...', | ||
} | ||
)} | ||
</EuiButton> | ||
); | ||
case CrawlerStatus.Running: | ||
return <StopCrawlPopoverContextMenu stopCrawl={stopCrawl} />; | ||
case CrawlerStatus.Canceling: | ||
case CrawlerStatus.Suspending: | ||
return ( | ||
<EuiButton isLoading fill> | ||
{i18n.translate( | ||
'xpack.enterpriseSearch.appSearch.crawler.crawlerStatusIndicator.stoppingButtonLabel', | ||
{ | ||
defaultMessage: 'Stopping...', | ||
} | ||
)} | ||
</EuiButton> | ||
); | ||
default: | ||
// We should never get here, you would have to pass a CrawlerStatus option not covered | ||
// in the switch cases above | ||
return disabledButton; | ||
} | ||
}; |
Oops, something went wrong.