From 43588b546da92af11397f4cbf8a5cef13a253270 Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Tue, 5 Oct 2021 16:14:24 -0500 Subject: [PATCH] [Workplace Search] Migrate Objects and assets from Source settings to Synchronization section (#113982) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Rename method We have to set the source from the sync logic file and this naming makes more sense * Wire up Enable Synchronization toggle * Remove sync controls from source settings * Refactor to pass in contentSource as prop Because we have a child logic file, SynchronizationLogic, we have to pass the content source into it for reading its values from SourceLogic. There are 3 ways to do this: 1. Access the source directly at SourceLogic.values.contentSource - This how we normally do it. The problem here is that SourceLogic is not mounted when the default values are set in the reducers. This caused the UI to break and I could not find a way to safely mount SourceLogic before this logic file needed it. 2. Use the connect property and connect to Sourcelogic to access contentSource - This actually worked great but our test helper does not work well with it and after an hour or so trying to make it work, I punted and decided to go with #3 below. 3. Pass the contentSource as a prop - This works great and is easy to test. The only drawback is that all other components that use the SynchronizationLogic file have to also pass in the content source. This commit does just that. * Add logic for Objects and assets view * Add content to Objects and assets view * Add fallback for `nextStart` that is in the past This is slightly beyond the scope of this PR but trying to make the final PR more manageable. There is an edge case where a running job lists the nextStart in the past if it is is running. After a lengthy Slack convo, it was decided to catch these in the UI and show a fallback string instead of something like “Next run 3 hours ago” * reduce -> map From previous PR feedback * Fix casing on i18n ID --- .../components/source_settings.test.tsx | 78 --------- .../components/source_settings.tsx | 94 +---------- .../synchronization/blocked_window_item.tsx | 12 +- .../blocked_window_tab.test.tsx | 2 + .../synchronization/blocked_window_tab.tsx | 6 +- .../synchronization/frequency.test.tsx | 5 +- .../components/synchronization/frequency.tsx | 6 +- .../synchronization/frequency_item.test.tsx | 33 +++- .../synchronization/frequency_item.tsx | 7 +- .../objects_and_assets.test.tsx | 86 ++++++++++ .../synchronization/objects_and_assets.tsx | 88 +++++++++- .../synchronization/synchronization.test.tsx | 21 ++- .../synchronization/synchronization.tsx | 16 +- .../synchronization_logic.test.ts | 155 +++++++++++++++++- .../synchronization/synchronization_logic.ts | 113 ++++++++++++- .../views/content_sources/constants.ts | 58 +++++-- .../content_sources/source_logic.test.ts | 12 +- .../views/content_sources/source_logic.ts | 10 +- .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 20 files changed, 563 insertions(+), 243 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.test.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.test.tsx index 883c8631365eb..83cf21ce86233 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.test.tsx @@ -105,84 +105,6 @@ describe('SourceSettings', () => { ); }); - it('handles disabling synchronization', () => { - const wrapper = shallow(); - - const synchronizeSwitch = wrapper.find('[data-test-subj="SynchronizeToggle"]').first(); - const event = { target: { checked: false } }; - synchronizeSwitch.prop('onChange')?.(event as any); - - wrapper.find('[data-test-subj="SaveSyncControlsButton"]').simulate('click'); - - expect(updateContentSource).toHaveBeenCalledWith(fullContentSources[0].id, { - indexing: { - enabled: false, - features: { - content_extraction: { enabled: true }, - thumbnails: { enabled: true }, - }, - }, - }); - }); - - it('handles disabling thumbnails', () => { - const wrapper = shallow(); - - const thumbnailsSwitch = wrapper.find('[data-test-subj="ThumbnailsToggle"]').first(); - const event = { target: { checked: false } }; - thumbnailsSwitch.prop('onChange')?.(event as any); - - wrapper.find('[data-test-subj="SaveSyncControlsButton"]').simulate('click'); - - expect(updateContentSource).toHaveBeenCalledWith(fullContentSources[0].id, { - indexing: { - enabled: true, - features: { - content_extraction: { enabled: true }, - thumbnails: { enabled: false }, - }, - }, - }); - }); - - it('handles disabling content extraction', () => { - const wrapper = shallow(); - - const contentExtractionSwitch = wrapper - .find('[data-test-subj="ContentExtractionToggle"]') - .first(); - const event = { target: { checked: false } }; - contentExtractionSwitch.prop('onChange')?.(event as any); - - wrapper.find('[data-test-subj="SaveSyncControlsButton"]').simulate('click'); - - expect(updateContentSource).toHaveBeenCalledWith(fullContentSources[0].id, { - indexing: { - enabled: true, - features: { - content_extraction: { enabled: false }, - thumbnails: { enabled: true }, - }, - }, - }); - }); - - it('disables the thumbnails switch when globally disabled', () => { - setMockValues({ - ...mockValues, - contentSource: { - ...fullContentSources[0], - areThumbnailsConfigEnabled: false, - }, - }); - - const wrapper = shallow(); - - const synchronizeSwitch = wrapper.find('[data-test-subj="ThumbnailsToggle"]'); - - expect(synchronizeSwitch.prop('disabled')).toEqual(true); - }); - describe('DownloadDiagnosticsButton', () => { it('renders for org with correct href', () => { const wrapper = shallow(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.tsx index 585477fed058e..dd8625ebd7a7c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/source_settings.tsx @@ -17,8 +17,6 @@ import { EuiFlexGroup, EuiFlexItem, EuiFormRow, - EuiSpacer, - EuiSwitch, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; @@ -51,12 +49,6 @@ import { SYNC_DIAGNOSTICS_TITLE, SYNC_DIAGNOSTICS_DESCRIPTION, SYNC_DIAGNOSTICS_BUTTON, - SYNC_MANAGEMENT_TITLE, - SYNC_MANAGEMENT_DESCRIPTION, - SYNC_MANAGEMENT_SYNCHRONIZE_LABEL, - SYNC_MANAGEMENT_THUMBNAILS_LABEL, - SYNC_MANAGEMENT_THUMBNAILS_GLOBAL_CONFIG_LABEL, - SYNC_MANAGEMENT_CONTENT_EXTRACTION_LABEL, } from '../constants'; import { staticSourceData } from '../source_data'; import { SourceLogic } from '../source_logic'; @@ -70,22 +62,7 @@ export const SourceSettings: React.FC = () => { const { getSourceConfigData } = useActions(AddSourceLogic); const { - contentSource: { - name, - id, - serviceType, - custom: isCustom, - isIndexedSource, - areThumbnailsConfigEnabled, - isOauth1, - indexing: { - enabled, - features: { - contentExtraction: { enabled: contentExtractionEnabled }, - thumbnails: { enabled: thumbnailsEnabled }, - }, - }, - }, + contentSource: { name, id, serviceType, isOauth1 }, buttonLoading, } = useValues(SourceLogic); @@ -109,11 +86,6 @@ export const SourceSettings: React.FC = () => { const hideConfirm = () => setModalVisibility(false); const showConfig = isOrganization && !isEmpty(configuredFields); - const showSyncControls = isOrganization && isIndexedSource && !isCustom; - - const [synchronizeChecked, setSynchronize] = useState(enabled); - const [thumbnailsChecked, setThumbnails] = useState(thumbnailsEnabled); - const [contentExtractionChecked, setContentExtraction] = useState(contentExtractionEnabled); const { clientId, clientSecret, publicKey, consumerKey, baseUrl } = configuredFields || {}; @@ -130,18 +102,6 @@ export const SourceSettings: React.FC = () => { updateContentSource(id, { name: inputValue }); }; - const submitSyncControls = () => { - updateContentSource(id, { - indexing: { - enabled: synchronizeChecked, - features: { - content_extraction: { enabled: contentExtractionChecked }, - thumbnails: { enabled: thumbnailsChecked }, - }, - }, - }); - }; - const handleSourceRemoval = () => { /** * The modal was just hanging while the UI waited for the server to respond. @@ -221,58 +181,6 @@ export const SourceSettings: React.FC = () => { )} - {showSyncControls && ( - - - - setSynchronize(e.target.checked)} - label={SYNC_MANAGEMENT_SYNCHRONIZE_LABEL} - data-test-subj="SynchronizeToggle" - /> - - - - - - setThumbnails(e.target.checked)} - label={ - areThumbnailsConfigEnabled - ? SYNC_MANAGEMENT_THUMBNAILS_LABEL - : SYNC_MANAGEMENT_THUMBNAILS_GLOBAL_CONFIG_LABEL - } - disabled={!areThumbnailsConfigEnabled} - data-test-subj="ThumbnailsToggle" - /> - - - - - setContentExtraction(e.target.checked)} - label={SYNC_MANAGEMENT_CONTENT_EXTRACTION_LABEL} - data-test-subj="ContentExtractionToggle" - /> - - - - - - - {SAVE_CHANGES_BUTTON} - - - - - )} { - options.push({ - label: DAYS_OF_WEEK_LABELS[day.toUpperCase() as keyof typeof DAYS_OF_WEEK_LABELS], - value: day, - }); - return options; -}, [] as Array>); +const dayPickerOptions = DAYS_OF_WEEK_VALUES.map((day) => ({ + label: DAYS_OF_WEEK_LABELS[day.toUpperCase() as keyof typeof DAYS_OF_WEEK_LABELS], + value: day, +})); export const BlockedWindowItem: React.FC = ({ blockedWindow }) => { const handleSyncTypeChange = () => '#TODO'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.test.tsx index 0d5183b5e95e1..7cada1d39fb6e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.test.tsx @@ -7,6 +7,7 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockActions, setMockValues } from '../../../../../__mocks__/kea_logic'; +import { fullContentSources } from '../../../../__mocks__/content_sources.mock'; import { blockedWindow } from './__mocks__/syncronization.mock'; import React from 'react'; @@ -25,6 +26,7 @@ describe('BlockedWindows', () => { }; const mockValues = { blockedWindows: [blockedWindow], + contentSource: fullContentSources[0], }; beforeEach(() => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.tsx index 474bf4cab2a8e..f0227f76d4aa5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_tab.tsx @@ -13,13 +13,15 @@ import { EuiButton, EuiEmptyPrompt, EuiSpacer } from '@elastic/eui'; import { ADD_LABEL } from '../../../../constants'; import { BLOCKED_EMPTY_STATE_TITLE, BLOCKED_EMPTY_STATE_DESCRIPTION } from '../../constants'; +import { SourceLogic } from '../../source_logic'; import { BlockedWindowItem } from './blocked_window_item'; import { SynchronizationLogic } from './synchronization_logic'; export const BlockedWindows: React.FC = () => { - const { blockedWindows } = useValues(SynchronizationLogic); - const { addBlockedWindow } = useActions(SynchronizationLogic); + const { contentSource } = useValues(SourceLogic); + const { blockedWindows } = useValues(SynchronizationLogic({ contentSource })); + const { addBlockedWindow } = useActions(SynchronizationLogic({ contentSource })); const hasBlockedWindows = blockedWindows.length > 0; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.test.tsx index 08de4b41758a2..283c9a9cebbbd 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.test.tsx @@ -7,6 +7,7 @@ import '../../../../../__mocks__/shallow_useeffect.mock'; import { setMockActions, setMockValues } from '../../../../../__mocks__/kea_logic'; +import { fullContentSources } from '../../../../__mocks__/content_sources.mock'; import React from 'react'; @@ -23,7 +24,9 @@ describe('Frequency', () => { const mockActions = { handleSelectedTabChanged, }; - const mockValues = {}; + const mockValues = { + contentSource: fullContentSources[0], + }; beforeEach(() => { setMockActions(mockActions); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.tsx index fb19c84ecfdd1..3ca34f4960474 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency.tsx @@ -7,7 +7,7 @@ import React from 'react'; -import { useActions } from 'kea'; +import { useActions, useValues } from 'kea'; import { EuiButton, @@ -31,6 +31,7 @@ import { DIFFERENT_SYNC_TYPES_LINK_LABEL, SYNC_BEST_PRACTICES_LINK_LABEL, } from '../../constants'; +import { SourceLogic } from '../../source_logic'; import { SourceLayout } from '../source_layout'; import { BlockedWindows } from './blocked_window_tab'; @@ -42,7 +43,8 @@ interface FrequencyProps { } export const Frequency: React.FC = ({ tabId }) => { - const { handleSelectedTabChanged } = useActions(SynchronizationLogic); + const { contentSource } = useValues(SourceLogic); + const { handleSelectedTabChanged } = useActions(SynchronizationLogic({ contentSource })); const tabs = [ { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.test.tsx index fb346ad96117e..ce295b467a09d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.test.tsx @@ -8,21 +8,24 @@ import React from 'react'; import { shallow } from 'enzyme'; +import moment from 'moment'; import { EuiFieldNumber, EuiSuperSelect } from '@elastic/eui'; import { FrequencyItem } from './frequency_item'; describe('FrequencyItem', () => { + const estimate = { + duration: 'PT3D', + nextStart: '2021-09-27T21:39:24+00:00', + lastRun: '2021-09-25T21:39:24+00:00', + }; + const props = { label: 'Item', description: 'My item', duration: 'PT2D', - estimate: { - duration: 'PT3D', - nextStart: '2021-09-27T21:39:24+00:00', - lastRun: '2021-09-25T21:39:24+00:00', - }, + estimate, }; it('renders', () => { @@ -60,5 +63,25 @@ describe('FrequencyItem', () => { expect(wrapper.find(EuiFieldNumber).prop('value')).toEqual(1); expect(wrapper.find(EuiSuperSelect).prop('valueOfSelected')).toEqual('minutes'); }); + + it('handles "nextStart" that is in past', () => { + const wrapper = shallow(); + + expect( + (wrapper.find('[data-test-subj="nextStartSummary"]').prop('values') as any)!.nextStartTime + ).toEqual('as soon as the currently running job finishes'); + }); + + it('handles "nextStart" that is in future', () => { + const estimateWithPastNextStart = { + ...estimate, + nextStart: moment().add(2, 'days').format(), + }; + const wrapper = shallow(); + + expect( + (wrapper.find('[data-test-subj="nextStartSummary"]').prop('values') as any)!.nextStartTime + ).toEqual('in 2 days'); + }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.tsx index 4e9eec28dc1eb..38f85ff2accaf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/frequency_item.tsx @@ -27,6 +27,8 @@ import { } from '../../../../../shared/constants'; import { SyncEstimate } from '../../../../types'; +import { NEXT_SYNC_RUNNING_MESSAGE } from '../../constants'; + interface Props { label: string; description: string; @@ -53,6 +55,8 @@ export const FrequencyItem: React.FC = ({ label, description, duration, e const [interval, unit] = formatDuration(duration); const { lastRun, nextStart, duration: durationEstimate } = estimate; const estimateDisplay = durationEstimate && moment.duration(durationEstimate).humanize(); + const nextStartIsPast = moment().isAfter(nextStart); + const nextStartTime = nextStartIsPast ? NEXT_SYNC_RUNNING_MESSAGE : moment(nextStart).fromNow(); const onChange = () => '#TODO'; @@ -86,6 +90,7 @@ export const FrequencyItem: React.FC = ({ label, description, duration, e const nextStartSummary = ( = ({ label, description, duration, e /> ), - nextStartTime: moment(nextStart).fromNow(), + nextStartTime, }} /> ); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.test.tsx new file mode 100644 index 0000000000000..42a08084db418 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.test.tsx @@ -0,0 +1,86 @@ +/* + * 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__/shallow_useeffect.mock'; +import { setMockActions, setMockValues } from '../../../../../__mocks__/kea_logic'; +import { fullContentSources } from '../../../../__mocks__/content_sources.mock'; +import { blockedWindow } from './__mocks__/syncronization.mock'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiSwitch } from '@elastic/eui'; + +import { ObjectsAndAssets } from './objects_and_assets'; + +describe('ObjectsAndAssets', () => { + const setThumbnailsChecked = jest.fn(); + const setContentExtractionChecked = jest.fn(); + const updateSyncSettings = jest.fn(); + const resetSyncSettings = jest.fn(); + const contentSource = fullContentSources[0]; + + const mockActions = { + setThumbnailsChecked, + setContentExtractionChecked, + updateSyncSettings, + resetSyncSettings, + }; + const mockValues = { + dataLoading: false, + blockedWindows: [blockedWindow], + contentSource, + thumbnailsChecked: true, + contentExtractionChecked: true, + hasUnsavedObjectsAndAssetsChanges: false, + }; + + beforeEach(() => { + setMockActions(mockActions); + setMockValues(mockValues); + }); + + it('renders', () => { + const wrapper = shallow(); + + expect(wrapper.find(EuiSwitch)).toHaveLength(2); + }); + + it('handles thumbnails switch change', () => { + const wrapper = shallow(); + wrapper + .find('[data-test-subj="ThumbnailsToggle"]') + .simulate('change', { target: { checked: false } }); + + expect(setThumbnailsChecked).toHaveBeenCalledWith(false); + }); + + it('handles content extraction switch change', () => { + const wrapper = shallow(); + wrapper + .find('[data-test-subj="ContentExtractionToggle"]') + .simulate('change', { target: { checked: false } }); + + expect(setContentExtractionChecked).toHaveBeenCalledWith(false); + }); + + it('renders correct text when areThumbnailsConfigEnabled is false', () => { + setMockValues({ + ...mockValues, + contentSource: { + ...contentSource, + areThumbnailsConfigEnabled: false, + }, + }); + const wrapper = shallow(); + + expect(wrapper.find('[data-test-subj="ThumbnailsToggle"]').prop('label')).toEqual( + 'Sync thumbnails - disabled at global configuration level' + ); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.tsx index 4c2804459f1ba..98abdb8bf67ea 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/objects_and_assets.tsx @@ -7,33 +7,113 @@ import React from 'react'; -import { EuiHorizontalRule, EuiLink } from '@elastic/eui'; +import { useActions, useValues } from 'kea'; +import { + EuiButton, + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiLink, + EuiSpacer, + EuiSwitch, + EuiText, +} from '@elastic/eui'; + +import { SAVE_BUTTON_LABEL } from '../../../../../shared/constants'; +import { UnsavedChangesPrompt } from '../../../../../shared/unsaved_changes_prompt'; import { ViewContentHeader } from '../../../../components/shared/view_content_header'; -import { NAV } from '../../../../constants'; +import { NAV, RESET_BUTTON } from '../../../../constants'; import { OBJECTS_AND_ASSETS_DOCS_URL } from '../../../../routes'; import { + SYNC_MANAGEMENT_CONTENT_EXTRACTION_LABEL, + SYNC_MANAGEMENT_THUMBNAILS_LABEL, + SYNC_MANAGEMENT_THUMBNAILS_GLOBAL_CONFIG_LABEL, SOURCE_OBJECTS_AND_ASSETS_DESCRIPTION, SYNC_OBJECTS_TYPES_LINK_LABEL, + SOURCE_OBJECTS_AND_ASSETS_LABEL, + SYNC_UNSAVED_CHANGES_MESSAGE, } from '../../constants'; +import { SourceLogic } from '../../source_logic'; import { SourceLayout } from '../source_layout'; +import { SynchronizationLogic } from './synchronization_logic'; + export const ObjectsAndAssets: React.FC = () => { + const { contentSource, dataLoading } = useValues(SourceLogic); + const { thumbnailsChecked, contentExtractionChecked, hasUnsavedObjectsAndAssetsChanges } = + useValues(SynchronizationLogic({ contentSource })); + const { + setThumbnailsChecked, + setContentExtractionChecked, + updateSyncSettings, + resetSyncSettings, + } = useActions(SynchronizationLogic({ contentSource })); + + const { areThumbnailsConfigEnabled } = contentSource; + + const actions = ( + + + + {RESET_BUTTON} + + + + + {SAVE_BUTTON_LABEL} + + + + ); + return ( + {SYNC_OBJECTS_TYPES_LINK_LABEL} -
TODO
+ {SOURCE_OBJECTS_AND_ASSETS_LABEL} + + + + setThumbnailsChecked(e.target.checked)} + label={ + areThumbnailsConfigEnabled + ? SYNC_MANAGEMENT_THUMBNAILS_LABEL + : SYNC_MANAGEMENT_THUMBNAILS_GLOBAL_CONFIG_LABEL + } + disabled={!areThumbnailsConfigEnabled} + data-test-subj="ThumbnailsToggle" + /> + + + + + setContentExtractionChecked(e.target.checked)} + label={SYNC_MANAGEMENT_CONTENT_EXTRACTION_LABEL} + data-test-subj="ContentExtractionToggle" + /> + +
); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.test.tsx index 632af08611ca9..fb9cdc6916fa9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.test.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { setMockValues } from '../../../../../__mocks__/kea_logic'; +import { setMockValues, setMockActions } from '../../../../../__mocks__/kea_logic'; +import { fullContentSources } from '../../../../__mocks__/content_sources.mock'; import React from 'react'; @@ -16,8 +17,15 @@ import { EuiLink, EuiCallOut, EuiSwitch } from '@elastic/eui'; import { Synchronization } from './synchronization'; describe('Synchronization', () => { + const updateSyncEnabled = jest.fn(); + const mockvalues = { contentSource: fullContentSources[0] }; + + beforeEach(() => { + setMockActions({ updateSyncEnabled }); + setMockValues(mockvalues); + }); + it('renders when config enabled', () => { - setMockValues({ contentSource: { isSyncConfigEnabled: true } }); const wrapper = shallow(); expect(wrapper.find(EuiLink)).toHaveLength(1); @@ -25,9 +33,16 @@ describe('Synchronization', () => { }); it('renders when config disabled', () => { - setMockValues({ contentSource: { isSyncConfigEnabled: false } }); + setMockValues({ contentSource: { isSyncConfigEnabled: false, indexing: { enabled: true } } }); const wrapper = shallow(); expect(wrapper.find(EuiCallOut)).toHaveLength(1); }); + + it('handles EuiSwitch change event', () => { + const wrapper = shallow(); + wrapper.find(EuiSwitch).simulate('change', { target: { checked: true } }); + + expect(updateSyncEnabled).toHaveBeenCalled(); + }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.tsx index 21daee8f26d40..21c44225615ea 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization.tsx @@ -7,7 +7,7 @@ import React from 'react'; -import { useValues } from 'kea'; +import { useActions, useValues } from 'kea'; import { EuiCallOut, EuiLink, EuiPanel, EuiSwitch, EuiSpacer, EuiText } from '@elastic/eui'; @@ -25,17 +25,23 @@ import { import { SourceLogic } from '../../source_logic'; import { SourceLayout } from '../source_layout'; +import { SynchronizationLogic } from './synchronization_logic'; + export const Synchronization: React.FC = () => { + const { contentSource } = useValues(SourceLogic); + const { updateSyncEnabled } = useActions(SynchronizationLogic({ contentSource })); + const { - contentSource: { isSyncConfigEnabled }, - } = useValues(SourceLogic); + isSyncConfigEnabled, + indexing: { enabled }, + } = contentSource; - const onChange = (checked: boolean) => `#TODO: ${checked}`; + const onChange = (checked: boolean) => updateSyncEnabled(checked); const syncToggle = ( onChange(e.target.checked)} /> diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.test.ts index 50553d1493417..c51ef6cf2bf34 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.test.ts @@ -5,14 +5,22 @@ * 2.0. */ -import { LogicMounter, mockKibanaValues } from '../../../../../__mocks__/kea_logic'; +import { + LogicMounter, + mockFlashMessageHelpers, + mockHttpValues, + mockKibanaValues, +} from '../../../../../__mocks__/kea_logic'; +import { fullContentSources } from '../../../../__mocks__/content_sources.mock'; import { nextTick } from '@kbn/test/jest'; -const contentSource = { id: 'source123' }; +import { expectedAsyncError } from '../../../../../test_helpers'; + jest.mock('../../source_logic', () => ({ - SourceLogic: { values: { contentSource } }, + SourceLogic: { actions: { setContentSource: jest.fn() } }, })); +import { SourceLogic } from '../../source_logic'; jest.mock('../../../../app_logic', () => ({ AppLogic: { values: { isOrganization: true } }, @@ -21,17 +29,23 @@ jest.mock('../../../../app_logic', () => ({ import { SynchronizationLogic, emptyBlockedWindow } from './synchronization_logic'; describe('SynchronizationLogic', () => { + const { http } = mockHttpValues; + const { flashAPIErrors, flashSuccessToast } = mockFlashMessageHelpers; const { navigateToUrl } = mockKibanaValues; const { mount } = new LogicMounter(SynchronizationLogic); + const contentSource = fullContentSources[0]; const defaultValues = { navigatingBetweenTabs: false, + hasUnsavedObjectsAndAssetsChanges: false, + contentExtractionChecked: true, + thumbnailsChecked: true, blockedWindows: [], }; beforeEach(() => { jest.clearAllMocks(); - mount(); + mount({}, { contentSource }); }); it('has expected default values', () => { @@ -50,6 +64,18 @@ describe('SynchronizationLogic', () => { expect(SynchronizationLogic.values.blockedWindows).toEqual([emptyBlockedWindow]); }); + + it('setThumbnailsChecked', () => { + SynchronizationLogic.actions.setThumbnailsChecked(false); + + expect(SynchronizationLogic.values.thumbnailsChecked).toEqual(false); + }); + + it('setContentExtractionChecked', () => { + SynchronizationLogic.actions.setContentExtractionChecked(false); + + expect(SynchronizationLogic.values.contentExtractionChecked).toEqual(false); + }); }); describe('listeners', () => { @@ -63,7 +89,7 @@ describe('SynchronizationLogic', () => { await nextTick(); expect(setNavigatingBetweenTabsSpy).toHaveBeenCalledWith(true); - expect(navigateToUrl).toHaveBeenCalledWith('/sources/source123/synchronization/frequency'); + expect(navigateToUrl).toHaveBeenCalledWith('/sources/123/synchronization/frequency'); }); it('calls calls correct route for "blocked_time_windows"', async () => { @@ -71,8 +97,125 @@ describe('SynchronizationLogic', () => { await nextTick(); expect(navigateToUrl).toHaveBeenCalledWith( - '/sources/source123/synchronization/frequency/blocked_windows' + '/sources/123/synchronization/frequency/blocked_windows' + ); + }); + }); + + describe('updateSyncEnabled', () => { + it('calls API and sets values for false value', async () => { + const setContentSourceSpy = jest.spyOn(SourceLogic.actions, 'setContentSource'); + const promise = Promise.resolve(contentSource); + http.patch.mockReturnValue(promise); + SynchronizationLogic.actions.updateSyncEnabled(false); + + expect(http.patch).toHaveBeenCalledWith( + '/internal/workplace_search/org/sources/123/settings', + { + body: JSON.stringify({ + content_source: { + indexing: { enabled: false }, + }, + }), + } + ); + await promise; + expect(setContentSourceSpy).toHaveBeenCalledWith(contentSource); + expect(flashSuccessToast).toHaveBeenCalledWith('Source synchronization disabled.'); + }); + + it('calls API and sets values for true value', async () => { + const promise = Promise.resolve(contentSource); + http.patch.mockReturnValue(promise); + SynchronizationLogic.actions.updateSyncEnabled(true); + + expect(http.patch).toHaveBeenCalledWith( + '/internal/workplace_search/org/sources/123/settings', + { + body: JSON.stringify({ + content_source: { + indexing: { enabled: true }, + }, + }), + } + ); + await promise; + expect(flashSuccessToast).toHaveBeenCalledWith('Source synchronization enabled.'); + }); + + it('handles error', async () => { + const error = { + response: { + error: 'this is an error', + status: 400, + }, + }; + const promise = Promise.reject(error); + http.patch.mockReturnValue(promise); + SynchronizationLogic.actions.updateSyncEnabled(false); + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith(error); + }); + }); + + describe('resetSyncSettings', () => { + it('calls methods', async () => { + const setThumbnailsCheckedSpy = jest.spyOn( + SynchronizationLogic.actions, + 'setThumbnailsChecked' + ); + const setContentExtractionCheckedSpy = jest.spyOn( + SynchronizationLogic.actions, + 'setContentExtractionChecked' ); + SynchronizationLogic.actions.resetSyncSettings(); + + expect(setThumbnailsCheckedSpy).toHaveBeenCalledWith(true); + expect(setContentExtractionCheckedSpy).toHaveBeenCalledWith(true); + }); + }); + + describe('updateSyncSettings', () => { + it('calls API and sets values', async () => { + const setContentSourceSpy = jest.spyOn(SourceLogic.actions, 'setContentSource'); + const promise = Promise.resolve(contentSource); + http.patch.mockReturnValue(promise); + SynchronizationLogic.actions.updateSyncSettings(); + + expect(http.patch).toHaveBeenCalledWith( + '/internal/workplace_search/org/sources/123/settings', + { + body: JSON.stringify({ + content_source: { + indexing: { + features: { + content_extraction: { enabled: true }, + thumbnails: { enabled: true }, + }, + }, + }, + }), + } + ); + await promise; + expect(setContentSourceSpy).toHaveBeenCalledWith(contentSource); + expect(flashSuccessToast).toHaveBeenCalledWith('Source synchronization settings updated.'); + }); + + it('handles error', async () => { + const error = { + response: { + error: 'this is an error', + status: 400, + }, + }; + const promise = Promise.reject(error); + http.patch.mockReturnValue(promise); + SynchronizationLogic.actions.updateSyncSettings(); + await expectedAsyncError(promise); + + expect(flashAPIErrors).toHaveBeenCalledWith(error); }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts index 4f67f6471e6e1..4106ab70cf201 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/synchronization_logic.ts @@ -10,6 +10,8 @@ import moment from 'moment'; export type TabId = 'source_sync_frequency' | 'blocked_time_windows'; +import { flashAPIErrors, flashSuccessToast } from '../../../../../shared/flash_messages'; +import { HttpLogic } from '../../../../../shared/http'; import { KibanaLogic } from '../../../../../shared/kibana'; import { AppLogic } from '../../../../app_logic'; import { @@ -19,17 +21,30 @@ import { } from '../../../../routes'; import { BlockedWindow } from '../../../../types'; +import { + SYNC_ENABLED_MESSAGE, + SYNC_DISABLED_MESSAGE, + SYNC_SETTINGS_UPDATED_MESSAGE, +} from '../../constants'; import { SourceLogic } from '../../source_logic'; interface SynchronizationActions { setNavigatingBetweenTabs(navigatingBetweenTabs: boolean): boolean; handleSelectedTabChanged(tabId: TabId): TabId; addBlockedWindow(): void; + updateSyncSettings(): void; + resetSyncSettings(): void; + updateSyncEnabled(enabled: boolean): boolean; + setThumbnailsChecked(checked: boolean): boolean; + setContentExtractionChecked(checked: boolean): boolean; } interface SynchronizationValues { - hasUnsavedChanges: boolean; navigatingBetweenTabs: boolean; + hasUnsavedFrequencyChanges: boolean; + hasUnsavedObjectsAndAssetsChanges: boolean; + thumbnailsChecked: boolean; + contentExtractionChecked: boolean; blockedWindows: BlockedWindow[]; } @@ -43,12 +58,18 @@ export const emptyBlockedWindow: BlockedWindow = { export const SynchronizationLogic = kea< MakeLogicType >({ + path: ['enterprise_search', 'workplace_search', 'synchronization_logic'], actions: { setNavigatingBetweenTabs: (navigatingBetweenTabs: boolean) => navigatingBetweenTabs, handleSelectedTabChanged: (tabId: TabId) => tabId, + updateSyncEnabled: (enabled: boolean) => enabled, + setThumbnailsChecked: (checked: boolean) => checked, + setContentExtractionChecked: (checked: boolean) => checked, + updateSyncSettings: true, + resetSyncSettings: true, addBlockedWindow: true, }, - reducers: { + reducers: ({ props }) => ({ navigatingBetweenTabs: [ false, { @@ -61,11 +82,47 @@ export const SynchronizationLogic = kea< addBlockedWindow: (state, _) => [...state, emptyBlockedWindow], }, ], - }, - listeners: ({ actions }) => ({ + thumbnailsChecked: [ + props.contentSource.indexing.features.thumbnails.enabled, + { + setThumbnailsChecked: (_, thumbnailsChecked) => thumbnailsChecked, + }, + ], + contentExtractionChecked: [ + props.contentSource.indexing.features.contentExtraction.enabled, + { + setContentExtractionChecked: (_, contentExtractionChecked) => contentExtractionChecked, + }, + ], + }), + selectors: ({ selectors }) => ({ + hasUnsavedObjectsAndAssetsChanges: [ + () => [ + selectors.thumbnailsChecked, + selectors.contentExtractionChecked, + (_, props) => props.contentSource, + ], + (thumbnailsChecked, contentExtractionChecked, contentSource) => { + const { + indexing: { + features: { + thumbnails: { enabled: thumbnailsEnabled }, + contentExtraction: { enabled: contentExtractionEnabled }, + }, + }, + } = contentSource; + + return ( + thumbnailsChecked !== thumbnailsEnabled || + contentExtractionChecked !== contentExtractionEnabled + ); + }, + ], + }), + listeners: ({ actions, values, props }) => ({ handleSelectedTabChanged: async (tabId, breakpoint) => { const { isOrganization } = AppLogic.values; - const { id: sourceId } = SourceLogic.values.contentSource; + const { id: sourceId } = props.contentSource; const path = tabId === 'source_sync_frequency' ? getContentSourcePath(SYNC_FREQUENCY_PATH, sourceId, isOrganization) @@ -82,5 +139,51 @@ export const SynchronizationLogic = kea< KibanaLogic.values.navigateToUrl(path); actions.setNavigatingBetweenTabs(false); }, + updateSyncEnabled: async (enabled) => { + const { id: sourceId } = props.contentSource; + const route = `/internal/workplace_search/org/sources/${sourceId}/settings`; + const successMessage = enabled ? SYNC_ENABLED_MESSAGE : SYNC_DISABLED_MESSAGE; + + try { + const response = await HttpLogic.values.http.patch(route, { + body: JSON.stringify({ content_source: { indexing: { enabled } } }), + }); + + SourceLogic.actions.setContentSource(response); + flashSuccessToast(successMessage); + } catch (e) { + flashAPIErrors(e); + } + }, + resetSyncSettings: () => { + actions.setThumbnailsChecked(props.contentSource.indexing.features.thumbnails.enabled); + actions.setContentExtractionChecked( + props.contentSource.indexing.features.contentExtraction.enabled + ); + }, + updateSyncSettings: async () => { + const { id: sourceId } = props.contentSource; + const route = `/internal/workplace_search/org/sources/${sourceId}/settings`; + + try { + const response = await HttpLogic.values.http.patch(route, { + body: JSON.stringify({ + content_source: { + indexing: { + features: { + content_extraction: { enabled: values.contentExtractionChecked }, + thumbnails: { enabled: values.thumbnailsChecked }, + }, + }, + }, + }), + }); + + SourceLogic.actions.setContentSource(response); + flashSuccessToast(SYNC_SETTINGS_UPDATED_MESSAGE); + } catch (e) { + flashAPIErrors(e); + } + }, }), }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/constants.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/constants.ts index ae55a970a4f9f..4e46100b591b9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/constants.ts @@ -306,20 +306,6 @@ export const SOURCE_CONFIG_TITLE = i18n.translate( } ); -export const SYNC_MANAGEMENT_TITLE = i18n.translate( - 'xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementTitle', - { - defaultMessage: 'Sync management', - } -); - -export const SYNC_MANAGEMENT_DESCRIPTION = i18n.translate( - 'xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementDescription', - { - defaultMessage: 'Enable and disable extraction of specific content for this source.', - } -); - export const SYNC_MANAGEMENT_SYNCHRONIZE_LABEL = i18n.translate( 'xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementSynchronizeLabel', { @@ -344,7 +330,7 @@ export const SYNC_MANAGEMENT_THUMBNAILS_GLOBAL_CONFIG_LABEL = i18n.translate( export const SYNC_MANAGEMENT_CONTENT_EXTRACTION_LABEL = i18n.translate( 'xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementContentExtractionLabel', { - defaultMessage: 'Sync all text and content', + defaultMessage: 'Sync full-text from files', } ); @@ -565,6 +551,13 @@ export const SOURCE_OBJECTS_AND_ASSETS_DESCRIPTION = i18n.translate( } ); +export const SOURCE_OBJECTS_AND_ASSETS_LABEL = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.sourceObjectsAndAssetsLabel', + { + defaultMessage: 'Object and details to include in search results', + } +); + export const SOURCE_SYNCRONIZATION_TOGGLE_LABEL = i18n.translate( 'xpack.enterpriseSearch.workplaceSearch.sources.sourceSyncronizationToggleLabel', { @@ -711,3 +704,38 @@ export const BLOCKED_EMPTY_STATE_DESCRIPTION = i18n.translate( defaultMessage: 'Add a blocked time window to only perform syncs at the right time.', } ); + +export const SYNC_ENABLED_MESSAGE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.syncEnabledMessage', + { + defaultMessage: 'Source synchronization enabled.', + } +); + +export const SYNC_DISABLED_MESSAGE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.syncDisabledMessage', + { + defaultMessage: 'Source synchronization disabled.', + } +); + +export const SYNC_SETTINGS_UPDATED_MESSAGE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.syncSettingsUpdatedMessage', + { + defaultMessage: 'Source synchronization settings updated.', + } +); + +export const SYNC_UNSAVED_CHANGES_MESSAGE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.syncUnsavedChangesMessage', + { + defaultMessage: 'Your changes have not been saved. Are you sure you want to leave?', + } +); + +export const NEXT_SYNC_RUNNING_MESSAGE = i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.sources.nextSyncRunningMessage', + { + defaultMessage: 'as soon as the currently running job finishes', + } +); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts index 0d8d5684c4a4c..1fb4477cea5c0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts @@ -58,8 +58,8 @@ describe('SourceLogic', () => { }); describe('actions', () => { - it('onInitializeSource', () => { - SourceLogic.actions.onInitializeSource(contentSource); + it('setContentSource', () => { + SourceLogic.actions.setContentSource(contentSource); expect(SourceLogic.values.contentSource).toEqual(contentSource); expect(SourceLogic.values.dataLoading).toEqual(false); @@ -67,7 +67,7 @@ describe('SourceLogic', () => { it('onUpdateSourceName', () => { const NAME = 'foo'; - SourceLogic.actions.onInitializeSource(contentSource); + SourceLogic.actions.setContentSource(contentSource); SourceLogic.actions.onUpdateSourceName(NAME); expect(SourceLogic.values.contentSource).toEqual({ @@ -88,7 +88,7 @@ describe('SourceLogic', () => { it('setContentFilterValue', () => { const VALUE = 'bar'; SourceLogic.actions.setSearchResults(searchServerResponse); - SourceLogic.actions.onInitializeSource(contentSource); + SourceLogic.actions.setContentSource(contentSource); SourceLogic.actions.setContentFilterValue(VALUE); expect(SourceLogic.values.contentMeta).toEqual({ @@ -127,7 +127,7 @@ describe('SourceLogic', () => { describe('listeners', () => { describe('initializeSource', () => { it('calls API and sets values (org)', async () => { - const onInitializeSourceSpy = jest.spyOn(SourceLogic.actions, 'onInitializeSource'); + const onInitializeSourceSpy = jest.spyOn(SourceLogic.actions, 'setContentSource'); const promise = Promise.resolve(contentSource); http.get.mockReturnValue(promise); SourceLogic.actions.initializeSource(contentSource.id); @@ -140,7 +140,7 @@ describe('SourceLogic', () => { it('calls API and sets values (account)', async () => { AppLogic.values.isOrganization = false; - const onInitializeSourceSpy = jest.spyOn(SourceLogic.actions, 'onInitializeSource'); + const onInitializeSourceSpy = jest.spyOn(SourceLogic.actions, 'setContentSource'); const promise = Promise.resolve(contentSource); http.get.mockReturnValue(promise); SourceLogic.actions.initializeSource(contentSource.id); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts index c31eacda69515..d10400bc5ba2d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts @@ -23,7 +23,7 @@ import { PRIVATE_SOURCES_PATH, SOURCES_PATH, getSourcesPath } from '../../routes import { ContentSourceFullData, Meta, DocumentSummaryItem, SourceContentItem } from '../../types'; export interface SourceActions { - onInitializeSource(contentSource: ContentSourceFullData): ContentSourceFullData; + setContentSource(contentSource: ContentSourceFullData): ContentSourceFullData; onUpdateSourceName(name: string): string; setSearchResults(searchResultsResponse: SearchResultsResponse): SearchResultsResponse; initializeFederatedSummary(sourceId: string): { sourceId: string }; @@ -73,7 +73,7 @@ interface SourceUpdatePayload { export const SourceLogic = kea>({ path: ['enterprise_search', 'workplace_search', 'source_logic'], actions: { - onInitializeSource: (contentSource: ContentSourceFullData) => contentSource, + setContentSource: (contentSource: ContentSourceFullData) => contentSource, onUpdateSourceName: (name: string) => name, onUpdateSummary: (summary: object[]) => summary, setSearchResults: (searchResultsResponse: SearchResultsResponse) => searchResultsResponse, @@ -93,7 +93,7 @@ export const SourceLogic = kea>({ contentSource: [ {} as ContentSourceFullData, { - onInitializeSource: (_, contentSource) => contentSource, + setContentSource: (_, contentSource) => contentSource, onUpdateSourceName: (contentSource, name) => ({ ...contentSource, name, @@ -108,7 +108,7 @@ export const SourceLogic = kea>({ dataLoading: [ true, { - onInitializeSource: () => false, + setContentSource: () => false, resetSourceState: () => true, }, ], @@ -158,7 +158,7 @@ export const SourceLogic = kea>({ try { const response = await HttpLogic.values.http.get(route); - actions.onInitializeSource(response); + actions.setContentSource(response); if (response.isFederatedSource) { actions.initializeFederatedSummary(sourceId); } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 48d15d4fd2574..7d6a668733992 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9951,11 +9951,9 @@ "xpack.enterpriseSearch.workplaceSearch.contentSources.displaySettings.unsaved.message": "表示設定は保存されていません。終了してよろしいですか?", "xpack.enterpriseSearch.workplaceSearch.contentSources.displaySettings.visibleFields.title": "表示フィールド", "xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementContentExtractionLabel": "すべてのテキストとコンテンツを同期", - "xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementDescription": "このソースの特定のコンテンツの抽出を有効および無効にします。", "xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementGlobalConfigLabel": "サムネイルを同期 - グローバル構成レベルでは無効", "xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementSynchronizeLabel": "このソースを同期", "xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementThumbnailsLabel": "サムネイルを同期", - "xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementTitle": "同期管理", "xpack.enterpriseSearch.workplaceSearch.copyText": "コピー", "xpack.enterpriseSearch.workplaceSearch.credentials.description": "クライアントで次の資格情報を使用して、認証サーバーからアクセストークンを要求します。", "xpack.enterpriseSearch.workplaceSearch.credentials.title": "資格情報", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 3bde8b402f08a..cd5fb213c0696 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -10050,11 +10050,9 @@ "xpack.enterpriseSearch.workplaceSearch.contentSources.displaySettings.unsaved.message": "您的显示设置尚未保存。是否确定要离开?", "xpack.enterpriseSearch.workplaceSearch.contentSources.displaySettings.visibleFields.title": "可见的字段", "xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementContentExtractionLabel": "同步所有文本和内容", - "xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementDescription": "为此源启用和禁用特定内容的提取。", "xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementGlobalConfigLabel": "同步缩略图 - 已在全局配置级别禁用", "xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementSynchronizeLabel": "同步此源", "xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementThumbnailsLabel": "同步缩略图", - "xpack.enterpriseSearch.workplaceSearch.contentSources.syncManagementTitle": "同步管理", "xpack.enterpriseSearch.workplaceSearch.copyText": "复制", "xpack.enterpriseSearch.workplaceSearch.credentials.description": "在您的客户端中使用以下凭据从我们的身份验证服务器请求访问令牌。", "xpack.enterpriseSearch.workplaceSearch.credentials.title": "凭据",