From 545b32adb48aeb1225632eb19328d8f2240d8414 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Tue, 19 Jul 2022 11:52:41 +0300 Subject: [PATCH 1/2] Added await for `isEditable` in top_nav EditorMenu. --- .../application/top_nav/editor_menu.tsx | 45 ++++++++++++++----- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx b/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx index 0422149b54a88..941a45cc6b956 100644 --- a/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx +++ b/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import React, { useCallback } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { EuiContextMenu, EuiContextMenuPanelItemDescriptor, @@ -19,7 +19,11 @@ import { METRIC_TYPE } from '@kbn/analytics'; import { i18n } from '@kbn/i18n'; import { BaseVisType, VisGroups, VisTypeAlias } from '@kbn/visualizations-plugin/public'; import { SolutionToolbarPopover } from '@kbn/presentation-util-plugin/public'; -import { EmbeddableFactoryDefinition, EmbeddableInput } from '../../services/embeddable'; +import { + EmbeddableFactory, + EmbeddableFactoryDefinition, + EmbeddableInput, +} from '../../services/embeddable'; import { useKibana } from '../../services/kibana_react'; import { DashboardAppServices } from '../../types'; import { DashboardContainer } from '..'; @@ -41,10 +45,34 @@ interface FactoryGroup { factories: EmbeddableFactoryDefinition[]; } +interface UnwrappedEmbeddableFactory { + factory: EmbeddableFactory; + isEditable: boolean; +} + export const EditorMenu = ({ dashboardContainer, createNewVisType }: Props) => { const { core, embeddable, visualizations, usageCollection, uiSettings } = useKibana().services; + const embeddableFactories = useMemo( + () => (embeddable ? Array.from(embeddable.getEmbeddableFactories()) : []), + [embeddable] + ); + const [unwrappedEmbeddableFactories, setUnwrappedEmbeddableFactories] = useState< + UnwrappedEmbeddableFactory[] + >([]); + + useEffect(() => { + Promise.all( + embeddableFactories.map>(async (factory) => ({ + factory, + isEditable: await factory.isEditable(), + })) + ).then((factories) => { + setUnwrappedEmbeddableFactories(factories); + }); + }, [embeddableFactories]); + const IS_DARK_THEME = uiSettings.get('theme:darkMode'); const LABS_ENABLED = uiSettings.get('visualize:enableLabs'); @@ -89,13 +117,10 @@ export const EditorMenu = ({ dashboardContainer, createNewVisType }: Props) => { a === b ? 0 : a ? -1 : 1 ); - const factories = embeddable - ? Array.from(embeddable.getEmbeddableFactories()).filter( - ({ type, isEditable, canCreateNew, isContainerType }) => - // @ts-expect-error ts 4.5 upgrade - isEditable() && !isContainerType && canCreateNew() && type !== 'visualization' - ) - : []; + const factories = unwrappedEmbeddableFactories.filter( + ({ isEditable, factory: { type, canCreateNew, isContainerType } }) => + isEditable && !isContainerType && canCreateNew() && type !== 'visualization' + ); const factoryGroupMap: Record = {}; const ungroupedFactories: EmbeddableFactoryDefinition[] = []; @@ -103,7 +128,7 @@ export const EditorMenu = ({ dashboardContainer, createNewVisType }: Props) => { let panelCount = 1 + aggBasedPanelID; - factories.forEach((factory: EmbeddableFactoryDefinition, index) => { + factories.forEach(({ factory }) => { const { grouping } = factory; if (grouping) { From 2457e7446cb67010da28424a41d787d7ebea8841 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Tue, 19 Jul 2022 12:17:49 +0300 Subject: [PATCH 2/2] Added await for `isEditable` in top_nav EditorMenu at Canvas. --- .../editor_menu/editor_menu.tsx | 56 ++++++++++++++----- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx index 8c10efe1b10d9..ed34b2818b531 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx @@ -5,10 +5,14 @@ * 2.0. */ -import React, { FC, useCallback } from 'react'; +import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import { useLocation } from 'react-router-dom'; import { BaseVisType, VisGroups, VisTypeAlias } from '@kbn/visualizations-plugin/public'; -import { EmbeddableFactoryDefinition, EmbeddableInput } from '@kbn/embeddable-plugin/public'; +import { + EmbeddableFactory, + EmbeddableFactoryDefinition, + EmbeddableInput, +} from '@kbn/embeddable-plugin/public'; import { trackCanvasUiMetric, METRIC_TYPE } from '../../../lib/ui_metric'; import { useEmbeddablesService, @@ -27,6 +31,11 @@ interface Props { addElement: (element: Partial) => void; } +interface UnwrappedEmbeddableFactory { + factory: EmbeddableFactory; + isEditable: boolean; +} + export const EditorMenu: FC = ({ addElement }) => { const embeddablesService = useEmbeddablesService(); const { pathname, search, hash } = useLocation(); @@ -35,6 +44,26 @@ export const EditorMenu: FC = ({ addElement }) => { const visualizationsService = useVisualizationsService(); const IS_DARK_THEME = platformService.getUISetting('theme:darkMode'); + const embeddableFactories = useMemo( + () => (embeddablesService ? Array.from(embeddablesService.getEmbeddableFactories()) : []), + [embeddablesService] + ); + + const [unwrappedEmbeddableFactories, setUnwrappedEmbeddableFactories] = useState< + UnwrappedEmbeddableFactory[] + >([]); + + useEffect(() => { + Promise.all( + embeddableFactories.map>(async (factory) => ({ + factory, + isEditable: await factory.isEditable(), + })) + ).then((factories) => { + setUnwrappedEmbeddableFactories(factories); + }); + }, [embeddableFactories]); + const createNewVisType = useCallback( (visType?: BaseVisType | VisTypeAlias) => () => { let path = ''; @@ -113,18 +142,17 @@ export const EditorMenu: FC = ({ addElement }) => { a === b ? 0 : a ? -1 : 1 ); - const factories = embeddablesService - ? Array.from(embeddablesService.getEmbeddableFactories()).filter( - ({ type, isEditable, canCreateNew, isContainerType }) => - // @ts-expect-error ts 4.5 upgrade - isEditable() && - !isContainerType && - canCreateNew() && - !['visualization', 'ml'].some((factoryType) => { - return type.includes(factoryType); - }) - ) - : []; + const factories = unwrappedEmbeddableFactories + .filter( + ({ isEditable, factory: { type, canCreateNew, isContainerType } }) => + isEditable && + !isContainerType && + canCreateNew() && + !['visualization', 'ml'].some((factoryType) => { + return type.includes(factoryType); + }) + ) + .map(({ factory }) => factory); const promotedVisTypes = getVisTypesByGroup(VisGroups.PROMOTED);