From 1f91a9244ffbfb611d41da97e2f88868307e3b1b Mon Sep 17 00:00:00 2001 From: Hannah Mudge Date: Tue, 8 Oct 2024 09:15:33 -0600 Subject: [PATCH] [Presentation Util] Cleanup services (#194201) Closes https://github.com/elastic/kibana/issues/167440 ## Summary This PR refactors the `PresentationUtil` services to no longer use its own `PluginServiceProvider`. In doing this, it removes the `PresentationUtil` context provider, since it is no longer necessary. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> (cherry picked from commit 9f2208db1a83889c76fd2413a0a133a858f4891e) --- .../components/control_panel.test.tsx | 26 ++-- .../internal_dashboard_top_nav.tsx | 11 +- .../dashboard/public/services/mocks.ts | 2 +- .../public/get_table_list.tsx | 3 +- .../event_annotation_listing/public/plugin.ts | 1 - src/plugins/links/public/mocks.ts | 2 +- .../dashboard_picker/dashboard_picker.tsx | 10 +- .../data_view_picker.stories.tsx | 20 +-- .../floating_actions/floating_actions.tsx | 13 +- .../components/labs/environment_switch.tsx | 10 +- .../components/labs/labs_beaker_button.tsx | 10 +- .../public/components/labs/labs_flyout.tsx | 35 +++--- .../labs/project_list_item.stories.tsx | 4 +- .../saved_object_save_modal_dashboard.tsx | 11 +- ..._save_modal_dashboard_selector.stories.tsx | 3 +- src/plugins/presentation_util/public/index.ts | 7 +- src/plugins/presentation_util/public/mocks.ts | 19 +-- .../presentation_util/public/plugin.ts | 12 +- .../capabilities/capabilities.story.ts | 32 ----- .../capabilities/capabilities.stub.ts | 20 --- .../capabilities/capabilities_service.ts | 28 ----- .../public/services/capabilities/types.ts | 15 --- .../content_management.stub.ts | 26 ---- .../content_management_service.ts | 25 ---- .../services/content_management/types.ts | 14 --- .../services/data_views/data_views.story.ts | 30 ----- .../services/data_views/data_views_service.ts | 29 ----- .../public/services/data_views/types.ts | 16 --- .../public/services/index.ts | 12 -- .../public/services/kibana_services.ts | 45 +++++++ .../public/services/labs/labs.story.ts | 64 ---------- .../public/services/labs/labs.stub.ts | 92 -------------- .../public/services/labs/types.ts | 85 ------------- .../public/services/mocks.ts | 43 +++++++ .../public/services/plugin_services.story.ts | 41 ------ .../public/services/plugin_services.stub.ts | 38 ------ .../public/services/plugin_services.ts | 42 ------- ...ervice.ts => presentation_labs_service.ts} | 119 +++++++++++++----- .../public/services/types.ts | 24 ---- .../public/services/ui_actions/types.ts | 14 --- .../services/ui_actions/ui_actions.stub.ts | 20 --- .../services/ui_actions/ui_actions_service.ts | 26 ---- src/plugins/presentation_util/public/types.ts | 11 +- .../utils/get_presentation_capabilities.ts | 28 +++++ .../presentation_util/storybook/decorator.tsx | 15 +-- .../presentation_util/storybook/main.ts | 8 +- .../presentation_util/storybook/preview.tsx | 5 + src/plugins/presentation_util/tsconfig.json | 1 + src/plugins/visualizations/public/mocks.ts | 2 +- .../public/visualize_app/index.tsx | 20 ++- .../utils/get_top_nav_config.tsx | 2 +- .../change_point_detection_root.tsx | 55 ++++---- .../public/hooks/use_aiops_app_context.ts | 2 - x-pack/plugins/canvas/public/application.tsx | 9 +- .../decorators/services_decorator.tsx | 9 +- .../lens/public/app_plugin/mounter.tsx | 39 +++--- .../app_plugin/shared/saved_modal_lazy.tsx | 6 +- .../lens/public/mocks/services_mock.tsx | 2 +- x-pack/plugins/lens/public/plugin.ts | 4 - x-pack/plugins/maps/public/kibana_services.ts | 1 - .../public/routes/map_page/top_nav_config.tsx | 4 +- .../aiops/change_point_detection.tsx | 1 - .../routing/routes/explorer/state_manager.tsx | 43 +++---- .../timeseriesexplorer_page.tsx | 5 +- .../public/application/index.tsx | 74 +++++------ .../slo/public/application.tsx | 77 ++++++------ .../public/apps/synthetics/synthetics_app.tsx | 42 +++---- 67 files changed, 471 insertions(+), 1093 deletions(-) delete mode 100644 src/plugins/presentation_util/public/services/capabilities/capabilities.story.ts delete mode 100644 src/plugins/presentation_util/public/services/capabilities/capabilities.stub.ts delete mode 100644 src/plugins/presentation_util/public/services/capabilities/capabilities_service.ts delete mode 100644 src/plugins/presentation_util/public/services/capabilities/types.ts delete mode 100644 src/plugins/presentation_util/public/services/content_management/content_management.stub.ts delete mode 100644 src/plugins/presentation_util/public/services/content_management/content_management_service.ts delete mode 100644 src/plugins/presentation_util/public/services/content_management/types.ts delete mode 100644 src/plugins/presentation_util/public/services/data_views/data_views.story.ts delete mode 100644 src/plugins/presentation_util/public/services/data_views/data_views_service.ts delete mode 100644 src/plugins/presentation_util/public/services/data_views/types.ts delete mode 100644 src/plugins/presentation_util/public/services/index.ts create mode 100644 src/plugins/presentation_util/public/services/kibana_services.ts delete mode 100644 src/plugins/presentation_util/public/services/labs/labs.story.ts delete mode 100644 src/plugins/presentation_util/public/services/labs/labs.stub.ts delete mode 100644 src/plugins/presentation_util/public/services/labs/types.ts create mode 100644 src/plugins/presentation_util/public/services/mocks.ts delete mode 100644 src/plugins/presentation_util/public/services/plugin_services.story.ts delete mode 100644 src/plugins/presentation_util/public/services/plugin_services.stub.ts delete mode 100644 src/plugins/presentation_util/public/services/plugin_services.ts rename src/plugins/presentation_util/public/services/{labs/labs_service.ts => presentation_labs_service.ts} (58%) delete mode 100644 src/plugins/presentation_util/public/services/types.ts delete mode 100644 src/plugins/presentation_util/public/services/ui_actions/types.ts delete mode 100644 src/plugins/presentation_util/public/services/ui_actions/ui_actions.stub.ts delete mode 100644 src/plugins/presentation_util/public/services/ui_actions/ui_actions_service.ts create mode 100644 src/plugins/presentation_util/public/utils/get_presentation_capabilities.ts diff --git a/src/plugins/controls/public/control_group/components/control_panel.test.tsx b/src/plugins/controls/public/control_group/components/control_panel.test.tsx index 116e268afe208..0f6d8b07b324a 100644 --- a/src/plugins/controls/public/control_group/components/control_panel.test.tsx +++ b/src/plugins/controls/public/control_group/components/control_panel.test.tsx @@ -10,12 +10,13 @@ import React, { useImperativeHandle } from 'react'; import { BehaviorSubject } from 'rxjs'; -import { pluginServices as presentationUtilPluginServices } from '@kbn/presentation-util-plugin/public/services'; -import { registry as presentationUtilServicesRegistry } from '@kbn/presentation-util-plugin/public/services/plugin_services.story'; +import { setMockedPresentationUtilServices } from '@kbn/presentation-util-plugin/public/mocks'; +import { uiActionsService } from '@kbn/presentation-util-plugin/public/services/kibana_services'; import { render, waitFor } from '@testing-library/react'; import type { ControlLabelPosition, ControlWidth } from '../../../common'; import { ControlPanel } from './control_panel'; +import { Action } from '@kbn/ui-actions-plugin/public'; describe('render', () => { let mockApi = {}; @@ -27,19 +28,14 @@ describe('render', () => { }) as any; beforeAll(() => { - presentationUtilServicesRegistry.start({}); - presentationUtilPluginServices.setRegistry(presentationUtilServicesRegistry); - presentationUtilPluginServices.getServices().uiActions.getTriggerCompatibleActions = jest - .fn() - .mockImplementation(() => { - return [ - { - isCompatible: jest.fn().mockResolvedValue(true), - id: 'testAction', - MenuItem: () =>
test1
, - }, - ]; - }); + setMockedPresentationUtilServices(); + jest.spyOn(uiActionsService, 'getTriggerCompatibleActions').mockResolvedValue([ + { + isCompatible: jest.fn().mockResolvedValue(true), + id: 'testAction', + MenuItem: () =>
test1
, + }, + ] as unknown as Action[]); }); beforeEach(() => { diff --git a/src/plugins/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx b/src/plugins/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx index bcfcf2e98dddf..bdbb506dfc713 100644 --- a/src/plugins/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx +++ b/src/plugins/dashboard/public/dashboard_top_nav/internal_dashboard_top_nav.tsx @@ -25,11 +25,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { getManagedContentBadge } from '@kbn/managed-content-badge'; import { TopNavMenuBadgeProps, TopNavMenuProps } from '@kbn/navigation-plugin/public'; import { useBatchedPublishingSubjects } from '@kbn/presentation-publishing'; -import { - LazyLabsFlyout, - getContextProvider as getPresentationUtilContextProvider, - withSuspense, -} from '@kbn/presentation-util-plugin/public'; +import { LazyLabsFlyout, withSuspense } from '@kbn/presentation-util-plugin/public'; import { UI_SETTINGS } from '../../common'; import { useDashboardApi } from '../dashboard_api/use_dashboard_api'; @@ -88,7 +84,6 @@ export function InternalDashboardTopNav({ const { setHeaderActionMenu, onAppLeave } = useDashboardMountContext(); const dashboardApi = useDashboardApi(); - const PresentationUtilContextProvider = getPresentationUtilContextProvider(); const [ allDataViews, @@ -405,9 +400,7 @@ export function InternalDashboardTopNav({ onSavedQueryIdChange={setSavedQueryId} /> {viewMode !== 'print' && isLabsEnabled && isLabsShown ? ( - - setIsLabsShown(false)} /> - + setIsLabsShown(false)} /> ) : null} {viewMode === 'edit' ? : null} {showBorderBottom && } diff --git a/src/plugins/dashboard/public/services/mocks.ts b/src/plugins/dashboard/public/services/mocks.ts index 61132c2fc264e..255098ecd8196 100644 --- a/src/plugins/dashboard/public/services/mocks.ts +++ b/src/plugins/dashboard/public/services/mocks.ts @@ -60,7 +60,7 @@ export const setStubKibanaServices = () => { navigation: navigationPluginMock.createStartContract(), noDataPage: noDataPagePublicMock.createStart(), observabilityAIAssistant: observabilityAIAssistantPluginMock.createStartContract(), - presentationUtil: presentationUtilPluginMock.createStartContract(core), + presentationUtil: presentationUtilPluginMock.createStartContract(), savedObjectsManagement: savedObjectsManagementPluginMock.createStartContract(), savedObjectsTaggingOss: savedObjectTaggingOssPluginMock.createStart(), screenshotMode: screenshotModePluginMock.createStartContract(), diff --git a/src/plugins/event_annotation_listing/public/get_table_list.tsx b/src/plugins/event_annotation_listing/public/get_table_list.tsx index da150bf63bac5..45ed046340fac 100644 --- a/src/plugins/event_annotation_listing/public/get_table_list.tsx +++ b/src/plugins/event_annotation_listing/public/get_table_list.tsx @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React, { FC } from 'react'; +import React from 'react'; import { FormattedRelative } from '@kbn/i18n-react'; import { TableListViewKibanaProvider } from '@kbn/content-management-table-list-view-table'; import { type TableListTabParentProps } from '@kbn/content-management-tabbed-table-list-view'; @@ -25,7 +25,6 @@ export interface EventAnnotationListingPageServices { core: CoreStart; savedObjectsTagging: SavedObjectsTaggingApi; eventAnnotationService: EventAnnotationServiceType; - PresentationUtilContextProvider: FC; dataViews: DataView[]; createDataView: (spec: DataViewSpec) => Promise; queryInputServices: QueryInputServices; diff --git a/src/plugins/event_annotation_listing/public/plugin.ts b/src/plugins/event_annotation_listing/public/plugin.ts index 4f8f9454e4c33..d32a26f19022c 100644 --- a/src/plugins/event_annotation_listing/public/plugin.ts +++ b/src/plugins/event_annotation_listing/public/plugin.ts @@ -74,7 +74,6 @@ export class EventAnnotationListingPlugin LensEmbeddableComponent: pluginsStart.lens.EmbeddableComponent, savedObjectsTagging: pluginsStart.savedObjectsTagging, eventAnnotationService, - PresentationUtilContextProvider: pluginsStart.presentationUtil.ContextProvider, dataViews, createDataView: pluginsStart.dataViews.create.bind(pluginsStart.dataViews), sessionService: pluginsStart.data.search.session, diff --git a/src/plugins/links/public/mocks.ts b/src/plugins/links/public/mocks.ts index 21e900339b41d..dc4f5d57d479f 100644 --- a/src/plugins/links/public/mocks.ts +++ b/src/plugins/links/public/mocks.ts @@ -40,7 +40,7 @@ export const setStubKibanaServices = () => { dashboard: dashboardPluginMock.createStartContract(), embeddable: embeddablePluginMock.createStartContract(), contentManagement: contentManagementMock.createStartContract(), - presentationUtil: presentationUtilPluginMock.createStartContract(core), + presentationUtil: presentationUtilPluginMock.createStartContract(), uiActions: uiActionsPluginMock.createStartContract(), }); }; diff --git a/src/plugins/presentation_util/public/components/dashboard_picker/dashboard_picker.tsx b/src/plugins/presentation_util/public/components/dashboard_picker/dashboard_picker.tsx index aaa9dc957e491..1f1f494b2d531 100644 --- a/src/plugins/presentation_util/public/components/dashboard_picker/dashboard_picker.tsx +++ b/src/plugins/presentation_util/public/components/dashboard_picker/dashboard_picker.tsx @@ -24,7 +24,7 @@ import { i18n } from '@kbn/i18n'; import { ToolbarButton } from '@kbn/shared-ux-button-toolbar'; import { SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common'; -import { pluginServices } from '../../services'; +import { contentManagementService } from '../../services/kibana_services'; export interface DashboardPickerProps { onChange: (dashboard: { name: string; id: string } | null) => void; @@ -53,10 +53,6 @@ export function DashboardPicker({ isDisabled, onChange, idsToOmit }: DashboardPi const [selectedDashboard, setSelectedDashboard] = useState(null); - const { - contentManagement: { client: cmClient }, - } = pluginServices.getServices(); - /** * Debounce the query to avoid many calls to content management. */ @@ -77,7 +73,7 @@ export function DashboardPicker({ isDisabled, onChange, idsToOmit }: DashboardPi (async () => { setIsLoading(true); - const response = await cmClient.mSearch({ + const response = await contentManagementService.client.mSearch({ contentTypes: [{ contentTypeId: 'dashboard' }], query: { text: debouncedQuery ? `${debouncedQuery}*` : undefined, @@ -95,7 +91,7 @@ export function DashboardPicker({ isDisabled, onChange, idsToOmit }: DashboardPi return () => { canceled = true; }; - }, [debouncedQuery, cmClient]); + }, [debouncedQuery]); /** * Format items with dashboard hits and selected option diff --git a/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.stories.tsx b/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.stories.tsx index 756813b7e201f..2e3a6140365de 100644 --- a/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.stories.tsx +++ b/src/plugins/presentation_util/public/components/data_view_picker/data_view_picker.stories.tsx @@ -9,12 +9,10 @@ import React, { useState } from 'react'; -import useMount from 'react-use/lib/useMount'; import { DataView, DataViewListItem } from '@kbn/data-views-plugin/common'; +import useMount from 'react-use/lib/useMount'; import { DataViewPicker } from './data_view_picker'; -import { injectStorybookDataView } from '../../services/data_views/data_views.story'; -import { storybookFlightsDataView } from '../../mocks'; -import { pluginServices, registry, StorybookParams } from '../../services/plugin_services.story'; +import { dataViewsService } from '../../services/kibana_services'; export default { component: DataViewPicker, @@ -22,27 +20,19 @@ export default { argTypes: {}, }; -injectStorybookDataView(storybookFlightsDataView); - -export function Example({}: {} & StorybookParams) { - pluginServices.setRegistry(registry.start({})); - - const { - dataViews: { getIdsWithTitle, get }, - } = pluginServices.getServices(); - +export function Example() { const [dataViews, setDataViews] = useState(); const [dataView, setDataView] = useState(undefined); useMount(() => { (async () => { - const listItems = await getIdsWithTitle(); + const listItems = await dataViewsService.getIdsWithTitle(); setDataViews(listItems); })(); }); const onChange = (newId: string) => { - get(newId).then((newDataView) => { + dataViewsService.get(newId).then((newDataView) => { setDataView(newDataView); }); }; diff --git a/src/plugins/presentation_util/public/components/floating_actions/floating_actions.tsx b/src/plugins/presentation_util/public/components/floating_actions/floating_actions.tsx index 8eb9ff4f2cef8..3c03e65714908 100644 --- a/src/plugins/presentation_util/public/components/floating_actions/floating_actions.tsx +++ b/src/plugins/presentation_util/public/components/floating_actions/floating_actions.tsx @@ -12,15 +12,15 @@ import React, { FC, ReactElement, useEffect, useState } from 'react'; import { v4 } from 'uuid'; import { - panelHoverTrigger, PANEL_HOVER_TRIGGER, + panelHoverTrigger, type EmbeddableInput, type ViewMode, } from '@kbn/embeddable-plugin/public'; import { apiHasUniqueId } from '@kbn/presentation-publishing'; import { Action } from '@kbn/ui-actions-plugin/public'; -import { pluginServices } from '../../services'; +import { uiActionsService } from '../../services/kibana_services'; import './floating_actions.scss'; export interface FloatingActionsProps { @@ -41,9 +41,6 @@ export const FloatingActions: FC = ({ className = '', disabledActions, }) => { - const { - uiActions: { getTriggerCompatibleActions }, - } = pluginServices.getServices(); const [floatingActions, setFloatingActions] = useState(undefined); useEffect(() => { @@ -55,7 +52,9 @@ export const FloatingActions: FC = ({ embeddable: api, trigger: panelHoverTrigger, }; - const actions = (await getTriggerCompatibleActions(PANEL_HOVER_TRIGGER, context)) + const actions = ( + await uiActionsService.getTriggerCompatibleActions(PANEL_HOVER_TRIGGER, context) + ) .filter((action): action is Action & { MenuItem: React.FC<{ context: unknown }> } => { return action.MenuItem !== undefined && (disabledActions ?? []).indexOf(action.id) === -1; }) @@ -82,7 +81,7 @@ export const FloatingActions: FC = ({ }; getActions(); - }, [api, getTriggerCompatibleActions, viewMode, disabledActions]); + }, [api, viewMode, disabledActions]); return (
diff --git a/src/plugins/presentation_util/public/components/labs/environment_switch.tsx b/src/plugins/presentation_util/public/components/labs/environment_switch.tsx index 83ac536368787..94e71fe432fc5 100644 --- a/src/plugins/presentation_util/public/components/labs/environment_switch.tsx +++ b/src/plugins/presentation_util/public/components/labs/environment_switch.tsx @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React from 'react'; +import React, { useMemo } from 'react'; import { EuiFlexGroup, EuiFlexItem, @@ -17,9 +17,9 @@ import { EuiScreenReaderOnly, } from '@elastic/eui'; -import { pluginServices } from '../../services'; import { EnvironmentName } from '../../../common/labs'; import { LabsStrings } from '../../i18n'; +import { getPresentationCapabilities } from '../../utils/get_presentation_capabilities'; const { Switch: strings } = LabsStrings.Components; @@ -37,9 +37,11 @@ export interface Props { } export const EnvironmentSwitch = ({ env, isChecked, onChange, name }: Props) => { - const { capabilities } = pluginServices.getHooks(); + const { canSetAdvancedSettings } = useMemo(() => { + return getPresentationCapabilities(); + }, []); - const canSet = env === 'kibana' ? capabilities.useService().canSetAdvancedSettings() : true; + const canSet = env === 'kibana' ? canSetAdvancedSettings : true; return ( diff --git a/src/plugins/presentation_util/public/components/labs/labs_beaker_button.tsx b/src/plugins/presentation_util/public/components/labs/labs_beaker_button.tsx index ca20f973344c6..1d454050963d9 100644 --- a/src/plugins/presentation_util/public/components/labs/labs_beaker_button.tsx +++ b/src/plugins/presentation_util/public/components/labs/labs_beaker_button.tsx @@ -7,20 +7,20 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React, { useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { EuiButton, EuiIcon, EuiNotificationBadge, EuiButtonProps } from '@elastic/eui'; -import { pluginServices } from '../../services'; import { LabsFlyout, Props as FlyoutProps } from './labs_flyout'; +import { getPresentationLabsService } from '../../services/presentation_labs_service'; export type Props = EuiButtonProps & Pick; export const LabsBeakerButton = ({ solutions, ...props }: Props) => { - const { labs: labsService } = pluginServices.getHooks(); - const { getProjects } = labsService.useService(); + const labsService = useMemo(() => getPresentationLabsService(), []); + const [isOpen, setIsOpen] = useState(false); - const projects = getProjects(); + const projects = labsService.getProjects(); const [overrideCount, onEnabledCountChange] = useState( Object.values(projects).filter((project) => project.status.isOverride).length diff --git a/src/plugins/presentation_util/public/components/labs/labs_flyout.tsx b/src/plugins/presentation_util/public/components/labs/labs_flyout.tsx index 2946adb8b7488..d7ec712c3eede 100644 --- a/src/plugins/presentation_util/public/components/labs/labs_flyout.tsx +++ b/src/plugins/presentation_util/public/components/labs/labs_flyout.tsx @@ -7,26 +7,26 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React, { ReactNode, useRef, useState, useEffect } from 'react'; import { + EuiButton, + EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, EuiFlyout, - EuiTitle, - EuiSpacer, - EuiText, EuiFlyoutBody, EuiFlyoutFooter, EuiFlyoutHeader, - EuiButton, - EuiButtonEmpty, - EuiFlexItem, - EuiFlexGroup, EuiIcon, + EuiSpacer, + EuiText, + EuiTitle, } from '@elastic/eui'; +import React, { ReactNode, useEffect, useMemo, useRef, useState } from 'react'; -import { SolutionName, ProjectStatus, ProjectID, Project, EnvironmentName } from '../../../common'; -import { pluginServices } from '../../services'; +import { EnvironmentName, Project, ProjectID, ProjectStatus, SolutionName } from '../../../common'; import { LabsStrings } from '../../i18n'; +import { getPresentationLabsService } from '../../services/presentation_labs_service'; import { ProjectList } from './project_list'; const { Flyout: strings } = LabsStrings.Components; @@ -56,12 +56,11 @@ export const getOverridenCount = (projects: Record) => export const LabsFlyout = (props: Props) => { const { solutions, onEnabledCountChange = () => {}, onClose } = props; - const { labs: labsService } = pluginServices.getHooks(); - const { getProjects, setProjectStatus, reset } = labsService.useService(); + const labsService = useMemo(() => getPresentationLabsService(), []); - const [projects, setProjects] = useState(getProjects()); + const [projects, setProjects] = useState(labsService.getProjects()); const [overrideCount, setOverrideCount] = useState(getOverridenCount(projects)); - const initialStatus = useRef(getProjects()); + const initialStatus = useRef(labsService.getProjects()); const isChanged = hasStatusChanged(initialStatus.current, projects); @@ -74,8 +73,8 @@ export const LabsFlyout = (props: Props) => { }, [onEnabledCountChange, overrideCount]); const onStatusChange = (id: ProjectID, env: EnvironmentName, enabled: boolean) => { - setProjectStatus(id, env, enabled); - setProjects(getProjects()); + labsService.setProjectStatus(id, env, enabled); + setProjects(labsService.getProjects()); }; let footer: ReactNode = null; @@ -83,8 +82,8 @@ export const LabsFlyout = (props: Props) => { const resetButton = ( { - reset(); - setProjects(getProjects()); + labsService.reset(); + setProjects(labsService.getProjects()); }} isDisabled={!overrideCount} > diff --git a/src/plugins/presentation_util/public/components/labs/project_list_item.stories.tsx b/src/plugins/presentation_util/public/components/labs/project_list_item.stories.tsx index 94feb75d3623d..3a157a972647a 100644 --- a/src/plugins/presentation_util/public/components/labs/project_list_item.stories.tsx +++ b/src/plugins/presentation_util/public/components/labs/project_list_item.stories.tsx @@ -7,15 +7,15 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React from 'react'; import { action } from '@storybook/addon-actions'; import { mapValues } from 'lodash'; +import React from 'react'; import { EnvironmentStatus, ProjectConfig, ProjectID, ProjectStatus } from '../../../common'; -import { applyProjectStatus } from '../../services/labs/types'; import { ProjectListItem, Props } from './project_list_item'; import { projects as projectConfigs } from '../../../common'; +import { applyProjectStatus } from '../../services/presentation_labs_service'; import { ProjectList } from './project_list'; export default { diff --git a/src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard.tsx b/src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard.tsx index 9bb8f0471375a..e2e87649d4251 100644 --- a/src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard.tsx +++ b/src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard.tsx @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React, { useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { i18n } from '@kbn/i18n'; @@ -17,20 +17,21 @@ import { type SaveModalState, } from '@kbn/saved-objects-plugin/public'; -import { pluginServices } from '../services'; import { SaveModalDashboardProps } from './types'; import { SaveModalDashboardSelector } from './saved_object_save_modal_dashboard_selector'; +import { getPresentationCapabilities } from '../utils/get_presentation_capabilities'; function SavedObjectSaveModalDashboard(props: SaveModalDashboardProps) { const { documentInfo, tagOptions, objectType, onClose, canSaveByReference } = props; const { id: documentId } = documentInfo; const initialCopyOnSave = !Boolean(documentId); - const { capabilities } = pluginServices.getHooks(); - const { canAccessDashboards, canCreateNewDashboards } = capabilities.useService(); + const { canAccessDashboards, canCreateNewDashboards } = useMemo(() => { + return getPresentationCapabilities(); + }, []); // Disable the dashboard options if the user can't access dashboards or if they're read-only - const disableDashboardOptions = !canAccessDashboards() || !canCreateNewDashboards(); + const disableDashboardOptions = !canAccessDashboards || !canCreateNewDashboards; const [dashboardOption, setDashboardOption] = useState<'new' | 'existing' | null>( documentId || disableDashboardOptions ? null : 'existing' diff --git a/src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard_selector.stories.tsx b/src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard_selector.stories.tsx index 336ff500ba9e1..95b03d66b65fe 100644 --- a/src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard_selector.stories.tsx +++ b/src/plugins/presentation_util/public/components/saved_object_save_modal_dashboard_selector.stories.tsx @@ -10,7 +10,6 @@ import React, { useState } from 'react'; import { action } from '@storybook/addon-actions'; -import { StorybookParams } from '../services/plugin_services.story'; import { SaveModalDashboardSelector } from './saved_object_save_modal_dashboard_selector'; export default { @@ -49,7 +48,7 @@ export function Example({ copyOnSave: boolean; hasDocumentId: boolean; canSaveVisualizations: boolean; -} & StorybookParams) { +}) { const [dashboardOption, setDashboardOption] = useState<'new' | 'existing' | null>('existing'); const [isAddToLibrarySelected, setAddToLibrary] = useState(false); diff --git a/src/plugins/presentation_util/public/index.ts b/src/plugins/presentation_util/public/index.ts index 74335d385e5f4..16f33d237364a 100644 --- a/src/plugins/presentation_util/public/index.ts +++ b/src/plugins/presentation_util/public/index.ts @@ -9,9 +9,8 @@ import { ExpressionFunction } from '@kbn/expressions-plugin/common'; import { PresentationUtilPlugin } from './plugin'; -import { pluginServices } from './services'; -export type { PresentationCapabilitiesService, PresentationLabsService } from './services'; +export type { PresentationLabsService } from './services/presentation_labs_service'; export type { KibanaPluginServiceFactory, @@ -70,7 +69,3 @@ export const registerExpressionsLanguage = async (expressionFunctions: Expressio export function plugin() { return new PresentationUtilPlugin(); } - -export const useLabs = () => (() => pluginServices.getHooks().labs.useService())(); - -export const getContextProvider = () => pluginServices.getContextProvider(); diff --git a/src/plugins/presentation_util/public/mocks.ts b/src/plugins/presentation_util/public/mocks.ts index e5a858375e98d..e9eea6790d3df 100644 --- a/src/plugins/presentation_util/public/mocks.ts +++ b/src/plugins/presentation_util/public/mocks.ts @@ -7,20 +7,21 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { CoreStart } from '@kbn/core/public'; import { PresentationUtilPluginStart } from './types'; -import { pluginServices } from './services'; -import { registry as stubRegistry } from './services/plugin_services.story'; import { ReduxToolsPackage, registerExpressionsLanguage } from '.'; import { createReduxEmbeddableTools } from './redux_tools/redux_embeddables/create_redux_embeddable_tools'; import { createReduxTools } from './redux_tools/create_redux_tools'; +import { setStubKibanaServices } from './services/mocks'; -const createStartContract = (coreStart: CoreStart): PresentationUtilPluginStart => { - pluginServices.setRegistry(stubRegistry.start({})); - +const createStartContract = (): PresentationUtilPluginStart => { const startContract: PresentationUtilPluginStart = { - ContextProvider: pluginServices.getContextProvider(), - labsService: pluginServices.getServices().labs, + labsService: { + getProjects: jest.fn(), + getProject: jest.fn(), + isProjectEnabled: jest.fn(), + reset: jest.fn(), + setProjectStatus: jest.fn(), + }, registerExpressionsLanguage, }; return startContract; @@ -40,5 +41,5 @@ export const mockedReduxEmbeddablePackage: ReduxToolsPackage = { export * from './__stories__/fixtures/flights'; export const setMockedPresentationUtilServices = () => { - pluginServices.setRegistry(stubRegistry.start({})); + setStubKibanaServices(); }; diff --git a/src/plugins/presentation_util/public/plugin.ts b/src/plugins/presentation_util/public/plugin.ts index 55294ae0ed683..e5055c53e2df3 100644 --- a/src/plugins/presentation_util/public/plugin.ts +++ b/src/plugins/presentation_util/public/plugin.ts @@ -8,15 +8,16 @@ */ import { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; -import { pluginServices, registry } from './services/plugin_services'; import { - PresentationUtilPluginSetupDeps, - PresentationUtilPluginStartDeps, PresentationUtilPluginSetup, + PresentationUtilPluginSetupDeps, PresentationUtilPluginStart, + PresentationUtilPluginStartDeps, } from './types'; import { registerExpressionsLanguage } from '.'; +import { setKibanaServices } from './services/kibana_services'; +import { getPresentationLabsService } from './services/presentation_labs_service'; export class PresentationUtilPlugin implements @@ -38,11 +39,10 @@ export class PresentationUtilPlugin coreStart: CoreStart, startPlugins: PresentationUtilPluginStartDeps ): PresentationUtilPluginStart { - pluginServices.setRegistry(registry.start({ coreStart, startPlugins })); + setKibanaServices(coreStart, startPlugins); return { - ContextProvider: pluginServices.getContextProvider(), - labsService: pluginServices.getServices().labs, + labsService: getPresentationLabsService(), registerExpressionsLanguage, }; } diff --git a/src/plugins/presentation_util/public/services/capabilities/capabilities.story.ts b/src/plugins/presentation_util/public/services/capabilities/capabilities.story.ts deleted file mode 100644 index 4c8ae3e893608..0000000000000 --- a/src/plugins/presentation_util/public/services/capabilities/capabilities.story.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { PluginServiceFactory } from '../create'; -import { StorybookParams } from '../plugin_services.story'; -import { PresentationCapabilitiesService } from './types'; - -type CapabilitiesServiceFactory = PluginServiceFactory< - PresentationCapabilitiesService, - StorybookParams ->; - -export const capabilitiesServiceFactory: CapabilitiesServiceFactory = ({ - canAccessDashboards, - canCreateNewDashboards, - canSaveVisualizations, - canSetAdvancedSettings, -}) => { - const check = (value: boolean = true) => value; - return { - canAccessDashboards: () => check(canAccessDashboards), - canCreateNewDashboards: () => check(canCreateNewDashboards), - canSaveVisualizations: () => check(canSaveVisualizations), - canSetAdvancedSettings: () => check(canSetAdvancedSettings), - }; -}; diff --git a/src/plugins/presentation_util/public/services/capabilities/capabilities.stub.ts b/src/plugins/presentation_util/public/services/capabilities/capabilities.stub.ts deleted file mode 100644 index f46471c8efb54..0000000000000 --- a/src/plugins/presentation_util/public/services/capabilities/capabilities.stub.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { PluginServiceFactory } from '../create'; -import { PresentationCapabilitiesService } from './types'; - -type CapabilitiesServiceFactory = PluginServiceFactory; - -export const capabilitiesServiceFactory: CapabilitiesServiceFactory = () => ({ - canAccessDashboards: () => true, - canCreateNewDashboards: () => true, - canSaveVisualizations: () => true, - canSetAdvancedSettings: () => true, -}); diff --git a/src/plugins/presentation_util/public/services/capabilities/capabilities_service.ts b/src/plugins/presentation_util/public/services/capabilities/capabilities_service.ts deleted file mode 100644 index d286802b17141..0000000000000 --- a/src/plugins/presentation_util/public/services/capabilities/capabilities_service.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { PresentationUtilPluginStartDeps } from '../../types'; -import { KibanaPluginServiceFactory } from '../create'; -import { PresentationCapabilitiesService } from './types'; - -export type CapabilitiesServiceFactory = KibanaPluginServiceFactory< - PresentationCapabilitiesService, - PresentationUtilPluginStartDeps ->; - -export const capabilitiesServiceFactory: CapabilitiesServiceFactory = ({ coreStart }) => { - const { dashboard, visualize, advancedSettings } = coreStart.application.capabilities; - - return { - canAccessDashboards: () => Boolean(dashboard.show), - canCreateNewDashboards: () => Boolean(dashboard.createNew), - canSaveVisualizations: () => Boolean(visualize.save), - canSetAdvancedSettings: () => Boolean(advancedSettings.save), - }; -}; diff --git a/src/plugins/presentation_util/public/services/capabilities/types.ts b/src/plugins/presentation_util/public/services/capabilities/types.ts deleted file mode 100644 index 51d323c0c0d54..0000000000000 --- a/src/plugins/presentation_util/public/services/capabilities/types.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export interface PresentationCapabilitiesService { - canAccessDashboards: () => boolean; - canCreateNewDashboards: () => boolean; - canSaveVisualizations: () => boolean; - canSetAdvancedSettings: () => boolean; -} diff --git a/src/plugins/presentation_util/public/services/content_management/content_management.stub.ts b/src/plugins/presentation_util/public/services/content_management/content_management.stub.ts deleted file mode 100644 index c492cce96fc23..0000000000000 --- a/src/plugins/presentation_util/public/services/content_management/content_management.stub.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { PluginServiceFactory } from '../create'; -import { PresentationContentManagementService } from './types'; - -type ContentManagementServiceFactory = PluginServiceFactory; - -export const contentManagementServiceFactory: ContentManagementServiceFactory = () => ({ - client: { - get: jest.fn(), - get$: jest.fn(), - create: jest.fn(), - update: jest.fn(), - delete: jest.fn(), - search: jest.fn(), - search$: jest.fn(), - mSearch: jest.fn(), - } as unknown as PresentationContentManagementService['client'], -}); diff --git a/src/plugins/presentation_util/public/services/content_management/content_management_service.ts b/src/plugins/presentation_util/public/services/content_management/content_management_service.ts deleted file mode 100644 index 7a5986c55ba80..0000000000000 --- a/src/plugins/presentation_util/public/services/content_management/content_management_service.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { PresentationUtilPluginStartDeps } from '../../types'; -import { PresentationContentManagementService } from './types'; -import { KibanaPluginServiceFactory } from '../create'; - -export type PresentationContentManagementServiceFactory = KibanaPluginServiceFactory< - PresentationContentManagementService, - PresentationUtilPluginStartDeps ->; - -export const contentManagementServiceFactory: PresentationContentManagementServiceFactory = ({ - startPlugins, -}) => { - return { - client: startPlugins.contentManagement.client, - }; -}; diff --git a/src/plugins/presentation_util/public/services/content_management/types.ts b/src/plugins/presentation_util/public/services/content_management/types.ts deleted file mode 100644 index f87d45072aa98..0000000000000 --- a/src/plugins/presentation_util/public/services/content_management/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; - -export interface PresentationContentManagementService { - client: ContentManagementPublicStart['client']; -} diff --git a/src/plugins/presentation_util/public/services/data_views/data_views.story.ts b/src/plugins/presentation_util/public/services/data_views/data_views.story.ts deleted file mode 100644 index de82be53bb00f..0000000000000 --- a/src/plugins/presentation_util/public/services/data_views/data_views.story.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; -import { DataView } from '@kbn/data-views-plugin/common'; -import { PluginServiceFactory } from '../create'; -import { PresentationDataViewsService } from './types'; - -export type DataViewsServiceFactory = PluginServiceFactory; - -let currentDataView: DataView; -export const injectStorybookDataView = (dataView: DataView) => (currentDataView = dataView); - -export const dataViewsServiceFactory: DataViewsServiceFactory = () => ({ - get: (() => - new Promise((r) => - setTimeout(() => r(currentDataView), 100) - ) as unknown) as DataViewsPublicPluginStart['get'], - getIdsWithTitle: (() => - new Promise((r) => - setTimeout(() => r([{ id: currentDataView.id, title: currentDataView.title }]), 100) - ) as unknown) as DataViewsPublicPluginStart['getIdsWithTitle'], - getDefaultId: () => Promise.resolve(currentDataView?.id ?? null), -}); diff --git a/src/plugins/presentation_util/public/services/data_views/data_views_service.ts b/src/plugins/presentation_util/public/services/data_views/data_views_service.ts deleted file mode 100644 index 40a47bc14713f..0000000000000 --- a/src/plugins/presentation_util/public/services/data_views/data_views_service.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { PresentationUtilPluginStartDeps } from '../../types'; -import { PresentationDataViewsService } from './types'; -import { KibanaPluginServiceFactory } from '../create'; - -export type DataViewsServiceFactory = KibanaPluginServiceFactory< - PresentationDataViewsService, - PresentationUtilPluginStartDeps ->; - -export const dataViewsServiceFactory: DataViewsServiceFactory = ({ startPlugins }) => { - const { - dataViews: { get, getIdsWithTitle, getDefaultId }, - } = startPlugins; - - return { - get, - getDefaultId, - getIdsWithTitle, - }; -}; diff --git a/src/plugins/presentation_util/public/services/data_views/types.ts b/src/plugins/presentation_util/public/services/data_views/types.ts deleted file mode 100644 index bb0af7c7e607d..0000000000000 --- a/src/plugins/presentation_util/public/services/data_views/types.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; - -export interface PresentationDataViewsService { - get: DataViewsPublicPluginStart['get']; - getDefaultId: DataViewsPublicPluginStart['getDefaultId']; - getIdsWithTitle: DataViewsPublicPluginStart['getIdsWithTitle']; -} diff --git a/src/plugins/presentation_util/public/services/index.ts b/src/plugins/presentation_util/public/services/index.ts deleted file mode 100644 index ccfcc112a41f7..0000000000000 --- a/src/plugins/presentation_util/public/services/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -export { pluginServices } from './plugin_services'; - -export type { PresentationCapabilitiesService, PresentationLabsService } from './types'; diff --git a/src/plugins/presentation_util/public/services/kibana_services.ts b/src/plugins/presentation_util/public/services/kibana_services.ts new file mode 100644 index 0000000000000..1299544623bd5 --- /dev/null +++ b/src/plugins/presentation_util/public/services/kibana_services.ts @@ -0,0 +1,45 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { BehaviorSubject } from 'rxjs'; + +import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; +import type { CoreStart } from '@kbn/core/public'; +import type { UiActionsPublicStart } from '@kbn/ui-actions-plugin/public/plugin'; +import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; + +import { PresentationUtilPluginStartDeps } from '../types'; + +export let coreServices: CoreStart; +export let contentManagementService: ContentManagementPublicStart; +export let dataViewsService: DataViewsPublicPluginStart; +export let uiActionsService: UiActionsPublicStart; + +const servicesReady$ = new BehaviorSubject(false); + +export const setKibanaServices = (kibanaCore: CoreStart, deps: PresentationUtilPluginStartDeps) => { + coreServices = kibanaCore; + contentManagementService = deps.contentManagement; + dataViewsService = deps.dataViews; + uiActionsService = deps.uiActions; + + servicesReady$.next(true); +}; + +export const untilPluginStartServicesReady = () => { + if (servicesReady$.value) return Promise.resolve(); + return new Promise((resolve) => { + const subscription = servicesReady$.subscribe((isInitialized) => { + if (isInitialized) { + subscription.unsubscribe(); + resolve(); + } + }); + }); +}; diff --git a/src/plugins/presentation_util/public/services/labs/labs.story.ts b/src/plugins/presentation_util/public/services/labs/labs.story.ts deleted file mode 100644 index 0ae9fc8b89a04..0000000000000 --- a/src/plugins/presentation_util/public/services/labs/labs.story.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { EnvironmentName, projectIDs, Project } from '../../../common'; -import { PluginServiceFactory } from '../create'; -import { projects, ProjectID, getProjectIDs, SolutionName } from '../../../common'; -import { PresentationLabsService, isEnabledByStorageValue, applyProjectStatus } from './types'; - -export type LabsServiceFactory = PluginServiceFactory; - -export const labsServiceFactory: LabsServiceFactory = () => { - const storage = window.sessionStorage; - - const getProjects = (solutions: SolutionName[] = []) => - projectIDs.reduce((acc, id) => { - const project = getProject(id); - if ( - solutions.length === 0 || - solutions.some((solution) => project.solutions.includes(solution)) - ) { - acc[id] = project; - } - return acc; - }, {} as { [id in ProjectID]: Project }); - - const getProject = (id: ProjectID) => { - const project = projects[id]; - const { isActive } = project; - const status = { - session: isEnabledByStorageValue(project, 'session', sessionStorage.getItem(id)), - browser: isEnabledByStorageValue(project, 'browser', localStorage.getItem(id)), - kibana: isActive, - }; - return applyProjectStatus(project, status); - }; - - const setProjectStatus = (name: ProjectID, env: EnvironmentName, enabled: boolean) => { - if (env === 'session') { - storage.setItem(name, enabled ? 'enabled' : 'disabled'); - } - }; - - const reset = () => { - // This is normally not ok, but it's our isolated Storybook instance. - storage.clear(); - }; - - const isProjectEnabled = (id: ProjectID) => getProject(id).status.isEnabled; - - return { - getProjectIDs, - getProjects, - getProject, - isProjectEnabled, - reset, - setProjectStatus, - }; -}; diff --git a/src/plugins/presentation_util/public/services/labs/labs.stub.ts b/src/plugins/presentation_util/public/services/labs/labs.stub.ts deleted file mode 100644 index 21e44b38f1ac3..0000000000000 --- a/src/plugins/presentation_util/public/services/labs/labs.stub.ts +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - projects, - projectIDs, - ProjectID, - EnvironmentName, - getProjectIDs, - Project, - SolutionName, -} from '../../../common'; -import { PluginServiceFactory } from '../create'; -import { PresentationLabsService, isEnabledByStorageValue, applyProjectStatus } from './types'; - -export type LabsServiceFactory = PluginServiceFactory; - -type Statuses = { - [id in ProjectID]: { - defaultValue: boolean; - session: boolean | null; - browser: boolean | null; - kibana: boolean; - }; -}; - -export const labsServiceFactory: LabsServiceFactory = () => { - let statuses = {} as Statuses; - - const getProject = (id: ProjectID) => { - const project = projects[id]; - const value = statuses[id]; - const status = { - session: isEnabledByStorageValue(project, 'session', value.session), - browser: isEnabledByStorageValue(project, 'browser', value.browser), - kibana: isEnabledByStorageValue(project, 'kibana', value.kibana), - }; - - return applyProjectStatus(project, status); - }; - - const reset = () => - projectIDs.reduce((acc, id) => { - const project = projects[id]; - const defaultValue = project.isActive; - - acc[id] = { - defaultValue, - session: null, - browser: null, - kibana: defaultValue, - }; - return acc; - }, {} as Statuses); - - statuses = reset(); - - const getProjects = (solutions: SolutionName[] = []) => - projectIDs.reduce((acc, id) => { - const project = getProject(id); - if ( - solutions.length === 0 || - solutions.some((solution) => project.solutions.includes(solution)) - ) { - acc[id] = project; - } - return acc; - }, {} as { [id in ProjectID]: Project }); - - const setProjectStatus = (id: ProjectID, env: EnvironmentName, value: boolean) => { - statuses[id] = { ...statuses[id], [env]: value }; - }; - - const isProjectEnabled = (id: ProjectID) => getProject(id).status.isEnabled; - - return { - getProjectIDs, - getProject, - getProjects, - isProjectEnabled, - setProjectStatus, - reset: () => { - statuses = reset(); - }, - }; -}; diff --git a/src/plugins/presentation_util/public/services/labs/types.ts b/src/plugins/presentation_util/public/services/labs/types.ts deleted file mode 100644 index 4c721c84f6a6f..0000000000000 --- a/src/plugins/presentation_util/public/services/labs/types.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { IUiSettingsClient } from '@kbn/core/public'; -import { - EnvironmentName, - projectIDs, - Project, - ProjectConfig, - ProjectID, - EnvironmentStatus, - environmentNames, - isProjectEnabledByStatus, - SolutionName, -} from '../../../common'; - -export interface PresentationLabsService { - isProjectEnabled: (id: ProjectID) => boolean; - getProjectIDs: () => typeof projectIDs; - getProject: (id: ProjectID) => Project; - getProjects: (solutions?: SolutionName[]) => Record; - setProjectStatus: (id: ProjectID, env: EnvironmentName, status: boolean) => void; - reset: () => void; -} - -export const isEnabledByStorageValue = ( - project: ProjectConfig, - environment: EnvironmentName, - value: string | boolean | null -): boolean => { - const defaultValue = project.isActive; - - if (!project.environments.includes(environment)) { - return defaultValue; - } - - if (value === true || value === false) { - return value; - } - - if (value === 'enabled') { - return true; - } - - if (value === 'disabled') { - return false; - } - - return defaultValue; -}; - -export const setStorageStatus = (storage: Storage, id: ProjectID, enabled: boolean) => - storage.setItem(id, enabled ? 'enabled' : 'disabled'); - -export const applyProjectStatus = (project: ProjectConfig, status: EnvironmentStatus): Project => { - const { isActive, environments } = project; - - environmentNames.forEach((name) => { - if (!environments.includes(name)) { - delete status[name]; - } - }); - - const isEnabled = isProjectEnabledByStatus(isActive, status); - const isOverride = isEnabled !== isActive; - - return { - ...project, - status: { - ...status, - defaultValue: isActive, - isEnabled, - isOverride, - }, - }; -}; - -export const setUISettingsStatus = (client: IUiSettingsClient, id: ProjectID, enabled: boolean) => - client.set(id, enabled); diff --git a/src/plugins/presentation_util/public/services/mocks.ts b/src/plugins/presentation_util/public/services/mocks.ts new file mode 100644 index 0000000000000..d0f54c5af5f09 --- /dev/null +++ b/src/plugins/presentation_util/public/services/mocks.ts @@ -0,0 +1,43 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { contentManagementMock } from '@kbn/content-management-plugin/public/mocks'; +import { CoreStart } from '@kbn/core/public'; +import { coreMock } from '@kbn/core/public/mocks'; +import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; +import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; + +import { setKibanaServices } from './kibana_services'; + +const setDefaultPresentationUtilCapabilities = (core: CoreStart) => { + core.application.capabilities = { + ...core.application.capabilities, + dashboard: { + show: true, + createNew: true, + }, + visualize: { + save: true, + }, + advancedSettings: { + save: true, + }, + }; +}; + +export const setStubKibanaServices = () => { + const core = coreMock.createStart(); + + setDefaultPresentationUtilCapabilities(core); + setKibanaServices(core, { + contentManagement: contentManagementMock.createStartContract(), + uiActions: uiActionsPluginMock.createStartContract(), + dataViews: dataViewPluginMocks.createStartContract(), + }); +}; diff --git a/src/plugins/presentation_util/public/services/plugin_services.story.ts b/src/plugins/presentation_util/public/services/plugin_services.story.ts deleted file mode 100644 index 76118233a4f14..0000000000000 --- a/src/plugins/presentation_util/public/services/plugin_services.story.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - PluginServices, - PluginServiceProviders, - PluginServiceProvider, - PluginServiceRegistry, -} from './create'; -import { PresentationUtilServices } from './types'; - -import { capabilitiesServiceFactory } from './capabilities/capabilities.story'; -import { dataViewsServiceFactory } from './data_views/data_views.story'; -import { contentManagementServiceFactory } from './content_management/content_management.stub'; -import { labsServiceFactory } from './labs/labs.story'; -import { uiActionsServiceFactory } from './ui_actions/ui_actions.stub'; - -export const providers: PluginServiceProviders = { - capabilities: new PluginServiceProvider(capabilitiesServiceFactory), - labs: new PluginServiceProvider(labsServiceFactory), - dataViews: new PluginServiceProvider(dataViewsServiceFactory), - contentManagement: new PluginServiceProvider(contentManagementServiceFactory), - uiActions: new PluginServiceProvider(uiActionsServiceFactory), -}; - -export const pluginServices = new PluginServices(); - -export const registry = new PluginServiceRegistry(providers); - -export interface StorybookParams { - canAccessDashboards?: boolean; - canCreateNewDashboards?: boolean; - canSaveVisualizations?: boolean; - canSetAdvancedSettings?: boolean; -} diff --git a/src/plugins/presentation_util/public/services/plugin_services.stub.ts b/src/plugins/presentation_util/public/services/plugin_services.stub.ts deleted file mode 100644 index c503af55bd876..0000000000000 --- a/src/plugins/presentation_util/public/services/plugin_services.stub.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { PluginServices, PluginServiceProviders, PluginServiceProvider } from './create'; -import { PresentationUtilServices } from './types'; -import { registry as stubRegistry } from './plugin_services.story'; -import { PresentationUtilPluginStart, registerExpressionsLanguage } from '..'; - -import { capabilitiesServiceFactory } from './capabilities/capabilities.story'; -import { dataViewsServiceFactory } from './data_views/data_views.story'; -import { labsServiceFactory } from './labs/labs.story'; -import { uiActionsServiceFactory } from './ui_actions/ui_actions.stub'; -import { contentManagementServiceFactory } from './content_management/content_management.stub'; - -export const providers: PluginServiceProviders = { - contentManagement: new PluginServiceProvider(contentManagementServiceFactory), - capabilities: new PluginServiceProvider(capabilitiesServiceFactory), - labs: new PluginServiceProvider(labsServiceFactory), - dataViews: new PluginServiceProvider(dataViewsServiceFactory), - uiActions: new PluginServiceProvider(uiActionsServiceFactory), -}; - -export const pluginServices = new PluginServices(); - -export const getStubPluginServices = (): PresentationUtilPluginStart => { - pluginServices.setRegistry(stubRegistry.start({})); - return { - ContextProvider: pluginServices.getContextProvider(), - labsService: pluginServices.getServices().labs, - registerExpressionsLanguage, - }; -}; diff --git a/src/plugins/presentation_util/public/services/plugin_services.ts b/src/plugins/presentation_util/public/services/plugin_services.ts deleted file mode 100644 index 4d43a0e4c4a74..0000000000000 --- a/src/plugins/presentation_util/public/services/plugin_services.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { - PluginServices, - PluginServiceProviders, - KibanaPluginServiceParams, - PluginServiceProvider, - PluginServiceRegistry, -} from './create'; -import { PresentationUtilPluginStartDeps } from '../types'; - -import { capabilitiesServiceFactory } from './capabilities/capabilities_service'; -import { dataViewsServiceFactory } from './data_views/data_views_service'; -import { contentManagementServiceFactory } from './content_management/content_management_service'; -import { uiActionsServiceFactory } from './ui_actions/ui_actions_service'; -import { labsServiceFactory } from './labs/labs_service'; -import { PresentationUtilServices } from './types'; - -export const providers: PluginServiceProviders< - PresentationUtilServices, - KibanaPluginServiceParams -> = { - capabilities: new PluginServiceProvider(capabilitiesServiceFactory), - labs: new PluginServiceProvider(labsServiceFactory), - dataViews: new PluginServiceProvider(dataViewsServiceFactory), - uiActions: new PluginServiceProvider(uiActionsServiceFactory), - contentManagement: new PluginServiceProvider(contentManagementServiceFactory), -}; - -export const pluginServices = new PluginServices(); - -export const registry = new PluginServiceRegistry< - PresentationUtilServices, - KibanaPluginServiceParams ->(providers); diff --git a/src/plugins/presentation_util/public/services/labs/labs_service.ts b/src/plugins/presentation_util/public/services/presentation_labs_service.ts similarity index 58% rename from src/plugins/presentation_util/public/services/labs/labs_service.ts rename to src/plugins/presentation_util/public/services/presentation_labs_service.ts index b30a7ee89bdde..b69f03d7c18a1 100644 --- a/src/plugins/presentation_util/public/services/labs/labs_service.ts +++ b/src/plugins/presentation_util/public/services/presentation_labs_service.ts @@ -7,43 +7,31 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; import { EnvironmentName, - projectIDs, - projects, - ProjectID, + EnvironmentStatus, + LABS_PROJECT_PREFIX, Project, - getProjectIDs, + ProjectConfig, + ProjectID, SolutionName, - LABS_PROJECT_PREFIX, -} from '../../../common'; -import { PresentationUtilPluginStartDeps } from '../../types'; -import { KibanaPluginServiceFactory } from '../create'; -import { - PresentationLabsService, - isEnabledByStorageValue, - setStorageStatus, - setUISettingsStatus, - applyProjectStatus, -} from './types'; - -export type LabsServiceFactory = KibanaPluginServiceFactory< - PresentationLabsService, - PresentationUtilPluginStartDeps ->; + isProjectEnabledByStatus, + projectIDs, + projects, +} from '../../common'; +import { coreServices } from './kibana_services'; -const clearLabsFromStorage = (storage: Storage) => { - projectIDs.forEach((projectID) => storage.removeItem(projectID)); +export interface PresentationLabsService { + isProjectEnabled: (id: ProjectID) => boolean; + getProject: (id: ProjectID) => Project; + getProjects: (solutions?: SolutionName[]) => Record; + setProjectStatus: (id: ProjectID, env: EnvironmentName, status: boolean) => void; + reset: () => void; +} - // This is a redundancy, to catch any labs that may have been removed above. - // We could consider gathering telemetry to see how often this happens, or this may be unnecessary. - Object.keys(storage) - .filter((key) => key.startsWith(LABS_PROJECT_PREFIX)) - .forEach((key) => storage.removeItem(key)); -}; - -export const labsServiceFactory: LabsServiceFactory = ({ coreStart }) => { - const { uiSettings } = coreStart; +export const getPresentationLabsService = (): PresentationLabsService => { + const { uiSettings } = coreServices; const localStorage = window.localStorage; const sessionStorage = window.sessionStorage; @@ -94,7 +82,6 @@ export const labsServiceFactory: LabsServiceFactory = ({ coreStart }) => { const isProjectEnabled = (id: ProjectID) => getProject(id).status.isEnabled; return { - getProjectIDs, getProjects, getProject, isProjectEnabled, @@ -102,3 +89,71 @@ export const labsServiceFactory: LabsServiceFactory = ({ coreStart }) => { setProjectStatus, }; }; + +/** + * Helpers + */ +const isEnabledByStorageValue = ( + project: ProjectConfig, + environment: EnvironmentName, + value: string | boolean | null +): boolean => { + const defaultValue = project.isActive; + + if (!project.environments.includes(environment)) { + return defaultValue; + } + + if (value === true || value === false) { + return value; + } + + if (value === 'enabled') { + return true; + } + + if (value === 'disabled') { + return false; + } + + return defaultValue; +}; + +const setStorageStatus = (storage: Storage, id: ProjectID, enabled: boolean) => + storage.setItem(id, enabled ? 'enabled' : 'disabled'); + +export const applyProjectStatus = (project: ProjectConfig, status: EnvironmentStatus): Project => { + const { isActive, environments } = project; + + environments.forEach((name) => { + if (!environments.includes(name)) { + delete status[name]; + } + }); + + const isEnabled = isProjectEnabledByStatus(isActive, status); + const isOverride = isEnabled !== isActive; + + return { + ...project, + status: { + ...status, + defaultValue: isActive, + isEnabled, + isOverride, + }, + }; +}; + +const setUISettingsStatus = (client: IUiSettingsClient, id: ProjectID, enabled: boolean) => + client.set(id, enabled); + +const clearLabsFromStorage = (storage: Storage) => { + projectIDs.forEach((projectID) => storage.removeItem(projectID)); + + // This is a redundancy, to catch any labs that may have been removed above. + // We could consider gathering telemetry to see how often this happens, or this may be unnecessary. + Object.keys(storage) + .filter((key) => key.startsWith(LABS_PROJECT_PREFIX)) + .forEach((key) => storage.removeItem(key)); +}; diff --git a/src/plugins/presentation_util/public/services/types.ts b/src/plugins/presentation_util/public/services/types.ts deleted file mode 100644 index 06247bb22739b..0000000000000 --- a/src/plugins/presentation_util/public/services/types.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { PresentationLabsService } from './labs/types'; -import { PresentationCapabilitiesService } from './capabilities/types'; -import { PresentationDataViewsService } from './data_views/types'; -import { PresentationUiActionsService } from './ui_actions/types'; -import { PresentationContentManagementService } from './content_management/types'; - -export interface PresentationUtilServices { - contentManagement: PresentationContentManagementService; - capabilities: PresentationCapabilitiesService; - dataViews: PresentationDataViewsService; - uiActions: PresentationUiActionsService; - labs: PresentationLabsService; -} - -export type { PresentationCapabilitiesService, PresentationLabsService }; diff --git a/src/plugins/presentation_util/public/services/ui_actions/types.ts b/src/plugins/presentation_util/public/services/ui_actions/types.ts deleted file mode 100644 index 4953fb6b37234..0000000000000 --- a/src/plugins/presentation_util/public/services/ui_actions/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; - -export interface PresentationUiActionsService { - getTriggerCompatibleActions: UiActionsStart['getTriggerCompatibleActions']; -} diff --git a/src/plugins/presentation_util/public/services/ui_actions/ui_actions.stub.ts b/src/plugins/presentation_util/public/services/ui_actions/ui_actions.stub.ts deleted file mode 100644 index 05399418b6015..0000000000000 --- a/src/plugins/presentation_util/public/services/ui_actions/ui_actions.stub.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; - -import { PluginServiceFactory } from '../create'; -import { PresentationUiActionsService } from './types'; - -type CapabilitiesServiceFactory = PluginServiceFactory; - -export const uiActionsServiceFactory: CapabilitiesServiceFactory = () => { - const { getTriggerCompatibleActions } = uiActionsPluginMock.createStartContract(); - return { getTriggerCompatibleActions }; -}; diff --git a/src/plugins/presentation_util/public/services/ui_actions/ui_actions_service.ts b/src/plugins/presentation_util/public/services/ui_actions/ui_actions_service.ts deleted file mode 100644 index cdce13e10ae94..0000000000000 --- a/src/plugins/presentation_util/public/services/ui_actions/ui_actions_service.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { PresentationUtilPluginStartDeps } from '../../types'; -import { PresentationUiActionsService } from './types'; -import { KibanaPluginServiceFactory } from '../create'; - -export type UiActionsServiceFactory = KibanaPluginServiceFactory< - PresentationUiActionsService, - PresentationUtilPluginStartDeps ->; - -export const uiActionsServiceFactory: UiActionsServiceFactory = ({ startPlugins }) => { - const { - uiActions: { getTriggerCompatibleActions }, - } = startPlugins; - return { - getTriggerCompatibleActions, - }; -}; diff --git a/src/plugins/presentation_util/public/types.ts b/src/plugins/presentation_util/public/types.ts index 2f592796d2524..c0f4005f000fe 100644 --- a/src/plugins/presentation_util/public/types.ts +++ b/src/plugins/presentation_util/public/types.ts @@ -7,18 +7,15 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { FC, PropsWithChildren } from 'react'; -import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; -import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; -import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; -import { registerExpressionsLanguage } from '.'; -import { PresentationLabsService } from './services/labs/types'; +import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; +import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; +import type { UiActionsStart } from '@kbn/ui-actions-plugin/public'; +import { type PresentationLabsService, registerExpressionsLanguage } from '.'; // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface PresentationUtilPluginSetup {} export interface PresentationUtilPluginStart { - ContextProvider: FC>; labsService: PresentationLabsService; registerExpressionsLanguage: typeof registerExpressionsLanguage; } diff --git a/src/plugins/presentation_util/public/utils/get_presentation_capabilities.ts b/src/plugins/presentation_util/public/utils/get_presentation_capabilities.ts new file mode 100644 index 0000000000000..bdc547c2f5202 --- /dev/null +++ b/src/plugins/presentation_util/public/utils/get_presentation_capabilities.ts @@ -0,0 +1,28 @@ +/* + * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { coreServices } from '../services/kibana_services'; + +interface PresentationCapabilities { + canAccessDashboards: boolean; + canCreateNewDashboards: boolean; + canSaveVisualizations: boolean; + canSetAdvancedSettings: boolean; +} + +export const getPresentationCapabilities = (): PresentationCapabilities => { + const { dashboard, visualize, advancedSettings } = coreServices.application.capabilities; + + return { + canAccessDashboards: Boolean(dashboard.show), + canCreateNewDashboards: Boolean(dashboard.createNew), + canSaveVisualizations: Boolean(visualize.save), + canSetAdvancedSettings: Boolean(advancedSettings.save), + }; +}; diff --git a/src/plugins/presentation_util/storybook/decorator.tsx b/src/plugins/presentation_util/storybook/decorator.tsx index 4e1eaa9ec4742..214ab42176ce1 100644 --- a/src/plugins/presentation_util/storybook/decorator.tsx +++ b/src/plugins/presentation_util/storybook/decorator.tsx @@ -9,13 +9,10 @@ import React from 'react'; -import { DecoratorFn } from '@storybook/react'; import { I18nProvider } from '@kbn/i18n-react'; import { KibanaContextProvider as KibanaReactProvider } from '@kbn/kibana-react-plugin/public'; -import { pluginServices } from '../public/services'; -import { PresentationUtilServices } from '../public/services/types'; -import { providers, StorybookParams } from '../public/services/plugin_services.story'; -import { PluginServiceRegistry } from '../public/services/create'; +import { DecoratorFn } from '@storybook/react'; +import { setStubKibanaServices } from '../public/services/mocks'; const settings = new Map(); settings.set('darkMode', true); @@ -33,15 +30,11 @@ const services = { }; export const servicesContextDecorator: DecoratorFn = (story: Function, storybook) => { - const registry = new PluginServiceRegistry(providers); - pluginServices.setRegistry(registry.start(storybook.args)); - const ContextProvider = pluginServices.getContextProvider(); + setStubKibanaServices(); return ( - - {story()} - + {story()} ); }; diff --git a/src/plugins/presentation_util/storybook/main.ts b/src/plugins/presentation_util/storybook/main.ts index e3b5b1c6c596a..c51873a09b7f2 100644 --- a/src/plugins/presentation_util/storybook/main.ts +++ b/src/plugins/presentation_util/storybook/main.ts @@ -9,4 +9,10 @@ import { defaultConfig } from '@kbn/storybook'; -module.exports = defaultConfig; +module.exports = { + ...defaultConfig, + define: { + global: 'window', + }, + stories: ['../../**/*.stories.+(tsx|mdx)'], +}; diff --git a/src/plugins/presentation_util/storybook/preview.tsx b/src/plugins/presentation_util/storybook/preview.tsx index 4ddf9e5080d29..a6b872f2d52cf 100644 --- a/src/plugins/presentation_util/storybook/preview.tsx +++ b/src/plugins/presentation_util/storybook/preview.tsx @@ -8,13 +8,18 @@ */ import React from 'react'; +import * as jest from 'jest-mock'; import { addDecorator } from '@storybook/react'; + import { Title, Subtitle, Description, Primary, Stories } from '@storybook/addon-docs/blocks'; import { servicesContextDecorator } from './decorator'; addDecorator(servicesContextDecorator); +// @ts-ignore +window.jest = jest; + export const parameters = { docs: { page: () => ( diff --git a/src/plugins/presentation_util/tsconfig.json b/src/plugins/presentation_util/tsconfig.json index dea02739d9db9..4e18f2e8bce2b 100644 --- a/src/plugins/presentation_util/tsconfig.json +++ b/src/plugins/presentation_util/tsconfig.json @@ -36,6 +36,7 @@ "@kbn/calculate-width-from-char-count", "@kbn/field-utils", "@kbn/presentation-publishing", + "@kbn/core-ui-settings-browser", ], "exclude": ["target/**/*"] } diff --git a/src/plugins/visualizations/public/mocks.ts b/src/plugins/visualizations/public/mocks.ts index fbc61c871bd59..6d58b3a65c11f 100644 --- a/src/plugins/visualizations/public/mocks.ts +++ b/src/plugins/visualizations/public/mocks.ts @@ -81,7 +81,7 @@ const createInstance = async () => { savedObjectsTaggingOss: savedObjectTaggingOssPluginMock.createStart(), savedSearch: savedSearchPluginMock.createStartContract(), navigation: navigationPluginMock.createStartContract(), - presentationUtil: presentationUtilPluginMock.createStartContract(coreMock.createStart()), + presentationUtil: presentationUtilPluginMock.createStartContract(), urlForwarding: urlForwardingPluginMock.createStartContract(), screenshotMode: screenshotModePluginMock.createStartContract(), fieldFormats: fieldFormatsServiceMock.createStartContract(), diff --git a/src/plugins/visualizations/public/visualize_app/index.tsx b/src/plugins/visualizations/public/visualize_app/index.tsx index 29509468ea44a..375df3a467790 100644 --- a/src/plugins/visualizations/public/visualize_app/index.tsx +++ b/src/plugins/visualizations/public/visualize_app/index.tsx @@ -35,17 +35,15 @@ export const renderApp = ( - - - - - + + + diff --git a/src/plugins/visualizations/public/visualize_app/utils/get_top_nav_config.tsx b/src/plugins/visualizations/public/visualize_app/utils/get_top_nav_config.tsx index 0d49b38319130..5c5a85fbf06ef 100644 --- a/src/plugins/visualizations/public/visualize_app/utils/get_top_nav_config.tsx +++ b/src/plugins/visualizations/public/visualize_app/utils/get_top_nav_config.tsx @@ -623,7 +623,7 @@ export const getTopNavConfig = ( ); } - showSaveModal(saveModal, presentationUtil.ContextProvider); + showSaveModal(saveModal); }, }, ] diff --git a/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_root.tsx b/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_root.tsx index 36f8f3e2ddaf6..420e2b510c62e 100644 --- a/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_root.tsx +++ b/x-pack/plugins/aiops/public/components/change_point_detection/change_point_detection_root.tsx @@ -82,39 +82,34 @@ export const ChangePointDetectionAppState: FC appContextValue.embeddingOrigin = AIOPS_EMBEDDABLE_ORIGIN.ML_AIOPS_LABS; - const PresentationContextProvider = - appContextValue.presentationUtil?.ContextProvider ?? React.Fragment; - const CasesContext = appContextValue.cases?.ui.getCasesContext() ?? React.Fragment; const casesPermissions = appContextValue.cases?.helpers.canUseCases(); return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + ); }; diff --git a/x-pack/plugins/aiops/public/hooks/use_aiops_app_context.ts b/x-pack/plugins/aiops/public/hooks/use_aiops_app_context.ts index 2c926797ac07f..de563f8f5a38d 100644 --- a/x-pack/plugins/aiops/public/hooks/use_aiops_app_context.ts +++ b/x-pack/plugins/aiops/public/hooks/use_aiops_app_context.ts @@ -24,7 +24,6 @@ import type { ThemeServiceStart, } from '@kbn/core/public'; import type { LensPublicStart } from '@kbn/lens-plugin/public'; -import type { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/public'; import type { EmbeddableStart } from '@kbn/embeddable-plugin/public'; import type { CasesPublicStart } from '@kbn/cases-plugin/public'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; @@ -105,7 +104,6 @@ export interface AiopsAppContextValue { * Internationalisation service */ i18n: CoreStart['i18n']; - presentationUtil?: PresentationUtilPluginStart; embeddable?: EmbeddableStart; cases?: CasesPublicStart; isServerless?: boolean; diff --git a/x-pack/plugins/canvas/public/application.tsx b/x-pack/plugins/canvas/public/application.tsx index d9a279e2d2619..72440e3e6873c 100644 --- a/x-pack/plugins/canvas/public/application.tsx +++ b/x-pack/plugins/canvas/public/application.tsx @@ -64,7 +64,6 @@ export const renderApp = ({ canvasStore: Store; pluginServices: PluginServices; }) => { - const { presentationUtil } = startPlugins; const { element } = params; element.classList.add('canvas'); element.classList.add('canvasContainerWrapper'); @@ -75,11 +74,9 @@ export const renderApp = ({ - - - - - + + + diff --git a/x-pack/plugins/canvas/storybook/decorators/services_decorator.tsx b/x-pack/plugins/canvas/storybook/decorators/services_decorator.tsx index 4c610a943a1f2..b5bb0710c3de2 100644 --- a/x-pack/plugins/canvas/storybook/decorators/services_decorator.tsx +++ b/x-pack/plugins/canvas/storybook/decorators/services_decorator.tsx @@ -28,14 +28,7 @@ export const servicesContextDecorator = (): DecoratorFn => { storybook.args.useStaticData = true; } - pluginServices.setRegistry(pluginServiceRegistry.start(storybook.args)); - const ContextProvider = pluginServices.getContextProvider(); - - return ( - - {story()} - - ); + return {story()}; }; }; diff --git a/x-pack/plugins/lens/public/app_plugin/mounter.tsx b/x-pack/plugins/lens/public/app_plugin/mounter.tsx index 07e1627f6d066..7f91943eade30 100644 --- a/x-pack/plugins/lens/public/app_plugin/mounter.tsx +++ b/x-pack/plugins/lens/public/app_plugin/mounter.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { FC, PropsWithChildren, useCallback, useEffect, useState, useMemo } from 'react'; +import React, { useCallback, useEffect, useState, useMemo } from 'react'; import { AppMountParameters, CoreSetup, CoreStart } from '@kbn/core/public'; import { FormattedMessage } from '@kbn/i18n-react'; import { RouteComponentProps } from 'react-router-dom'; @@ -147,18 +147,11 @@ export async function mountApp( mountProps: { createEditorFrame: EditorFrameStart['createInstance']; attributeService: LensAttributeService; - getPresentationUtilContext: () => FC>; topNavMenuEntryGenerators: LensTopNavMenuEntryGenerator[]; locator?: LensAppLocator; } ) { - const { - createEditorFrame, - attributeService, - getPresentationUtilContext, - topNavMenuEntryGenerators, - locator, - } = mountProps; + const { createEditorFrame, attributeService, topNavMenuEntryGenerators, locator } = mountProps; const [[coreStart, startDependencies], instance] = await Promise.all([ core.getStartServices(), createEditorFrame(), @@ -411,25 +404,21 @@ export async function mountApp( params.element.classList.add('lnsAppWrapper'); - const PresentationUtilContext = getPresentationUtilContext(); - render( - - - - - } - /> - - - - - + + + + } + /> + + + + , params.element diff --git a/x-pack/plugins/lens/public/app_plugin/shared/saved_modal_lazy.tsx b/x-pack/plugins/lens/public/app_plugin/shared/saved_modal_lazy.tsx index 24eeffd283f5f..05aaa5a59c75c 100644 --- a/x-pack/plugins/lens/public/app_plugin/shared/saved_modal_lazy.tsx +++ b/x-pack/plugins/lens/public/app_plugin/shared/saved_modal_lazy.tsx @@ -57,13 +57,9 @@ export function getSaveModalComponent( return ; } - const { ContextProvider: PresentationUtilContext } = lensServices.presentationUtil; - return ( - - - + ); }; diff --git a/x-pack/plugins/lens/public/mocks/services_mock.tsx b/x-pack/plugins/lens/public/mocks/services_mock.tsx index fa98db785c50e..18fa29fd6caf2 100644 --- a/x-pack/plugins/lens/public/mocks/services_mock.tsx +++ b/x-pack/plugins/lens/public/mocks/services_mock.tsx @@ -145,7 +145,7 @@ export function makeDefaultServices( inspect: jest.fn(), close: jest.fn(), }, - presentationUtil: presentationUtilPluginMock.createStartContract(core), + presentationUtil: presentationUtilPluginMock.createStartContract(), savedObjectStore: { load: jest.fn(), search: jest.fn(), diff --git a/x-pack/plugins/lens/public/plugin.ts b/x-pack/plugins/lens/public/plugin.ts index 80dfa0f0398bc..b2293ea43b109 100644 --- a/x-pack/plugins/lens/public/plugin.ts +++ b/x-pack/plugins/lens/public/plugin.ts @@ -455,9 +455,6 @@ export class LensPlugin { () => startServices().plugins.data.nowProvider.get() ); - const getPresentationUtilContext = () => - startServices().plugins.presentationUtil.ContextProvider; - core.application.register({ id: APP_ID, title: NOT_INTERNATIONALIZED_PRODUCT_NAME, @@ -490,7 +487,6 @@ export class LensPlugin { return mountApp(core, params, { createEditorFrame: frameStart.createInstance, attributeService: getLensAttributeService(coreStart, deps), - getPresentationUtilContext, topNavMenuEntryGenerators: this.topNavMenuEntries, locator: this.locator, }); diff --git a/x-pack/plugins/maps/public/kibana_services.ts b/x-pack/plugins/maps/public/kibana_services.ts index e6f65fc67866d..ea31df8734ade 100644 --- a/x-pack/plugins/maps/public/kibana_services.ts +++ b/x-pack/plugins/maps/public/kibana_services.ts @@ -89,7 +89,6 @@ export const getNavigateToApp = () => coreStart.application.navigateToApp; export const getUrlForApp = () => coreStart.application.getUrlForApp; export const getNavigateToUrl = () => coreStart.application.navigateToUrl; export const getSavedObjectsTagging = () => pluginsStart.savedObjectsTagging; -export const getPresentationUtilContext = () => pluginsStart.presentationUtil.ContextProvider; export const getSpacesApi = () => pluginsStart.spaces; export const getTheme = () => coreStart.theme; export const getApplication = () => coreStart.application; diff --git a/x-pack/plugins/maps/public/routes/map_page/top_nav_config.tsx b/x-pack/plugins/maps/public/routes/map_page/top_nav_config.tsx index 706b3b58ca979..d9b7aec6612f3 100644 --- a/x-pack/plugins/maps/public/routes/map_page/top_nav_config.tsx +++ b/x-pack/plugins/maps/public/routes/map_page/top_nav_config.tsx @@ -24,7 +24,6 @@ import { getInspector, getCoreOverlays, getSavedObjectsTagging, - getPresentationUtilContext, } from '../../kibana_services'; import { MAP_EMBEDDABLE_NAME } from '../../../common/constants'; import { SavedMap } from './saved_map'; @@ -210,7 +209,6 @@ export function getTopNavConfig({ defaultMessage: 'map', }), }; - const PresentationUtilContext = getPresentationUtilContext(); let saveModal; @@ -251,7 +249,7 @@ export function getTopNavConfig({ ); } - showSaveModal(saveModal, PresentationUtilContext); + showSaveModal(saveModal); }, }); diff --git a/x-pack/plugins/ml/public/application/aiops/change_point_detection.tsx b/x-pack/plugins/ml/public/application/aiops/change_point_detection.tsx index 146a3efc9cfcd..f9c2e7846be91 100644 --- a/x-pack/plugins/ml/public/application/aiops/change_point_detection.tsx +++ b/x-pack/plugins/ml/public/application/aiops/change_point_detection.tsx @@ -64,7 +64,6 @@ export const ChangePointDetectionPage: FC = () => { 'i18n', 'lens', 'notifications', - 'presentationUtil', 'share', 'storage', 'theme', diff --git a/x-pack/plugins/ml/public/application/routing/routes/explorer/state_manager.tsx b/x-pack/plugins/ml/public/application/routing/routes/explorer/state_manager.tsx index d61849436c73d..87983d2c61603 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/explorer/state_manager.tsx +++ b/x-pack/plugins/ml/public/application/routing/routes/explorer/state_manager.tsx @@ -39,7 +39,7 @@ export const ExplorerUrlStateManager: FC = ({ jobsWithTimeRange, }) => { const { - services: { cases, presentationUtil, uiSettings, mlServices }, + services: { cases, uiSettings, mlServices }, } = useMlKibana(); const { mlApi } = mlServices; @@ -194,7 +194,6 @@ export const ExplorerUrlStateManager: FC = ({ } const CasesContext = cases?.ui.getCasesContext() ?? React.Fragment; - const PresentationContextProvider = presentationUtil?.ContextProvider ?? React.Fragment; const casesPermissions = cases?.helpers.canUseCases(); @@ -218,27 +217,25 @@ export const ExplorerUrlStateManager: FC = ({ - - {jobsWithTimeRange.length === 0 ? ( - - ) : ( - - )} - + {jobsWithTimeRange.length === 0 ? ( + + ) : ( + + )}
); diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_page.tsx b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_page.tsx index 982884911e582..d673aca1e74e3 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_page.tsx +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_page.tsx @@ -33,9 +33,8 @@ export const TimeSeriesExplorerPage: FC { const { - services: { cases, docLinks, presentationUtil }, + services: { cases, docLinks }, } = useMlKibana(); - const PresentationContextProvider = presentationUtil?.ContextProvider ?? React.Fragment; const CasesContext = cases?.ui.getCasesContext() ?? React.Fragment; const casesPermissions = cases?.helpers.canUseCases(); const helpLink = docLinks.links.ml.anomalyDetection; @@ -65,7 +64,7 @@ export const TimeSeriesExplorerPage: FC )} - {children} + {children} diff --git a/x-pack/plugins/observability_solution/observability/public/application/index.tsx b/x-pack/plugins/observability_solution/observability/public/application/index.tsx index 9c56ec1bb54ec..3ae624d2f8ea1 100644 --- a/x-pack/plugins/observability_solution/observability/public/application/index.tsx +++ b/x-pack/plugins/observability_solution/observability/public/application/index.tsx @@ -83,52 +83,46 @@ export const renderApp = ({ const ApplicationUsageTrackingProvider = usageCollection?.components.ApplicationUsageTrackingProvider ?? React.Fragment; const CloudProvider = plugins.cloud?.CloudContextProvider ?? React.Fragment; - const PresentationContextProvider = plugins.presentationUtil?.ContextProvider ?? React.Fragment; ReactDOM.render( - - - - - + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + , element ); diff --git a/x-pack/plugins/observability_solution/slo/public/application.tsx b/x-pack/plugins/observability_solution/slo/public/application.tsx index de8851d2dd67c..b6291b5286148 100644 --- a/x-pack/plugins/observability_solution/slo/public/application.tsx +++ b/x-pack/plugins/observability_solution/slo/public/application.tsx @@ -82,8 +82,6 @@ export const renderApp = ({ usageCollection?.components.ApplicationUsageTrackingProvider ?? React.Fragment; const CloudProvider = plugins.cloud?.CloudContextProvider ?? React.Fragment; - const PresentationContextProvider = plugins.presentationUtil?.ContextProvider ?? React.Fragment; - const unregisterPrompts = plugins.observabilityAIAssistant?.service.setScreenContext({ starterPrompts: [ { @@ -109,50 +107,45 @@ export const renderApp = ({ ReactDOM.render( - - - - - + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + , element ); diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/synthetics_app.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/synthetics_app.tsx index 014043efa5cee..0dd010e7b78e3 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/synthetics_app.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/synthetics_app.tsx @@ -24,15 +24,8 @@ import { PageRouter } from './routes'; import { setBasePath, store } from './state'; const Application = (props: SyntheticsAppProps) => { - const { - basePath, - canSave, - coreStart, - startPlugins, - renderGlobalHelpControls, - setBadge, - appMountParameters, - } = props; + const { basePath, canSave, coreStart, renderGlobalHelpControls, setBadge, appMountParameters } = + props; useEffect(() => { renderGlobalHelpControls(); @@ -55,9 +48,6 @@ const Application = (props: SyntheticsAppProps) => { store.dispatch(setBasePath(basePath)); - const PresentationContextProvider = - startPlugins.presentationUtil?.ContextProvider ?? React.Fragment; - return ( { }} > - - - - -
- - - - - -
-
-
-
-
+ + + +
+ + + + + +
+
+
+