From e9867e0fd1e82c97a2671a1f275034cbbdf15966 Mon Sep 17 00:00:00 2001 From: Jason Stoltzfus Date: Tue, 10 Nov 2020 13:07:00 -0500 Subject: [PATCH] [App Search] Added the log retention panel to the Settings page (#82982) (#83068) --- .../log_retention_panel.test.tsx | 187 ++++++++++++++++++ .../log_retention/log_retention_panel.tsx | 110 +++++++++++ .../log_retention/messaging/constants.ts | 119 +++++++++++ .../determine_tooltip_content.test.ts | 168 ++++++++++++++++ .../messaging/determine_tooltip_content.ts | 46 +++++ .../log_retention/messaging/index.test.tsx | 74 +++++++ .../log_retention/messaging/index.tsx | 46 +++++ .../settings/log_retention/messaging/types.ts | 18 ++ .../components/settings/settings.tsx | 19 +- 9 files changed, 782 insertions(+), 5 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/constants.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/determine_tooltip_content.test.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/determine_tooltip_content.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/types.ts diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx new file mode 100644 index 00000000000000..b4f7e92fac8cc6 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.test.tsx @@ -0,0 +1,187 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import '../../../../__mocks__/kea.mock'; +import '../../../../__mocks__/shallow_useeffect.mock'; + +import { setMockActions, setMockValues } from '../../../../__mocks__'; + +import React from 'react'; +import { shallow } from 'enzyme'; + +import { LogRetentionPanel } from './log_retention_panel'; +import { ILogRetention } from './types'; + +describe('', () => { + const actions = { + fetchLogRetention: jest.fn(), + toggleLogRetention: jest.fn(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + setMockActions(actions); + }); + + it('renders', () => { + const logRetentionPanel = shallow(); + expect(logRetentionPanel.find('[data-test-subj="LogRetentionPanel"]')).toHaveLength(1); + }); + + it('initializes data on mount', () => { + shallow(); + expect(actions.fetchLogRetention).toHaveBeenCalledTimes(1); + }); + + it('renders Analytics switch off when analytics log retention is false in LogRetentionLogic ', () => { + setMockValues({ + isLogRetentionUpdating: false, + logRetention: mockLogRetention({ + analytics: { + enabled: false, + }, + }), + }); + + const logRetentionPanel = shallow(); + expect( + logRetentionPanel.find('[data-test-subj="LogRetentionPanelAnalyticsSwitch"]').prop('checked') + ).toEqual(false); + }); + + it('renders Analytics switch on when analyticsLogRetention is true in LogRetentionLogic ', () => { + setMockValues({ + isLogRetentionUpdating: false, + logRetention: mockLogRetention({ + analytics: { + enabled: true, + }, + }), + }); + + const logRetentionPanel = shallow(); + expect( + logRetentionPanel.find('[data-test-subj="LogRetentionPanelAnalyticsSwitch"]').prop('checked') + ).toEqual(true); + }); + + it('renders API switch off when apiLogRetention is false in LogRetentionLogic ', () => { + setMockValues({ + isLogRetentionUpdating: false, + logRetention: mockLogRetention({ + api: { + enabled: false, + }, + }), + }); + + const logRetentionPanel = shallow(); + expect( + logRetentionPanel.find('[data-test-subj="LogRetentionPanelAPISwitch"]').prop('checked') + ).toEqual(false); + }); + + it('renders API switch on when apiLogRetention is true in LogRetentionLogic ', () => { + setMockValues({ + isLogRetentionUpdating: false, + logRetention: mockLogRetention({ + api: { + enabled: true, + }, + }), + }); + + const logRetentionPanel = shallow(); + expect( + logRetentionPanel.find('[data-test-subj="LogRetentionPanelAPISwitch"]').prop('checked') + ).toEqual(true); + }); + + it('enables both switches when isLogRetentionUpdating is false', () => { + setMockValues({ + isLogRetentionUpdating: false, + logRetention: mockLogRetention({}), + }); + const logRetentionPanel = shallow(); + expect( + logRetentionPanel.find('[data-test-subj="LogRetentionPanelAnalyticsSwitch"]').prop('disabled') + ).toEqual(false); + expect( + logRetentionPanel.find('[data-test-subj="LogRetentionPanelAPISwitch"]').prop('disabled') + ).toEqual(false); + }); + + it('disables both switches when isLogRetentionUpdating is true', () => { + setMockValues({ + isLogRetentionUpdating: true, + logRetention: mockLogRetention({}), + }); + const logRetentionPanel = shallow(); + + expect( + logRetentionPanel.find('[data-test-subj="LogRetentionPanelAnalyticsSwitch"]').prop('disabled') + ).toEqual(true); + expect( + logRetentionPanel.find('[data-test-subj="LogRetentionPanelAPISwitch"]').prop('disabled') + ).toEqual(true); + }); + + it('calls toggleLogRetention when analytics log retention option is changed', () => { + setMockValues({ + isLogRetentionUpdating: false, + logRetention: mockLogRetention({ + analytics: { + enabled: false, + }, + }), + }); + const logRetentionPanel = shallow(); + logRetentionPanel + .find('[data-test-subj="LogRetentionPanelAnalyticsSwitch"]') + .simulate('change'); + expect(actions.toggleLogRetention).toHaveBeenCalledWith('analytics'); + }); + + it('calls toggleLogRetention when api log retention option is changed', () => { + setMockValues({ + isLogRetentionUpdating: false, + logRetention: mockLogRetention({ + analytics: { + enabled: false, + }, + }), + }); + const logRetentionPanel = shallow(); + logRetentionPanel.find('[data-test-subj="LogRetentionPanelAPISwitch"]').simulate('change'); + expect(actions.toggleLogRetention).toHaveBeenCalledWith('api'); + }); +}); + +const mockLogRetention = (logRetention: Partial) => { + const baseLogRetention = { + analytics: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + api: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + }; + + return { + analytics: { + ...baseLogRetention.analytics, + ...logRetention.analytics, + }, + api: { + ...baseLogRetention.api, + ...logRetention.api, + }, + }; +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.tsx new file mode 100644 index 00000000000000..7b8eea061d1108 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/log_retention_panel.tsx @@ -0,0 +1,110 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; + +import { EuiLink, EuiSpacer, EuiSwitch, EuiText, EuiTextColor, EuiTitle } from '@elastic/eui'; +import { useActions, useValues } from 'kea'; + +import { LogRetentionLogic } from './log_retention_logic'; +import { AnalyticsLogRetentionMessage, ApiLogRetentionMessage } from './messaging'; +import { ELogRetentionOptions } from './types'; + +export const LogRetentionPanel: React.FC = () => { + const { toggleLogRetention, fetchLogRetention } = useActions(LogRetentionLogic); + + const { logRetention, isLogRetentionUpdating } = useValues(LogRetentionLogic); + + const hasILM = logRetention !== null; + const analyticsLogRetentionSettings = logRetention?.[ELogRetentionOptions.Analytics]; + const apiLogRetentionSettings = logRetention?.[ELogRetentionOptions.API]; + + useEffect(() => { + fetchLogRetention(); + }, []); + + return ( +
+ +

+ {i18n.translate('xpack.enterpriseSearch.appSearch.settings.logRetention.title', { + defaultMessage: 'Log Retention', + })} +

+
+ +

+ {i18n.translate('xpack.enterpriseSearch.appSearch.settings.logRetention.description', { + defaultMessage: 'Manage the default write settings for API Logs and Analytics.', + })}{' '} + + {i18n.translate('xpack.enterpriseSearch.appSearch.settings.logRetention.learnMore', { + defaultMessage: 'Learn more about retention settings.', + })} + +

+
+ + + + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.label', + { + defaultMessage: 'Analytics Logs', + } + )} + + {': '} + {hasILM && ( + + + + )} + + } + checked={!!analyticsLogRetentionSettings?.enabled} + onChange={() => toggleLogRetention(ELogRetentionOptions.Analytics)} + disabled={isLogRetentionUpdating} + data-test-subj="LogRetentionPanelAnalyticsSwitch" + /> + + + + + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.settings.logRetention.api.label', + { + defaultMessage: 'API Logs', + } + )} + + {': '} + {hasILM && ( + + + + )} + + } + checked={!!apiLogRetentionSettings?.enabled} + onChange={() => toggleLogRetention(ELogRetentionOptions.API)} + disabled={isLogRetentionUpdating} + data-test-subj="LogRetentionPanelAPISwitch" + /> + +
+ ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/constants.ts new file mode 100644 index 00000000000000..f7f0fbdff1acbd --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/constants.ts @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; + +import { ILogRetentionMessages } from './types'; +import { renderLogRetentionDate } from '.'; + +const ANALYTICS_NO_LOGGING = i18n.translate( + 'xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.noLogging', + { + defaultMessage: 'Analytics collection has been disabled for all engines.', + } +); + +const ANALYTICS_NO_LOGGING_COLLECTED = (disabledAt: string) => + i18n.translate( + 'xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.noLogging.collected', + { + defaultMessage: 'The last date analytics were collected was {disabledAt}.', + values: { disabledAt }, + } + ); + +const ANALYTICS_NO_LOGGING_NOT_COLLECTED = i18n.translate( + 'xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.noLogging.notCollected', + { + defaultMessage: 'There are no analytics collected.', + } +); + +const ANALYTICS_ILM_DISABLED = i18n.translate( + 'xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.ilmDisabled', + { + defaultMessage: "App Search isn't managing analytics retention.", + } +); + +const ANALYTICS_CUSTOM_POLICY = i18n.translate( + 'xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.customPolicy', + { + defaultMessage: 'You have a custom analytics retention policy.', + } +); + +const ANALYTICS_STORED = (minAgeDays: number | null | undefined) => + i18n.translate('xpack.enterpriseSearch.appSearch.settings.logRetention.analytics.stored', { + defaultMessage: 'Your analytics are being stored for at least {minAgeDays} days.', + values: { minAgeDays }, + }); + +const API_NO_LOGGING = i18n.translate( + 'xpack.enterpriseSearch.appSearch.settings.logRetention.api.noLogging', + { + defaultMessage: 'API logging has been disabled for all engines.', + } +); + +const API_NO_LOGGING_COLLECTED = (disabledAt: string) => + i18n.translate('xpack.enterpriseSearch.appSearch.settings.logRetention.api.noLogging.collected', { + defaultMessage: 'The last date logs were collected was {disabledAt}.', + values: { disabledAt }, + }); + +const API_NO_LOGGING_NOT_COLLECTED = i18n.translate( + 'xpack.enterpriseSearch.appSearch.settings.logRetention.api.noLogging.notCollected', + { + defaultMessage: 'There are no logs collected.', + } +); + +const API_ILM_DISABLED = i18n.translate( + 'xpack.enterpriseSearch.appSearch.settings.logRetention.api.ilmDisabled', + { + defaultMessage: "App Search isn't managing API log retention.", + } +); + +const API_CUSTOM_POLICY = i18n.translate( + 'xpack.enterpriseSearch.appSearch.settings.logRetention.api.customPolicy', + { + defaultMessage: 'You have a custom API log retention policy.', + } +); + +const API_STORED = (minAgeDays: number | null | undefined) => + i18n.translate('xpack.enterpriseSearch.appSearch.settings.logRetention.api.stored', { + defaultMessage: 'Your logs are being stored for at least {minAgeDays} days.', + values: { minAgeDays }, + }); + +export const ANALYTICS_MESSAGES: ILogRetentionMessages = { + noLogging: (_, logRetentionSettings) => + `${ANALYTICS_NO_LOGGING} ${ + logRetentionSettings.disabledAt + ? ANALYTICS_NO_LOGGING_COLLECTED(renderLogRetentionDate(logRetentionSettings.disabledAt)) + : ANALYTICS_NO_LOGGING_NOT_COLLECTED + }`, + ilmDisabled: ANALYTICS_ILM_DISABLED, + customPolicy: ANALYTICS_CUSTOM_POLICY, + defaultPolicy: (_, logRetentionSettings) => + ANALYTICS_STORED(logRetentionSettings.retentionPolicy?.minAgeDays), +}; + +export const API_MESSAGES: ILogRetentionMessages = { + noLogging: (_, logRetentionSettings) => + `${API_NO_LOGGING} ${ + logRetentionSettings.disabledAt + ? API_NO_LOGGING_COLLECTED(renderLogRetentionDate(logRetentionSettings.disabledAt)) + : API_NO_LOGGING_NOT_COLLECTED + }`, + ilmDisabled: API_ILM_DISABLED, + customPolicy: API_CUSTOM_POLICY, + defaultPolicy: (_, logRetentionSettings) => + API_STORED(logRetentionSettings.retentionPolicy?.minAgeDays), +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/determine_tooltip_content.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/determine_tooltip_content.test.ts new file mode 100644 index 00000000000000..fbc2ccfbc8a527 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/determine_tooltip_content.test.ts @@ -0,0 +1,168 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { determineTooltipContent } from './determine_tooltip_content'; +import { ANALYTICS_MESSAGES, API_MESSAGES } from './constants'; + +describe('determineTooltipContent', () => { + const BASE_SETTINGS = { + disabledAt: null, + enabled: true, + retentionPolicy: null, + }; + + it('will return nothing if settings are not provided', () => { + expect(determineTooltipContent(ANALYTICS_MESSAGES, true)).toBeUndefined(); + }); + + describe('analytics messages', () => { + describe('when analytics logs are enabled', () => { + describe("and they're using the default policy", () => { + it('will render a retention policy message', () => { + expect( + determineTooltipContent(ANALYTICS_MESSAGES, true, { + ...BASE_SETTINGS, + enabled: true, + retentionPolicy: { + isDefault: true, + minAgeDays: 7, + }, + }) + ).toEqual('Your analytics are being stored for at least 7 days.'); + }); + }); + + describe('and there is a custom policy', () => { + it('will render a retention policy message', () => { + expect( + determineTooltipContent(ANALYTICS_MESSAGES, true, { + ...BASE_SETTINGS, + enabled: true, + retentionPolicy: { + isDefault: false, + minAgeDays: 7, + }, + }) + ).toEqual('You have a custom analytics retention policy.'); + }); + }); + }); + + describe('when analytics logs are disabled', () => { + describe('and there is no disabledAt date', () => { + it('will render a no logging message', () => { + expect( + determineTooltipContent(ANALYTICS_MESSAGES, true, { + ...BASE_SETTINGS, + enabled: false, + disabledAt: null, + }) + ).toEqual( + 'Analytics collection has been disabled for all engines. There are no analytics collected.' + ); + }); + }); + + describe('and there is a disabledAt date', () => { + it('will render a no logging message', () => { + expect( + determineTooltipContent(ANALYTICS_MESSAGES, true, { + ...BASE_SETTINGS, + enabled: false, + disabledAt: 'Thu, 05 Nov 2020 18:57:28 +0000', + }) + ).toEqual( + 'Analytics collection has been disabled for all engines. The last date analytics were collected was November 5, 2020.' + ); + }); + }); + }); + + describe('when ilm is disabled entirely', () => { + it('will render a no logging message', () => { + expect( + determineTooltipContent(ANALYTICS_MESSAGES, false, { + ...BASE_SETTINGS, + enabled: true, + }) + ).toEqual("App Search isn't managing analytics retention."); + }); + }); + }); + + describe('api messages', () => { + describe('when analytics logs are enabled', () => { + describe("and they're using the default policy", () => { + it('will render a retention policy message', () => { + expect( + determineTooltipContent(API_MESSAGES, true, { + ...BASE_SETTINGS, + enabled: true, + retentionPolicy: { + isDefault: true, + minAgeDays: 7, + }, + }) + ).toEqual('Your logs are being stored for at least 7 days.'); + }); + }); + + describe('and there is a custom policy', () => { + it('will render a retention policy message', () => { + expect( + determineTooltipContent(API_MESSAGES, true, { + ...BASE_SETTINGS, + enabled: true, + retentionPolicy: { + isDefault: false, + minAgeDays: 7, + }, + }) + ).toEqual('You have a custom API log retention policy.'); + }); + }); + }); + + describe('when analytics logs are disabled', () => { + describe('and there is no disabledAt date', () => { + it('will render a no logging message', () => { + expect( + determineTooltipContent(API_MESSAGES, true, { + ...BASE_SETTINGS, + enabled: false, + disabledAt: null, + }) + ).toEqual('API logging has been disabled for all engines. There are no logs collected.'); + }); + }); + + describe('and there is a disabledAt date', () => { + it('will render a no logging message', () => { + expect( + determineTooltipContent(API_MESSAGES, true, { + ...BASE_SETTINGS, + enabled: false, + disabledAt: 'Thu, 05 Nov 2020 18:57:28 +0000', + }) + ).toEqual( + 'API logging has been disabled for all engines. The last date logs were collected was November 5, 2020.' + ); + }); + }); + }); + + describe('when ilm is disabled entirely', () => { + it('will render a no logging message', () => { + expect( + determineTooltipContent(API_MESSAGES, false, { + ...BASE_SETTINGS, + enabled: true, + }) + ).toEqual("App Search isn't managing API log retention."); + }); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/determine_tooltip_content.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/determine_tooltip_content.ts new file mode 100644 index 00000000000000..e361e28490a830 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/determine_tooltip_content.ts @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ILogRetentionSettings } from '../types'; +import { TMessageStringOrFunction, ILogRetentionMessages } from './types'; + +export const determineTooltipContent = ( + messages: ILogRetentionMessages, + ilmEnabled: boolean, + logRetentionSettings?: ILogRetentionSettings +) => { + if (typeof logRetentionSettings === 'undefined') { + return; + } + + const renderOrReturnMessage = (message: TMessageStringOrFunction) => { + if (typeof message === 'function') { + return message(ilmEnabled, logRetentionSettings); + } + return message; + }; + + if (!logRetentionSettings.enabled) { + return renderOrReturnMessage(messages.noLogging); + } + if (logRetentionSettings.enabled && !ilmEnabled) { + return renderOrReturnMessage(messages.ilmDisabled); + } + if ( + logRetentionSettings.enabled && + ilmEnabled && + !logRetentionSettings.retentionPolicy?.isDefault + ) { + return renderOrReturnMessage(messages.customPolicy); + } + if ( + logRetentionSettings.enabled && + ilmEnabled && + logRetentionSettings.retentionPolicy?.isDefault + ) { + return renderOrReturnMessage(messages.defaultPolicy); + } +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.test.tsx new file mode 100644 index 00000000000000..b65ffc04ad7009 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.test.tsx @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import '../../../../../__mocks__/kea.mock'; +import { setMockValues } from '../../../../../__mocks__'; + +import React from 'react'; +import { shallow } from 'enzyme'; + +import { AnalyticsLogRetentionMessage, ApiLogRetentionMessage, renderLogRetentionDate } from '.'; + +describe('LogRetentionMessaging', () => { + const LOG_RETENTION = { + analytics: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + api: { + disabledAt: null, + enabled: true, + retentionPolicy: { isDefault: true, minAgeDays: 180 }, + }, + }; + + describe('renderLogRetentionDate', () => { + it('renders a formatted date', () => { + expect(renderLogRetentionDate('Thu, 05 Nov 2020 18:57:28 +0000')).toEqual('November 5, 2020'); + }); + }); + + describe('AnalyticsLogRetentionMessage', () => { + it('renders', () => { + setMockValues({ + ilmEnabled: true, + logRetention: LOG_RETENTION, + }); + const wrapper = shallow(); + expect(wrapper.text()).toEqual('Your analytics are being stored for at least 180 days.'); + }); + + it('renders nothing if logRetention is null', () => { + setMockValues({ + ilmEnabled: true, + logRetention: null, + }); + const wrapper = shallow(); + expect(wrapper.isEmptyRender()).toEqual(true); + }); + }); + + describe('ApiLogRetentionMessage', () => { + it('renders', () => { + setMockValues({ + ilmEnabled: true, + logRetention: LOG_RETENTION, + }); + const wrapper = shallow(); + expect(wrapper.text()).toEqual('Your logs are being stored for at least 180 days.'); + }); + + it('renders nothing if logRetention is null', () => { + setMockValues({ + ilmEnabled: true, + logRetention: null, + }); + const wrapper = shallow(); + expect(wrapper.isEmptyRender()).toEqual(true); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.tsx new file mode 100644 index 00000000000000..9fe2e8dc72ed65 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/index.tsx @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React from 'react'; + +import { useValues } from 'kea'; +import moment from 'moment'; + +import { AppLogic } from '../../../../app_logic'; +import { LogRetentionLogic } from '../log_retention_logic'; +import { ELogRetentionOptions } from '../types'; + +import { determineTooltipContent } from './determine_tooltip_content'; +import { ANALYTICS_MESSAGES, API_MESSAGES } from './constants'; + +export const renderLogRetentionDate = (dateString: string) => + moment(dateString).format('MMMM D, YYYY'); + +export const AnalyticsLogRetentionMessage: React.FC = () => { + const { ilmEnabled } = useValues(AppLogic); + const { logRetention } = useValues(LogRetentionLogic); + if (!logRetention) return null; + + return ( + <> + {determineTooltipContent( + ANALYTICS_MESSAGES, + ilmEnabled, + logRetention[ELogRetentionOptions.Analytics] + )} + + ); +}; + +export const ApiLogRetentionMessage: React.FC = () => { + const { ilmEnabled } = useValues(AppLogic); + const { logRetention } = useValues(LogRetentionLogic); + if (!logRetention) return null; + + return ( + <>{determineTooltipContent(API_MESSAGES, ilmEnabled, logRetention[ELogRetentionOptions.API])} + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/types.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/types.ts new file mode 100644 index 00000000000000..a9546343d9aa70 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/log_retention/messaging/types.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ILogRetentionSettings } from '../types'; + +export type TMessageStringOrFunction = + | string + | ((ilmEnabled: boolean, logRetentionSettings: ILogRetentionSettings) => string); + +export interface ILogRetentionMessages { + noLogging: TMessageStringOrFunction; + ilmDisabled: TMessageStringOrFunction; + customPolicy: TMessageStringOrFunction; + defaultPolicy: TMessageStringOrFunction; +} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx index 13079bb380f135..7bd3683919bc14 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/settings/settings.tsx @@ -5,11 +5,17 @@ */ import React from 'react'; - -import { EuiPageHeader, EuiPageHeaderSection, EuiPageContentBody, EuiTitle } from '@elastic/eui'; +import { + EuiPageHeader, + EuiPageHeaderSection, + EuiPageContent, + EuiPageContentBody, + EuiTitle, +} from '@elastic/eui'; import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; import { FlashMessages } from '../../../shared/flash_messages'; +import { LogRetentionPanel } from './log_retention/log_retention_panel'; import { SETTINGS_TITLE } from './'; @@ -24,9 +30,12 @@ export const Settings: React.FC = () => { - - - + + + + + + ); };