From d37d8ae85ce42b06aefc6398fda13d88119612b7 Mon Sep 17 00:00:00 2001
From: Elena Stoeva <59341489+ElenaStoeva@users.noreply.github.com>
Date: Fri, 29 Sep 2023 16:48:37 +0100
Subject: [PATCH] [serverless] Add Advanced Settings page (#167383)
## Summary
This PR adds a Settings application component for rendering the Advanced
Settings page in serverless.
### How to test:
1. Start Es with `yarn es serverless` and Kibana with `yarn
serverless-{es/oblt/security}`
2. Go to Management -> Advanced Settings
3. Verify that the settings can be changed and saved.
### Advanced Settings page:
### Added an Advanced Settings card to the Management landing page:
---------
Co-authored-by: Clint Andrew Hall
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Clint Andrew Hall
---
.github/CODEOWNERS | 1 +
package.json | 1 +
.../cards_navigation/src/consts.tsx | 9 ++
.../settings/application/README.md | 13 ++
.../settings/application/application.tsx | 38 ++++++
.../settings/application/hooks/index.ts | 10 ++
.../settings/application/hooks/use_fields.ts | 22 ++++
.../application/hooks/use_settings.ts | 35 +++++
.../settings/application/index.tsx | 34 +++++
.../settings/application/jest.config.js | 13 ++
.../settings/application/kibana.jsonc | 5 +
.../settings/application/package.json | 6 +
.../settings/application/services.tsx | 121 ++++++++++++++++++
.../settings/application/tsconfig.json | 26 ++++
.../components/field_input/services.tsx | 2 +-
.../settings/components/field_input/types.ts | 4 +-
.../components/field_row/services.tsx | 4 +-
.../settings/components/form/services.tsx | 29 ++---
.../settings/components/form/types.ts | 10 +-
.../settings/utilities/mocks/settings.mock.ts | 39 +++---
.../public/{plugin.ts => plugin.tsx} | 47 ++++++-
src/plugins/management/tsconfig.json | 5 +-
tsconfig.base.json | 2 +
.../translations/translations/fr-FR.json | 3 -
.../translations/translations/ja-JP.json | 3 -
.../translations/translations/zh-CN.json | 3 -
.../test_serverless/functional/config.base.ts | 2 +-
.../common/management/advanced_settings.ts | 44 +++++--
.../observability/advanced_settings.ts | 19 ++-
.../test_suites/search/advanced_settings.ts | 19 ++-
.../test_suites/security/advanced_settings.ts | 19 ++-
x-pack/test_serverless/tsconfig.json | 1 +
yarn.lock | 4 +
33 files changed, 510 insertions(+), 83 deletions(-)
create mode 100644 packages/kbn-management/settings/application/README.md
create mode 100644 packages/kbn-management/settings/application/application.tsx
create mode 100644 packages/kbn-management/settings/application/hooks/index.ts
create mode 100644 packages/kbn-management/settings/application/hooks/use_fields.ts
create mode 100644 packages/kbn-management/settings/application/hooks/use_settings.ts
create mode 100644 packages/kbn-management/settings/application/index.tsx
create mode 100644 packages/kbn-management/settings/application/jest.config.js
create mode 100644 packages/kbn-management/settings/application/kibana.jsonc
create mode 100644 packages/kbn-management/settings/application/package.json
create mode 100644 packages/kbn-management/settings/application/services.tsx
create mode 100644 packages/kbn-management/settings/application/tsconfig.json
rename src/plugins/management/public/{plugin.ts => plugin.tsx} (76%)
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 908ade51321b..c0ba6f69d592 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -485,6 +485,7 @@ packages/kbn-managed-vscode-config @elastic/kibana-operations
packages/kbn-managed-vscode-config-cli @elastic/kibana-operations
packages/kbn-management/cards_navigation @elastic/platform-deployment-management
src/plugins/management @elastic/platform-deployment-management
+packages/kbn-management/settings/application @elastic/platform-deployment-management
packages/kbn-management/settings/components/field_category @elastic/platform-deployment-management
packages/kbn-management/settings/components/field_input @elastic/platform-deployment-management
packages/kbn-management/settings/components/field_row @elastic/platform-deployment-management
diff --git a/package.json b/package.json
index 6ea5ef3486ef..5e9da822b1fc 100644
--- a/package.json
+++ b/package.json
@@ -507,6 +507,7 @@
"@kbn/logstash-plugin": "link:x-pack/plugins/logstash",
"@kbn/management-cards-navigation": "link:packages/kbn-management/cards_navigation",
"@kbn/management-plugin": "link:src/plugins/management",
+ "@kbn/management-settings-application": "link:packages/kbn-management/settings/application",
"@kbn/management-settings-components-field-category": "link:packages/kbn-management/settings/components/field_category",
"@kbn/management-settings-components-field-input": "link:packages/kbn-management/settings/components/field_input",
"@kbn/management-settings-components-field-row": "link:packages/kbn-management/settings/components/field_row",
diff --git a/packages/kbn-management/cards_navigation/src/consts.tsx b/packages/kbn-management/cards_navigation/src/consts.tsx
index 8a26334eae8c..45deab542b0a 100644
--- a/packages/kbn-management/cards_navigation/src/consts.tsx
+++ b/packages/kbn-management/cards_navigation/src/consts.tsx
@@ -27,6 +27,7 @@ export enum appIds {
CONNECTORS = 'triggersActionsConnectors',
RULES = 'triggersActions',
MAINTENANCE_WINDOWS = 'maintenanceWindows',
+ SERVERLESS_SETTINGS = 'settings',
}
// Create new type that is a union of all the appId values
@@ -155,6 +156,14 @@ export const appDefinitions: Record = {
}),
icon: ,
},
+
+ [appIds.SERVERLESS_SETTINGS]: {
+ category: appCategories.OTHER,
+ description: i18n.translate('management.landing.withCardNavigation.settingsDescription', {
+ defaultMessage: 'Control project behavior, such as date display and default sorting.',
+ }),
+ icon: ,
+ },
};
// Compose a list of app ids that belong to a given category
diff --git a/packages/kbn-management/settings/application/README.md b/packages/kbn-management/settings/application/README.md
new file mode 100644
index 000000000000..ebbc45c1707b
--- /dev/null
+++ b/packages/kbn-management/settings/application/README.md
@@ -0,0 +1,13 @@
+---
+id: management/settings/application
+slug: /management/settings/application
+title: Management Settings Application
+description: A package containing a component for rendering the Settings page.
+tags: ['management', 'settings']
+date: 2023-09-27
+---
+
+## Description
+
+This package contains a component for rendering the Settings page that contains a `Form` component for displaying and changing the available uiSettings.
+The settings application also handles the logic for filtering out the uiSettings that are not in the allowlist.
diff --git a/packages/kbn-management/settings/application/application.tsx b/packages/kbn-management/settings/application/application.tsx
new file mode 100644
index 000000000000..603f5f0f36f4
--- /dev/null
+++ b/packages/kbn-management/settings/application/application.tsx
@@ -0,0 +1,38 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+import React from 'react';
+
+import { Form } from '@kbn/management-settings-components-form';
+
+import { EuiText, EuiSpacer } from '@elastic/eui';
+import { i18n as i18nLib } from '@kbn/i18n';
+import { useFields } from './hooks/use_fields';
+
+const title = i18nLib.translate('management.settings.advancedSettingsLabel', {
+ defaultMessage: 'Advanced Settings',
+});
+
+export const DATA_TEST_SUBJ_SETTINGS_TITLE = 'managementSettingsTitle';
+
+/**
+ * Component for displaying a {@link Form} component.
+ * @param props The {@link SettingsApplicationProps} for the {@link SettingsApplication} component.
+ */
+export const SettingsApplication = () => {
+ const fields = useFields();
+
+ return (
+
+
+ {title}
+
+
+
+
+ );
+};
diff --git a/packages/kbn-management/settings/application/hooks/index.ts b/packages/kbn-management/settings/application/hooks/index.ts
new file mode 100644
index 000000000000..2b8e1b6ad102
--- /dev/null
+++ b/packages/kbn-management/settings/application/hooks/index.ts
@@ -0,0 +1,10 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+export { useFields } from './use_fields';
+export { useSettings } from './use_settings';
diff --git a/packages/kbn-management/settings/application/hooks/use_fields.ts b/packages/kbn-management/settings/application/hooks/use_fields.ts
new file mode 100644
index 000000000000..551582594107
--- /dev/null
+++ b/packages/kbn-management/settings/application/hooks/use_fields.ts
@@ -0,0 +1,22 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { getFieldDefinitions } from '@kbn/management-settings-field-definition';
+import { FieldDefinition, SettingType } from '@kbn/management-settings-types';
+import { useServices } from '../services';
+import { useSettings } from './use_settings';
+
+/**
+ * React hook which retrieves settings and returns an observed collection of
+ * {@link FieldDefinition} objects derived from those settings.
+ */
+export const useFields = (): Array> => {
+ const { isCustomSetting: isCustom, isOverriddenSetting: isOverridden } = useServices();
+ const settings = useSettings();
+ return getFieldDefinitions(settings, { isCustom, isOverridden });
+};
diff --git a/packages/kbn-management/settings/application/hooks/use_settings.ts b/packages/kbn-management/settings/application/hooks/use_settings.ts
new file mode 100644
index 000000000000..e00cbad9ebaf
--- /dev/null
+++ b/packages/kbn-management/settings/application/hooks/use_settings.ts
@@ -0,0 +1,35 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { useState } from 'react';
+import useEffectOnce from 'react-use/lib/useEffectOnce';
+
+import { useServices } from '../services';
+
+/**
+ * React hook which retrieves settings from a particular {@link IUiSettingsClient},
+ * normalizes them to a predictable format, {@link UiSettingMetadata}, and returns
+ * them as an observed collection.
+ */
+export const useSettings = () => {
+ const { getAllowlistedSettings, subscribeToUpdates } = useServices();
+
+ const [settings, setSettings] = useState(getAllowlistedSettings());
+
+ useEffectOnce(() => {
+ const subscription = subscribeToUpdates(() => {
+ setSettings(getAllowlistedSettings());
+ });
+
+ return () => {
+ subscription.unsubscribe();
+ };
+ });
+
+ return settings;
+};
diff --git a/packages/kbn-management/settings/application/index.tsx b/packages/kbn-management/settings/application/index.tsx
new file mode 100644
index 000000000000..0f491a5d8cff
--- /dev/null
+++ b/packages/kbn-management/settings/application/index.tsx
@@ -0,0 +1,34 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React from 'react';
+import { SettingsApplication } from './application';
+import {
+ SettingsApplicationKibanaDependencies,
+ SettingsApplicationKibanaProvider,
+} from './services';
+
+export { SettingsApplication } from './application';
+export {
+ SettingsApplicationProvider,
+ SettingsApplicationKibanaProvider,
+ type SettingsApplicationServices,
+ type SettingsApplicationKibanaDependencies,
+} from './services';
+
+export const KibanaSettingsApplication = ({
+ docLinks,
+ i18n,
+ notifications,
+ settings,
+ theme,
+}: SettingsApplicationKibanaDependencies) => (
+
+
+
+);
diff --git a/packages/kbn-management/settings/application/jest.config.js b/packages/kbn-management/settings/application/jest.config.js
new file mode 100644
index 000000000000..aa4230234635
--- /dev/null
+++ b/packages/kbn-management/settings/application/jest.config.js
@@ -0,0 +1,13 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+module.exports = {
+ preset: '@kbn/test',
+ rootDir: '../../../..',
+ roots: ['/packages/kbn-management/settings/application'],
+};
diff --git a/packages/kbn-management/settings/application/kibana.jsonc b/packages/kbn-management/settings/application/kibana.jsonc
new file mode 100644
index 000000000000..ab9c47c87f60
--- /dev/null
+++ b/packages/kbn-management/settings/application/kibana.jsonc
@@ -0,0 +1,5 @@
+{
+ "type": "shared-common",
+ "id": "@kbn/management-settings-application",
+ "owner": "@elastic/platform-deployment-management"
+}
diff --git a/packages/kbn-management/settings/application/package.json b/packages/kbn-management/settings/application/package.json
new file mode 100644
index 000000000000..f66c66a6269f
--- /dev/null
+++ b/packages/kbn-management/settings/application/package.json
@@ -0,0 +1,6 @@
+{
+ "name": "@kbn/management-settings-application",
+ "private": true,
+ "version": "1.0.0",
+ "license": "SSPL-1.0 OR Elastic License 2.0"
+}
\ No newline at end of file
diff --git a/packages/kbn-management/settings/application/services.tsx b/packages/kbn-management/settings/application/services.tsx
new file mode 100644
index 000000000000..b88e0787769e
--- /dev/null
+++ b/packages/kbn-management/settings/application/services.tsx
@@ -0,0 +1,121 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import React, { FC, useContext } from 'react';
+
+import {
+ FormProvider,
+ FormKibanaProvider,
+ type FormKibanaDependencies,
+ type FormServices,
+} from '@kbn/management-settings-components-form';
+import { UiSettingMetadata } from '@kbn/management-settings-types';
+import { IUiSettingsClient } from '@kbn/core-ui-settings-browser';
+import { normalizeSettings } from '@kbn/management-settings-utilities';
+import { Subscription } from 'rxjs';
+
+export interface Services {
+ getAllowlistedSettings: () => Record;
+ subscribeToUpdates: (fn: () => void) => Subscription;
+ isCustomSetting: (key: string) => boolean;
+ isOverriddenSetting: (key: string) => boolean;
+}
+
+export type SettingsApplicationServices = Services & FormServices;
+
+export interface KibanaDependencies {
+ settings: {
+ client: Pick;
+ };
+}
+
+export type SettingsApplicationKibanaDependencies = KibanaDependencies & FormKibanaDependencies;
+
+const SettingsApplicationContext = React.createContext(null);
+
+/**
+ * A Context Provider that provides services to the component and its dependencies.
+ */
+export const SettingsApplicationProvider: FC = ({
+ children,
+ ...services
+}) => {
+ // Destructure the services to avoid a type-widening inclusion of unrelated services.
+ const {
+ saveChanges,
+ showError,
+ showReloadPagePrompt,
+ links,
+ showDanger,
+ getAllowlistedSettings,
+ subscribeToUpdates,
+ isCustomSetting,
+ isOverriddenSetting,
+ } = services;
+
+ return (
+
+
+ {children}
+
+
+ );
+};
+
+/**
+ * Kibana-specific Provider that maps dependencies to services.
+ */
+export const SettingsApplicationKibanaProvider: FC = ({
+ children,
+ ...dependencies
+}) => {
+ const { docLinks, notifications, theme, i18n, settings } = dependencies;
+ const { client } = settings;
+
+ const getAllowlistedSettings = () => {
+ const rawSettings = Object.fromEntries(
+ Object.entries(client.getAll()).filter(
+ ([settingId, settingDef]) => !settingDef.readonly && !client.isCustom(settingId)
+ )
+ );
+
+ return normalizeSettings(rawSettings);
+ };
+
+ const services: Services = {
+ getAllowlistedSettings,
+ isCustomSetting: (key: string) => client.isCustom(key),
+ isOverriddenSetting: (key: string) => client.isOverridden(key),
+ subscribeToUpdates: (fn: () => void) => client.getUpdate$().subscribe(fn),
+ };
+
+ return (
+
+
+ {children}
+
+
+ );
+};
+
+/**
+ * React hook for accessing pre-wired services.
+ */
+export const useServices = () => {
+ const context = useContext(SettingsApplicationContext);
+
+ if (!context) {
+ throw new Error(
+ 'SettingsApplicationContext is missing. Ensure your component or React root is wrapped with SettingsApplicationProvider.'
+ );
+ }
+
+ return context;
+};
diff --git a/packages/kbn-management/settings/application/tsconfig.json b/packages/kbn-management/settings/application/tsconfig.json
new file mode 100644
index 000000000000..3893085e710e
--- /dev/null
+++ b/packages/kbn-management/settings/application/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "extends": "../../../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "target/types",
+ "types": [
+ "jest",
+ "node",
+ "react"
+ ]
+ },
+ "include": [
+ "**/*.ts",
+ "**/*.tsx",
+ ],
+ "exclude": [
+ "target/**/*"
+ ],
+ "kbn_references": [
+ "@kbn/core-ui-settings-browser",
+ "@kbn/management-settings-types",
+ "@kbn/management-settings-field-definition",
+ "@kbn/management-settings-utilities",
+ "@kbn/management-settings-components-form",
+ "@kbn/i18n",
+ ]
+}
diff --git a/packages/kbn-management/settings/components/field_input/services.tsx b/packages/kbn-management/settings/components/field_input/services.tsx
index b76c9b7a9a6a..95a6474f89b5 100644
--- a/packages/kbn-management/settings/components/field_input/services.tsx
+++ b/packages/kbn-management/settings/components/field_input/services.tsx
@@ -27,7 +27,7 @@ export const FieldInputProvider: FC = ({ children, ...servic
*/
export const FieldInputKibanaProvider: FC = ({
children,
- toasts,
+ notifications: { toasts },
}) => {
return (
;
+ notifications: {
+ toasts: Pick;
+ };
}
/**
diff --git a/packages/kbn-management/settings/components/field_row/services.tsx b/packages/kbn-management/settings/components/field_row/services.tsx
index e138307979db..10963041837e 100644
--- a/packages/kbn-management/settings/components/field_row/services.tsx
+++ b/packages/kbn-management/settings/components/field_row/services.tsx
@@ -44,7 +44,7 @@ export const FieldRowProvider = ({ children, ...services }: FieldRowProviderProp
export const FieldRowKibanaProvider: FC = ({
children,
docLinks,
- toasts,
+ notifications,
}) => {
return (
= ({
links: docLinks.links.management,
}}
>
- {children}
+ {children}
);
};
diff --git a/packages/kbn-management/settings/components/form/services.tsx b/packages/kbn-management/settings/components/form/services.tsx
index 73100c1729da..e0a48807b351 100644
--- a/packages/kbn-management/settings/components/form/services.tsx
+++ b/packages/kbn-management/settings/components/form/services.tsx
@@ -7,7 +7,6 @@
*/
import React, { FC, useContext } from 'react';
-import { UnsavedFieldChange } from '@kbn/management-settings-types';
import {
FieldCategoryKibanaProvider,
@@ -42,22 +41,22 @@ export const FormProvider = ({ children, ...services }: FormProviderProps) => {
* Kibana-specific Provider that maps Kibana plugins and services to a {@link FormProvider}.
*/
export const FormKibanaProvider: FC = ({ children, ...deps }) => {
- const { settings, toasts, docLinks, theme, i18nStart } = deps;
+ const { settings, notifications, docLinks, theme, i18n } = deps;
+
+ const services: Services = {
+ saveChanges: (changes) => {
+ const arr = Object.entries(changes).map(([key, value]) =>
+ settings.client.set(key, value.unsavedValue)
+ );
+ return Promise.all(arr);
+ },
+ showError: (message: string) => notifications.toasts.addDanger(message),
+ showReloadPagePrompt: () => notifications.toasts.add(reloadPageToast(theme, i18n)),
+ };
return (
- ) => {
- const arr = Object.entries(changes).map(([key, value]) =>
- settings.client.set(key, value.unsavedValue)
- );
- return Promise.all(arr);
- },
- showError: (message: string) => toasts.addDanger(message),
- showReloadPagePrompt: () => toasts.add(reloadPageToast(theme, i18nStart)),
- }}
- >
-
+
+
{children}
diff --git a/packages/kbn-management/settings/components/form/types.ts b/packages/kbn-management/settings/components/form/types.ts
index 155420f5effe..257c64cc02a7 100644
--- a/packages/kbn-management/settings/components/form/types.ts
+++ b/packages/kbn-management/settings/components/form/types.ts
@@ -11,7 +11,7 @@ import type {
FieldRowServices,
} from '@kbn/management-settings-components-field-row';
import { UnsavedFieldChange } from '@kbn/management-settings-types';
-import { SettingsStart } from '@kbn/core-ui-settings-browser';
+import { IUiSettingsClient } from '@kbn/core-ui-settings-browser';
import { I18nStart } from '@kbn/core-i18n-browser';
import { ThemeServiceStart } from '@kbn/core-theme-browser';
import { ToastsStart } from '@kbn/core-notifications-browser';
@@ -36,12 +36,14 @@ export type FormServices = FieldRowServices & Services;
*/
interface KibanaDependencies {
settings: {
- client: SettingsStart['client'];
+ client: Pick;
};
theme: ThemeServiceStart;
- i18nStart: I18nStart;
+ i18n: I18nStart;
/** The portion of the {@link ToastsStart} contract used by this component. */
- toasts: Pick;
+ notifications: {
+ toasts: Pick;
+ };
}
/**
diff --git a/packages/kbn-management/settings/utilities/mocks/settings.mock.ts b/packages/kbn-management/settings/utilities/mocks/settings.mock.ts
index ca2a2892836c..cbab28536346 100644
--- a/packages/kbn-management/settings/utilities/mocks/settings.mock.ts
+++ b/packages/kbn-management/settings/utilities/mocks/settings.mock.ts
@@ -9,7 +9,7 @@
import { KnownTypeToMetadata, SettingType } from '@kbn/management-settings-types';
type Settings = {
- [key in SettingType]: KnownTypeToMetadata;
+ [key in Exclude]: KnownTypeToMetadata;
};
/**
@@ -71,24 +71,25 @@ export const getSettingsMock = (
category: ['dashboard', 'discover'],
...defaults,
},
- json: {
- name: 'json:test:setting',
- description: 'Description for Json test setting',
- type: 'json',
- userValue: null,
- value: '{"foo": "bar"}',
- category: ['dashboard', 'discover'],
- ...defaults,
- },
- markdown: {
- name: 'markdown:test:setting',
- description: 'Description for Markdown test setting',
- type: 'markdown',
- userValue: null,
- value: '',
- category: ['notifications', 'search'],
- ...defaults,
- },
+ // These are notoriously difficult to test, in both Jest and Storybook.
+ // json: {
+ // name: 'json:test:setting',
+ // description: 'Description for Json test setting',
+ // type: 'json',
+ // userValue: null,
+ // value: '{"foo": "bar"}',
+ // category: ['dashboard', 'discover'],
+ // ...defaults,
+ // },
+ // markdown: {
+ // name: 'markdown:test:setting',
+ // description: 'Description for Markdown test setting',
+ // type: 'markdown',
+ // userValue: null,
+ // value: '',
+ // category: ['notifications', 'search'],
+ // ...defaults,
+ // },
select: {
description: 'Description for Select test setting',
name: 'select:test:setting',
diff --git a/src/plugins/management/public/plugin.ts b/src/plugins/management/public/plugin.tsx
similarity index 76%
rename from src/plugins/management/public/plugin.ts
rename to src/plugins/management/public/plugin.tsx
index d4ef130eb4de..e0c65d66d369 100644
--- a/src/plugins/management/public/plugin.ts
+++ b/src/plugins/management/public/plugin.tsx
@@ -6,7 +6,9 @@
* Side Public License, v 1.
*/
-import { i18n } from '@kbn/i18n';
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { i18n as kbnI18n } from '@kbn/i18n';
import { BehaviorSubject } from 'rxjs';
import type { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
import { HomePublicPluginSetup } from '@kbn/home-plugin/public';
@@ -23,6 +25,8 @@ import {
AppNavLinkStatus,
AppDeepLink,
} from '@kbn/core/public';
+import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
+import { withSuspense } from '@kbn/shared-ux-utility';
import { ConfigSchema, ManagementSetup, ManagementStart, NavigationCardsSubject } from './types';
import { MANAGEMENT_APP_ID } from '../common/contants';
@@ -43,6 +47,12 @@ interface ManagementStartDependencies {
serverless?: ServerlessPluginStart;
}
+const LazyKibanaSettingsApplication = React.lazy(async () => ({
+ default: (await import('@kbn/management-settings-application')).KibanaSettingsApplication,
+}));
+
+const KibanaSettingsApplication = withSuspense(LazyKibanaSettingsApplication);
+
export class ManagementPlugin
implements
Plugin<
@@ -99,10 +109,10 @@ export class ManagementPlugin
if (home) {
home.featureCatalogue.register({
id: 'stack-management',
- title: i18n.translate('management.stackManagement.managementLabel', {
+ title: kbnI18n.translate('management.stackManagement.managementLabel', {
defaultMessage: 'Stack Management',
}),
- description: i18n.translate('management.stackManagement.managementDescription', {
+ description: kbnI18n.translate('management.stackManagement.managementDescription', {
defaultMessage: 'Your center console for managing the Elastic Stack.',
}),
icon: 'managementApp',
@@ -115,7 +125,7 @@ export class ManagementPlugin
core.application.register({
id: MANAGEMENT_APP_ID,
- title: i18n.translate('management.stackManagement.title', {
+ title: kbnI18n.translate('management.stackManagement.title', {
defaultMessage: 'Stack Management',
}),
order: 9040,
@@ -152,7 +162,7 @@ export class ManagementPlugin
};
}
- public start(core: CoreStart, _plugins: ManagementStartDependencies): ManagementStart {
+ public start(core: CoreStart, plugins: ManagementStartDependencies): ManagementStart {
this.managementSections.start({ capabilities: core.application.capabilities });
this.hasAnyEnabledApps = getSectionsServiceStartPrivate()
.getSectionsEnabled()
@@ -167,6 +177,33 @@ export class ManagementPlugin
});
}
+ // Register the Settings app only if in serverless, until we integrate the SettingsApplication into the Advanced settings plugin
+ // Otherwise, it will be double registered from the Advanced settings plugin
+ if (plugins.serverless) {
+ const title = kbnI18n.translate('management.settings.settingsLabel', {
+ defaultMessage: 'Advanced Settings',
+ });
+
+ this.managementSections.definedSections.kibana.registerApp({
+ id: 'settings',
+ title,
+ order: 3,
+ async mount({ element, setBreadcrumbs }) {
+ setBreadcrumbs([{ text: title }]);
+
+ ReactDOM.render(
+
+
+ ,
+ element
+ );
+ return () => {
+ ReactDOM.unmountComponentAtNode(element);
+ };
+ },
+ });
+ }
+
return {
setIsSidebarEnabled: (isSidebarEnabled: boolean) =>
this.isSidebarEnabled$.next(isSidebarEnabled),
diff --git a/src/plugins/management/tsconfig.json b/src/plugins/management/tsconfig.json
index 77c3752e7b0c..0f060475796c 100644
--- a/src/plugins/management/tsconfig.json
+++ b/src/plugins/management/tsconfig.json
@@ -26,7 +26,10 @@
"@kbn/config-schema",
"@kbn/core-application-browser",
"@kbn/core-http-browser",
- "@kbn/serverless"
+ "@kbn/serverless",
+ "@kbn/management-settings-application",
+ "@kbn/react-kibana-context-render",
+ "@kbn/shared-ux-utility"
],
"exclude": [
"target/**/*"
diff --git a/tsconfig.base.json b/tsconfig.base.json
index 2ea42b377596..c5bdbcfd4f53 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -964,6 +964,8 @@
"@kbn/management-cards-navigation/*": ["packages/kbn-management/cards_navigation/*"],
"@kbn/management-plugin": ["src/plugins/management"],
"@kbn/management-plugin/*": ["src/plugins/management/*"],
+ "@kbn/management-settings-application": ["packages/kbn-management/settings/application"],
+ "@kbn/management-settings-application/*": ["packages/kbn-management/settings/application/*"],
"@kbn/management-settings-components-field-category": ["packages/kbn-management/settings/components/field_category"],
"@kbn/management-settings-components-field-category/*": ["packages/kbn-management/settings/components/field_category/*"],
"@kbn/management-settings-components-field-input": ["packages/kbn-management/settings/components/field_input"],
diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json
index 427014326ed7..2391c36acc26 100644
--- a/x-pack/plugins/translations/translations/fr-FR.json
+++ b/x-pack/plugins/translations/translations/fr-FR.json
@@ -4738,9 +4738,6 @@
"management.sections.section.title": "Sécurité",
"management.sections.stackTip": "Gérez votre licence et mettez la Suite à niveau.",
"management.sections.stackTitle": "Suite",
- "management.stackManagement.managementDescription": "La console centrale de gestion de la Suite Elastic.",
- "management.stackManagement.managementLabel": "Gestion de la Suite",
- "management.stackManagement.title": "Gestion de la Suite",
"newsfeed.flyoutList.versionTextLabel": "{version}",
"newsfeed.emptyPrompt.noNewsText": "Si votre instance Kibana n'a pas accès à Internet, demandez à votre administrateur de désactiver cette fonctionnalité. Sinon, nous continuerons d'essayer de récupérer les actualités.",
"newsfeed.emptyPrompt.noNewsTitle": "Pas d'actualités ?",
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index b396434aa2f3..ebd523dace81 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -4754,9 +4754,6 @@
"management.sections.section.title": "セキュリティ",
"management.sections.stackTip": "ライセンスを管理し、スタックをアップグレードします",
"management.sections.stackTitle": "スタック",
- "management.stackManagement.managementDescription": "Elastic Stack の管理を行うセンターコンソールです。",
- "management.stackManagement.managementLabel": "スタック管理",
- "management.stackManagement.title": "スタック管理",
"newsfeed.flyoutList.versionTextLabel": "{version}",
"newsfeed.emptyPrompt.noNewsText": "Kibana インスタンスがインターネットにアクセスできない場合、管理者にこの機能を無効にするように依頼してください。そうでない場合は、ニュースを取り込み続けます。",
"newsfeed.emptyPrompt.noNewsTitle": "ニュースがない場合",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index 85371195ebcb..96adbe87e50d 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -4753,9 +4753,6 @@
"management.sections.section.title": "安全",
"management.sections.stackTip": "管理您的许可并升级 Stack",
"management.sections.stackTitle": "Stack",
- "management.stackManagement.managementDescription": "您用于管理 Elastic Stack 的中心控制台。",
- "management.stackManagement.managementLabel": "Stack Management",
- "management.stackManagement.title": "Stack Management",
"newsfeed.flyoutList.versionTextLabel": "{version}",
"newsfeed.emptyPrompt.noNewsText": "如果您的 Kibana 实例没有 Internet 连接,请让您的管理员禁用此功能。否则,我们将不断尝试获取新闻。",
"newsfeed.emptyPrompt.noNewsTitle": "无新闻?",
diff --git a/x-pack/test_serverless/functional/config.base.ts b/x-pack/test_serverless/functional/config.base.ts
index 3db533e9d930..6f45ac8e2ca8 100644
--- a/x-pack/test_serverless/functional/config.base.ts
+++ b/x-pack/test_serverless/functional/config.base.ts
@@ -72,7 +72,7 @@ export function createTestConfig(options: CreateTestConfigOptions) {
connectors: {
pathname: '/app/management/insightsAndAlerting/triggersActionsConnectors/',
},
- advancedSettings: {
+ settings: {
pathname: '/app/management/kibana/settings',
},
login: {
diff --git a/x-pack/test_serverless/functional/test_suites/common/management/advanced_settings.ts b/x-pack/test_serverless/functional/test_suites/common/management/advanced_settings.ts
index 0ea1e6339772..aad12001ed52 100644
--- a/x-pack/test_serverless/functional/test_suites/common/management/advanced_settings.ts
+++ b/x-pack/test_serverless/functional/test_suites/common/management/advanced_settings.ts
@@ -7,18 +7,37 @@
import expect from '@kbn/expect';
import { ALL_COMMON_SETTINGS } from '@kbn/serverless-common-settings';
+import * as settings from '@kbn/management-settings-ids';
import { FtrProviderContext } from '../../../ftr_provider_context';
+const editorSettings = new Set([
+ settings.BANNERS_TEXT_CONTENT_ID,
+ settings.DATE_FORMAT_SCALED_ID,
+ settings.ML_ANOMALY_DETECTION_RESULTS_TIME_DEFAULTS_ID,
+ settings.NOTIFICATIONS_BANNER_ID,
+ settings.TIMEPICKER_TIME_DEFAULTS_ID,
+ settings.TIMEPICKER_QUICK_RANGES_ID,
+ settings.SECURITY_SOLUTION_REFRESH_INTERVAL_DEFAULTS_ID,
+ settings.SECURITY_SOLUTION_TIME_DEFAULTS_ID,
+ settings.SECURITY_SOLUTION_RULES_TABLE_REFRESH_ID,
+ settings.SECURITY_SOLUTION_IP_REPUTATION_LINKS_ID,
+]);
+export const isEditorFieldSetting = (settingId: string) => editorSettings.has(settingId);
+
export default ({ getPageObjects, getService }: FtrProviderContext) => {
const testSubjects = getService('testSubjects');
- const pageObjects = getPageObjects(['common']);
+ const pageObjects = getPageObjects(['svlCommonPage', 'common']);
const browser = getService('browser');
const retry = getService('retry');
- // Skip until we enable the Advanced settings app in serverless
- describe.skip('Common advanced settings', function () {
+ describe('Common advanced settings', function () {
before(async () => {
- await pageObjects.common.navigateToApp('advancedSettings');
+ await pageObjects.svlCommonPage.login();
+ await pageObjects.common.navigateToApp('settings');
+ });
+
+ after(async () => {
+ await pageObjects.svlCommonPage.forceLogout();
});
it('renders the page', async () => {
@@ -32,13 +51,18 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
describe('renders common settings', () => {
for (const settingId of ALL_COMMON_SETTINGS) {
+ // Code editors don't have their test subjects rendered
+ if (isEditorFieldSetting(settingId)) {
+ continue;
+ }
+ const isColorPickerField =
+ settingId === settings.BANNERS_TEXT_COLOR_ID ||
+ settingId === settings.BANNERS_BACKGROUND_COLOR_ID;
+ const fieldTestSubj =
+ (isColorPickerField ? 'euiColorPickerAnchor ' : '') +
+ 'management-settings-editField-' +
+ settingId;
it('renders ' + settingId + ' edit field', async () => {
- const isColorPickerField =
- settingId === 'banners:textColor' || settingId === 'banners:backgroundColor';
- const fieldTestSubj =
- (isColorPickerField ? 'euiColorPickerAnchor ' : '') +
- 'advancedSetting-editField-' +
- settingId;
expect(await testSubjects.exists(fieldTestSubj)).to.be(true);
});
}
diff --git a/x-pack/test_serverless/functional/test_suites/observability/advanced_settings.ts b/x-pack/test_serverless/functional/test_suites/observability/advanced_settings.ts
index e723b81dbe20..d6f2ef6502f2 100644
--- a/x-pack/test_serverless/functional/test_suites/observability/advanced_settings.ts
+++ b/x-pack/test_serverless/functional/test_suites/observability/advanced_settings.ts
@@ -8,17 +8,22 @@
import expect from '@kbn/expect';
import { OBSERVABILITY_PROJECT_SETTINGS } from '@kbn/serverless-observability-settings';
import { FtrProviderContext } from '../../ftr_provider_context';
+import { isEditorFieldSetting } from '../common/management/advanced_settings';
export default ({ getPageObjects, getService }: FtrProviderContext) => {
const testSubjects = getService('testSubjects');
- const pageObjects = getPageObjects(['common']);
+ const pageObjects = getPageObjects(['svlCommonPage', 'common']);
const browser = getService('browser');
const retry = getService('retry');
- // Skip until we enable the Advanced settings app in serverless
- describe.skip('Observability advanced settings', function () {
+ describe('Observability advanced settings', function () {
before(async () => {
- await pageObjects.common.navigateToApp('advancedSettings');
+ await pageObjects.svlCommonPage.login();
+ await pageObjects.common.navigateToApp('settings');
+ });
+
+ after(async () => {
+ await pageObjects.svlCommonPage.forceLogout();
});
it('renders the page', async () => {
@@ -32,8 +37,12 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
describe('renders observability settings', () => {
for (const settingId of OBSERVABILITY_PROJECT_SETTINGS) {
+ // Code editors don't have their test subjects rendered
+ if (isEditorFieldSetting(settingId)) {
+ continue;
+ }
it('renders ' + settingId + ' edit field', async () => {
- const fieldTestSubj = 'advancedSetting-editField-' + settingId;
+ const fieldTestSubj = 'management-settings-editField-' + settingId;
expect(await testSubjects.exists(fieldTestSubj)).to.be(true);
});
}
diff --git a/x-pack/test_serverless/functional/test_suites/search/advanced_settings.ts b/x-pack/test_serverless/functional/test_suites/search/advanced_settings.ts
index 63b6053589ea..2f2b76b21eda 100644
--- a/x-pack/test_serverless/functional/test_suites/search/advanced_settings.ts
+++ b/x-pack/test_serverless/functional/test_suites/search/advanced_settings.ts
@@ -8,17 +8,22 @@
import expect from '@kbn/expect';
import { SEARCH_PROJECT_SETTINGS } from '@kbn/serverless-search-settings';
import { FtrProviderContext } from '../../ftr_provider_context';
+import { isEditorFieldSetting } from '../common/management/advanced_settings';
export default ({ getPageObjects, getService }: FtrProviderContext) => {
const testSubjects = getService('testSubjects');
- const pageObjects = getPageObjects(['common']);
+ const pageObjects = getPageObjects(['svlCommonPage', 'common']);
const browser = getService('browser');
const retry = getService('retry');
- // Skip until we enable the Advanced settings app in serverless
- describe.skip('Search advanced settings', function () {
+ describe('Search advanced settings', function () {
before(async () => {
- await pageObjects.common.navigateToApp('advancedSettings');
+ await pageObjects.svlCommonPage.login();
+ await pageObjects.common.navigateToApp('settings');
+ });
+
+ after(async () => {
+ await pageObjects.svlCommonPage.forceLogout();
});
it('renders the page', async () => {
@@ -32,8 +37,12 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
describe('renders search settings', () => {
for (const settingId of SEARCH_PROJECT_SETTINGS) {
+ // Code editors don't have their test subjects rendered
+ if (isEditorFieldSetting(settingId)) {
+ continue;
+ }
it('renders ' + settingId + ' edit field', async () => {
- const fieldTestSubj = 'advancedSetting-editField-' + settingId;
+ const fieldTestSubj = 'management-settings-editField-' + settingId;
expect(await testSubjects.exists(fieldTestSubj)).to.be(true);
});
}
diff --git a/x-pack/test_serverless/functional/test_suites/security/advanced_settings.ts b/x-pack/test_serverless/functional/test_suites/security/advanced_settings.ts
index 27fa42549dcc..63e3a8a9a667 100644
--- a/x-pack/test_serverless/functional/test_suites/security/advanced_settings.ts
+++ b/x-pack/test_serverless/functional/test_suites/security/advanced_settings.ts
@@ -8,17 +8,22 @@
import expect from '@kbn/expect';
import { SECURITY_PROJECT_SETTINGS } from '@kbn/serverless-security-settings';
import { FtrProviderContext } from '../../ftr_provider_context';
+import { isEditorFieldSetting } from '../common/management/advanced_settings';
export default ({ getPageObjects, getService }: FtrProviderContext) => {
const testSubjects = getService('testSubjects');
- const pageObjects = getPageObjects(['common']);
+ const pageObjects = getPageObjects(['svlCommonPage', 'common']);
const browser = getService('browser');
const retry = getService('retry');
- // Skip until we enable the Advanced settings app in serverless
- describe.skip('Security advanced settings', function () {
+ describe('Security advanced settings', function () {
before(async () => {
- await pageObjects.common.navigateToApp('advancedSettings');
+ await pageObjects.svlCommonPage.login();
+ await pageObjects.common.navigateToApp('settings');
+ });
+
+ after(async () => {
+ await pageObjects.svlCommonPage.forceLogout();
});
it('renders the page', async () => {
@@ -32,8 +37,12 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
describe('renders security settings', () => {
for (const settingId of SECURITY_PROJECT_SETTINGS) {
+ // Code editors don't have their test subjects rendered
+ if (isEditorFieldSetting(settingId)) {
+ continue;
+ }
it('renders ' + settingId + ' edit field', async () => {
- const fieldTestSubj = 'advancedSetting-editField-' + settingId;
+ const fieldTestSubj = 'management-settings-editField-' + settingId;
expect(await testSubjects.exists(fieldTestSubj)).to.be(true);
});
}
diff --git a/x-pack/test_serverless/tsconfig.json b/x-pack/test_serverless/tsconfig.json
index bf23a1889940..66bef3ea9911 100644
--- a/x-pack/test_serverless/tsconfig.json
+++ b/x-pack/test_serverless/tsconfig.json
@@ -57,5 +57,6 @@
"@kbn/serverless-observability-settings",
"@kbn/serverless-search-settings",
"@kbn/serverless-security-settings",
+ "@kbn/management-settings-ids",
]
}
diff --git a/yarn.lock b/yarn.lock
index d85a677823ca..88a5a21cbdb5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4871,6 +4871,10 @@
version "0.0.0"
uid ""
+"@kbn/management-settings-application@link:packages/kbn-management/settings/application":
+ version "0.0.0"
+ uid ""
+
"@kbn/management-settings-components-field-category@link:packages/kbn-management/settings/components/field_category":
version "0.0.0"
uid ""