diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler.tsx index 585bee0008229..de6d247bd5bb6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler.tsx @@ -27,7 +27,6 @@ import { import { i18n } from '@kbn/i18n'; -import { CrawlerIndex } from '../../../../../../../common/types/indices'; import { HOURS_UNIT_LABEL, DAYS_UNIT_LABEL, @@ -36,23 +35,21 @@ import { } from '../../../../../shared/constants'; import { EnterpriseSearchCronEditor } from '../../../../../shared/cron_editor/enterprise_search_cron_editor'; import { docLinks } from '../../../../../shared/doc_links/doc_links'; -import { UpdateConnectorSchedulingApiLogic } from '../../../../api/connector/update_connector_scheduling_api_logic'; import { CrawlUnits } from '../../../../api/crawler/types'; import { isCrawlerIndex } from '../../../../utils/indices'; -import { IndexViewLogic } from '../../index_view_logic'; import { AutomaticCrawlSchedulerLogic } from './automatic_crawl_scheduler_logic'; export const AutomaticCrawlScheduler: React.FC = () => { - const { index } = useValues(IndexViewLogic); - const { makeRequest } = useActions(UpdateConnectorSchedulingApiLogic); + const { + setCrawlAutomatically, + setCrawlFrequency, + setCrawlUnit, + setUseConnectorSchedule, + submitConnectorSchedule, + } = useActions(AutomaticCrawlSchedulerLogic); - const scheduling = (index as CrawlerIndex)?.connector?.scheduling; - - const { setCrawlFrequency, setCrawlUnit, setUseConnectorSchedule, toggleCrawlAutomatically } = - useActions(AutomaticCrawlSchedulerLogic); - - const { crawlAutomatically, crawlFrequency, crawlUnit, useConnectorSchedule } = useValues( + const { index, crawlAutomatically, crawlFrequency, crawlUnit, useConnectorSchedule } = useValues( AutomaticCrawlSchedulerLogic ); @@ -84,7 +81,7 @@ export const AutomaticCrawlScheduler: React.FC = () => { defaultMessage: 'Enable recurring crawls with the following schedule', } )} - onChange={toggleCrawlAutomatically} + onChange={(e) => setCrawlAutomatically(e.target.checked)} compressed /> @@ -124,11 +121,11 @@ export const AutomaticCrawlScheduler: React.FC = () => { > - makeRequest({ - connectorId: index.connector.id, - scheduling: { ...newScheduling }, + submitConnectorSchedule({ + ...newScheduling, + enabled: true, }) } /> diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler_logic.test.ts deleted file mode 100644 index ac324eac83c37..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler_logic.test.ts +++ /dev/null @@ -1,266 +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 { - LogicMounter, - mockHttpValues, - mockFlashMessageHelpers, -} from '../../../../../__mocks__/kea_logic'; -import '../../_mocks_/index_name_logic.mock'; - -import { nextTick } from '@kbn/test-jest-helpers'; - -import { CrawlUnits } from '../../../../api/crawler/types'; - -import { AutomaticCrawlSchedulerLogic } from './automatic_crawl_scheduler_logic'; - -describe('AutomaticCrawlSchedulerLogic', () => { - const { mount } = new LogicMounter(AutomaticCrawlSchedulerLogic); - const { http } = mockHttpValues; - const { flashAPIErrors } = mockFlashMessageHelpers; - - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('has expected default values', () => { - mount(); - - expect(AutomaticCrawlSchedulerLogic.values).toEqual({ - crawlAutomatically: false, - crawlFrequency: 24, - crawlUnit: CrawlUnits.hours, - isSubmitting: false, - useConnectorSchedule: false, - }); - }); - - describe('actions', () => { - describe('clearCrawlSchedule', () => { - it('sets crawl schedule related values to their defaults', () => { - mount({ - crawlAutomatically: true, - crawlFrequency: 36, - crawlUnit: CrawlUnits.hours, - }); - - AutomaticCrawlSchedulerLogic.actions.clearCrawlSchedule(); - - expect(AutomaticCrawlSchedulerLogic.values).toMatchObject({ - crawlAutomatically: false, - crawlFrequency: 24, - crawlUnit: CrawlUnits.hours, - }); - }); - }); - - describe('toggleCrawlAutomatically', () => { - it('toggles the ability to crawl automatically', () => { - mount({ - crawlAutomatically: false, - }); - - AutomaticCrawlSchedulerLogic.actions.toggleCrawlAutomatically(); - - expect(AutomaticCrawlSchedulerLogic.values.crawlAutomatically).toEqual(true); - - AutomaticCrawlSchedulerLogic.actions.toggleCrawlAutomatically(); - - expect(AutomaticCrawlSchedulerLogic.values.crawlAutomatically).toEqual(false); - }); - }); - - describe('onDoneSubmitting', () => { - mount({ - isSubmitting: true, - }); - - AutomaticCrawlSchedulerLogic.actions.onDoneSubmitting(); - - expect(AutomaticCrawlSchedulerLogic.values.isSubmitting).toEqual(false); - }); - - describe('setCrawlFrequency', () => { - it("sets the crawl schedule's frequency", () => { - mount({ - crawlFrequency: 36, - }); - - AutomaticCrawlSchedulerLogic.actions.setCrawlFrequency(12); - - expect(AutomaticCrawlSchedulerLogic.values.crawlFrequency).toEqual(12); - }); - }); - - describe('setCrawlSchedule', () => { - it("sets the crawl schedule's frequency and unit, and enables crawling automatically", () => { - mount(); - - AutomaticCrawlSchedulerLogic.actions.setCrawlSchedule({ - frequency: 3, - unit: CrawlUnits.hours, - useConnectorSchedule: true, - }); - - expect(AutomaticCrawlSchedulerLogic.values).toMatchObject({ - crawlAutomatically: true, - crawlFrequency: 3, - crawlUnit: CrawlUnits.hours, - }); - }); - }); - - describe('setCrawlUnit', () => { - it("sets the crawl schedule's unit", () => { - mount({ - crawlUnit: CrawlUnits.months, - }); - - AutomaticCrawlSchedulerLogic.actions.setCrawlUnit(CrawlUnits.weeks); - - expect(AutomaticCrawlSchedulerLogic.values.crawlUnit).toEqual(CrawlUnits.weeks); - }); - }); - }); - - describe('listeners', () => { - describe('deleteCrawlSchedule', () => { - describe('error paths', () => { - it('resets the states of the crawl scheduler on a 404 response', async () => { - jest.spyOn(AutomaticCrawlSchedulerLogic.actions, 'onDoneSubmitting'); - http.delete.mockReturnValueOnce( - Promise.reject({ - response: { status: 404 }, - }) - ); - - AutomaticCrawlSchedulerLogic.actions.deleteCrawlSchedule(); - await nextTick(); - - expect(AutomaticCrawlSchedulerLogic.actions.onDoneSubmitting).toHaveBeenCalled(); - }); - - it('flashes an error on a non-404 response', async () => { - jest.spyOn(AutomaticCrawlSchedulerLogic.actions, 'onDoneSubmitting'); - http.delete.mockReturnValueOnce( - Promise.reject({ - response: { status: 500 }, - }) - ); - - AutomaticCrawlSchedulerLogic.actions.deleteCrawlSchedule(); - await nextTick(); - - expect(flashAPIErrors).toHaveBeenCalledWith({ - response: { status: 500 }, - }); - expect(AutomaticCrawlSchedulerLogic.actions.onDoneSubmitting).toHaveBeenCalled(); - }); - }); - }); - - describe('fetchCrawlSchedule', () => { - it('set the state of the crawl scheduler on success', async () => { - jest.spyOn(AutomaticCrawlSchedulerLogic.actions, 'setCrawlSchedule'); - http.get.mockReturnValueOnce( - Promise.resolve({ - unit: CrawlUnits.days, - frequency: '30', - }) - ); - - AutomaticCrawlSchedulerLogic.actions.fetchCrawlSchedule(); - await nextTick(); - - expect(AutomaticCrawlSchedulerLogic.actions.setCrawlSchedule).toHaveBeenCalledWith({ - unit: CrawlUnits.days, - frequency: '30', - }); - }); - - describe('error paths', () => { - it('flashes an error on a non-404 response', async () => { - http.get.mockReturnValueOnce( - Promise.reject({ - response: { status: 500 }, - }) - ); - - AutomaticCrawlSchedulerLogic.actions.fetchCrawlSchedule(); - await nextTick(); - - expect(flashAPIErrors).toHaveBeenCalledWith({ - response: { status: 500 }, - }); - }); - }); - }); - - describe('saveChanges', () => { - it('updates or creates a crawl schedule if the user has chosen to crawl automatically', () => { - jest.spyOn(AutomaticCrawlSchedulerLogic.actions, 'submitCrawlSchedule'); - mount({ - crawlAutomatically: true, - }); - - AutomaticCrawlSchedulerLogic.actions.saveChanges(); - - expect(AutomaticCrawlSchedulerLogic.actions.submitCrawlSchedule); - }); - - it('deletes the crawl schedule if the user has chosen to disable automatic crawling', () => { - jest.spyOn(AutomaticCrawlSchedulerLogic.actions, 'deleteCrawlSchedule'); - mount({ - crawlAutomatically: false, - }); - - AutomaticCrawlSchedulerLogic.actions.saveChanges(); - - expect(AutomaticCrawlSchedulerLogic.actions.deleteCrawlSchedule); - }); - }); - - describe('submitCrawlSchedule', () => { - it('sets the states of the crawl scheduler and closes the popover on success', async () => { - jest.spyOn(AutomaticCrawlSchedulerLogic.actions, 'setCrawlSchedule'); - jest.spyOn(AutomaticCrawlSchedulerLogic.actions, 'onDoneSubmitting'); - http.put.mockReturnValueOnce( - Promise.resolve({ - unit: CrawlUnits.days, - frequency: 30, - }) - ); - - AutomaticCrawlSchedulerLogic.actions.submitCrawlSchedule(); - await nextTick(); - - expect(AutomaticCrawlSchedulerLogic.actions.setCrawlSchedule).toHaveBeenCalledWith({ - unit: CrawlUnits.days, - frequency: 30, - }); - expect(AutomaticCrawlSchedulerLogic.actions.onDoneSubmitting).toHaveBeenCalled(); - }); - - it('flashes an error callout if there is an error', async () => { - jest.spyOn(AutomaticCrawlSchedulerLogic.actions, 'onDoneSubmitting'); - http.delete.mockReturnValueOnce( - Promise.reject({ - response: { status: 500 }, - }) - ); - - AutomaticCrawlSchedulerLogic.actions.deleteCrawlSchedule(); - await nextTick(); - - expect(flashAPIErrors).toHaveBeenCalledWith({ - response: { status: 500 }, - }); - expect(AutomaticCrawlSchedulerLogic.actions.onDoneSubmitting).toHaveBeenCalled(); - }); - }); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler_logic.ts index 04a11c6c182e6..e2533e4e8f658 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/automatic_crawl_scheduler/automatic_crawl_scheduler_logic.ts @@ -7,16 +7,27 @@ import { kea, MakeLogicType } from 'kea'; +import { ConnectorScheduling } from '../../../../../../../common/types/connectors'; + +import { CrawlerIndex } from '../../../../../../../common/types/indices'; +import { Actions } from '../../../../../shared/api_logic/create_api_logic'; + import { flashAPIErrors } from '../../../../../shared/flash_messages'; import { HttpLogic } from '../../../../../shared/http'; +import { + UpdateConnectorSchedulingApiLogic, + UpdateConnectorSchedulingArgs, +} from '../../../../api/connector/update_connector_scheduling_api_logic'; import { CrawlSchedule, CrawlScheduleFromServer, CrawlUnits } from '../../../../api/crawler/types'; import { crawlScheduleServerToClient } from '../../../../api/crawler/utils'; import { IndexNameLogic } from '../../index_name_logic'; +import { IndexViewLogic } from '../../index_view_logic'; export interface AutomaticCrawlSchedulerLogicValues { crawlAutomatically: boolean; crawlFrequency: CrawlSchedule['frequency']; crawlUnit: CrawlSchedule['unit']; + index: CrawlerIndex; isSubmitting: boolean; useConnectorSchedule: CrawlSchedule['useConnectorSchedule']; } @@ -33,7 +44,9 @@ export interface AutomaticCrawlSchedulerLogicActions { onDoneSubmitting(): void; enableCrawlAutomatically(): void; fetchCrawlSchedule(): void; + makeUpdateConnectorSchedulingRequest: Actions<{}, UpdateConnectorSchedulingArgs>['makeRequest']; saveChanges(): void; + setCrawlAutomatically(crawlAutomatically: boolean): { crawlAutomatically: boolean }; setCrawlFrequency(crawlFrequency: CrawlSchedule['frequency']): { crawlFrequency: CrawlSchedule['frequency']; }; @@ -42,14 +55,25 @@ export interface AutomaticCrawlSchedulerLogicActions { setUseConnectorSchedule(useConnectorSchedule: CrawlSchedule['useConnectorSchedule']): { useConnectorSchedule: CrawlSchedule['useConnectorSchedule']; }; + submitConnectorSchedule(scheduling: ConnectorScheduling): { scheduling: ConnectorScheduling }; submitCrawlSchedule(): void; - toggleCrawlAutomatically(): void; + updateConnectorSchedulingApiError: Actions<{}, UpdateConnectorSchedulingArgs>['apiError']; } export const AutomaticCrawlSchedulerLogic = kea< MakeLogicType >({ path: ['enterprise_search', 'crawler', 'automatic_crawl_scheduler_logic'], + connect: { + actions: [ + UpdateConnectorSchedulingApiLogic, + [ + 'makeRequest as makeUpdateConnectorSchedulingRequest', + 'apiError as updateConnectorSchedulingApiError', + ], + ], + values: [IndexViewLogic, ['index']], + }, actions: () => ({ clearCrawlSchedule: true, deleteCrawlSchedule: true, @@ -59,19 +83,20 @@ export const AutomaticCrawlSchedulerLogic = kea< fetchCrawlSchedule: true, saveChanges: true, setCrawlSchedule: (crawlSchedule: CrawlSchedule) => ({ crawlSchedule }), + submitConnectorSchedule: (scheduling) => ({ scheduling }), submitCrawlSchedule: true, + setCrawlAutomatically: (crawlAutomatically) => ({ crawlAutomatically }), setCrawlFrequency: (crawlFrequency: string) => ({ crawlFrequency }), setCrawlUnit: (crawlUnit: CrawlUnits) => ({ crawlUnit }), setUseConnectorSchedule: (useConnectorSchedule) => ({ useConnectorSchedule }), - toggleCrawlAutomatically: true, }), reducers: () => ({ crawlAutomatically: [ false, { clearCrawlSchedule: () => false, + setCrawlAutomatically: (_, { crawlAutomatically }) => crawlAutomatically, setCrawlSchedule: () => true, - toggleCrawlAutomatically: (crawlAutomatically) => !crawlAutomatically, }, ], crawlFrequency: [ @@ -80,6 +105,8 @@ export const AutomaticCrawlSchedulerLogic = kea< clearCrawlSchedule: () => DEFAULT_VALUES.crawlFrequency, setCrawlSchedule: (_, { crawlSchedule: { frequency } }) => frequency, setCrawlFrequency: (_, { crawlFrequency }) => crawlFrequency, + setUseConnectorSchedule: (crawlFrequency) => + crawlFrequency || DEFAULT_VALUES.crawlFrequency, }, ], crawlUnit: [ @@ -88,6 +115,7 @@ export const AutomaticCrawlSchedulerLogic = kea< clearCrawlSchedule: () => DEFAULT_VALUES.crawlUnit, setCrawlSchedule: (_, { crawlSchedule: { unit } }) => unit, setCrawlUnit: (_, { crawlUnit }) => crawlUnit, + setUseConnectorSchedule: (crawlUnit) => crawlUnit || DEFAULT_VALUES.crawlUnit, }, ], isSubmitting: [ @@ -101,6 +129,8 @@ export const AutomaticCrawlSchedulerLogic = kea< useConnectorSchedule: [ false, { + setCrawlAutomatically: (useConnectorSchedule, { crawlAutomatically }) => + crawlAutomatically || useConnectorSchedule, setCrawlSchedule: (_, { crawlSchedule: { useConnectorSchedule = false } }) => useConnectorSchedule, setUseConnectorSchedule: (_, { useConnectorSchedule }) => useConnectorSchedule, @@ -148,11 +178,21 @@ export const AutomaticCrawlSchedulerLogic = kea< } else { actions.deleteCrawlSchedule(); } + actions.submitConnectorSchedule({ + ...values.index.connector.scheduling, + enabled: values.crawlAutomatically && values.useConnectorSchedule, + }); }, - setCrawlUnit: actions.saveChanges, + setCrawlAutomatically: actions.saveChanges, setCrawlFrequency: actions.saveChanges, + setCrawlUnit: actions.saveChanges, setUseConnectorSchedule: actions.saveChanges, - toggleCrawlAutomatically: actions.saveChanges, + submitConnectorSchedule: ({ scheduling }) => { + actions.makeUpdateConnectorSchedulingRequest({ + connectorId: values.index.connector.id, + scheduling, + }); + }, submitCrawlSchedule: async () => { const { http } = HttpLogic.values; const { indexName } = IndexNameLogic.values; @@ -179,6 +219,7 @@ export const AutomaticCrawlSchedulerLogic = kea< actions.onDoneSubmitting(); } }, + updateConnectorSchedulingApiError: (e) => flashAPIErrors(e), }), events: ({ actions }) => ({ afterMount: () => {