Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Workplace Search] Migrate Objects and assets from Source settings to Synchronization section #113982

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ describe('SynchronizationLogic', () => {

const defaultValues = {
navigatingBetweenTabs: false,
hasUnsavedObjectsAndAssetsChanges: false,
contentExtractionChecked: true,
thumbnailsChecked: true,
blockedWindows: [],
};

Expand All @@ -61,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', () => {
Expand Down Expand Up @@ -143,5 +158,65 @@ describe('SynchronizationLogic', () => {
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);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,30 @@ import {
} from '../../../../routes';
import { BlockedWindow } from '../../../../types';

import { SYNC_ENABLED_MESSAGE, SYNC_DISABLED_MESSAGE } from '../../constants';
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[];
}

Expand All @@ -47,13 +58,18 @@ export const emptyBlockedWindow: BlockedWindow = {
export const SynchronizationLogic = kea<
MakeLogicType<SynchronizationValues, SynchronizationActions>
>({
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,
{
Expand All @@ -66,7 +82,43 @@ export const SynchronizationLogic = kea<
addBlockedWindow: (state, _) => [...state, emptyBlockedWindow],
},
],
},
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;
Expand Down Expand Up @@ -103,5 +155,35 @@ export const SynchronizationLogic = kea<
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);
}
},
}),
});
Original file line number Diff line number Diff line change
Expand Up @@ -711,3 +711,17 @@ export const SYNC_DISABLED_MESSAGE = i18n.translate(
defaultMessage: 'Source synchronization disabled.',
}
);

export const SYNC_SETTINGS_UPDATED_MESSAGE = i18n.translate(
'xpack.enterpriseSearch.workplaceSearch.sources.sync_settings_updated_message',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably use camelCase here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch!

{
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?',
}
);