diff --git a/frontend/packages/console-app/src/components/console-operator/ConsoleOperatorConfig.tsx b/frontend/packages/console-app/src/components/console-operator/ConsoleOperatorConfig.tsx index 7f9d945327f..3d133a772ad 100644 --- a/frontend/packages/console-app/src/components/console-operator/ConsoleOperatorConfig.tsx +++ b/frontend/packages/console-app/src/components/console-operator/ConsoleOperatorConfig.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { PluginInfoEntry } from '@openshift/dynamic-plugin-sdk'; import { Alert, Button } from '@patternfly/react-core'; import { PencilAltIcon } from '@patternfly/react-icons/dist/esm/icons/pencil-alt-icon'; import { @@ -30,7 +31,7 @@ import { useK8sWatchResource } from '@console/internal/components/utils/k8s-watc import { KebabAction } from '@console/internal/components/utils/kebab'; import { asAccessReview, RequireCreatePermission } from '@console/internal/components/utils/rbac'; import { ResourceLink } from '@console/internal/components/utils/resource-link'; -import { EmptyBox, LoadingBox } from '@console/internal/components/utils/status-box'; +import { EmptyBox } from '@console/internal/components/utils/status-box'; import { ConsoleOperatorConfigModel, ConsolePluginModel } from '@console/internal/models'; import { ConsolePluginKind, @@ -39,11 +40,6 @@ import { referenceForModel, } from '@console/internal/module/k8s'; import { RootState } from '@console/internal/redux'; -import { - isLoadedDynamicPluginInfo, - DynamicPluginInfo, - isNotLoadedDynamicPluginInfo, -} from '@console/plugin-sdk/src'; import { usePluginInfo } from '@console/plugin-sdk/src/api/usePluginInfo'; import PaneBody from '@console/shared/src/components/layout/PaneBody'; import { consolePluginModal } from '@console/shared/src/components/modals/ConsolePluginModal'; @@ -94,7 +90,7 @@ export const useConsoleOperatorConfigData = () => { export const ConsolePluginStatus: React.FC = ({ status, errorMessage, -}) => ; +}) => ; export const ConsolePluginEnabledStatus: React.FC = ({ pluginName, @@ -159,7 +155,7 @@ export const ConsolePluginCSPStatus: React.FC = ({ ); }; -const ConsolePluginsTable: React.FC = ({ obj, rows, loaded }) => { +const ConsolePluginsTable: React.FC = ({ obj, rows }) => { const { t } = useTranslation(); const [sortBy, setSortBy] = React.useState(() => ({ @@ -223,9 +219,7 @@ const ConsolePluginsTable: React.FC = ({ obj, rows, lo const sortedRows = React.useMemo(() => rows.sort(compare), [rows, compare]); - return !loaded ? ( - - ) : ( + return ( {obj.spec?.managementState === 'Unmanaged' && ( = ({ obj, rows, lo }; const DevPluginsPage: React.FCC = (props) => { - const [pluginInfo, pluginInfoLoaded] = usePluginInfo(); + const pluginInfo = usePluginInfo(); const cspViolations = useSelector(({ UI }) => UI.get('pluginCSPViolations'), ); const rows = React.useMemo( () => - !pluginInfoLoaded - ? [] - : pluginInfo.filter(isLoadedDynamicPluginInfo).map((plugin) => ({ - name: plugin.metadata.name, - version: plugin.metadata.version, - description: plugin.metadata?.customProperties?.console?.description, - enabled: plugin.enabled, - status: plugin.status, - hasCSPViolations: cspViolations[plugin.metadata.name] ?? false, - })), - [pluginInfo, pluginInfoLoaded, cspViolations], + pluginInfo + .filter((plugin) => plugin.status === 'loaded') + .map((plugin) => ({ + name: plugin.metadata.name, + version: plugin.metadata.version, + description: plugin.metadata?.customProperties?.console?.description, + enabled: plugin.enabled, + status: plugin.status, + hasCSPViolations: cspViolations[plugin.metadata.name] ?? false, + })), + [pluginInfo, cspViolations], ); - return ; + return ; }; const PluginsPage: React.FC = (props) => { - const [pluginInfo] = usePluginInfo(); + const pluginInfo = usePluginInfo(); const [consolePlugins, consolePluginsLoaded] = useK8sWatchResource({ isList: true, kind: referenceForModel(ConsolePluginModel), @@ -342,10 +336,10 @@ const PluginsPage: React.FC = (props) => { const pluginName = plugin?.metadata?.name; const enabled = enabledPlugins.includes(pluginName); const loadedPluginInfo = pluginInfo - .filter(isLoadedDynamicPluginInfo) + .filter((p) => p.status === 'loaded') .find((i) => i?.metadata?.name === pluginName); const notLoadedPluginInfo = pluginInfo - .filter(isNotLoadedDynamicPluginInfo) + .filter((p) => p.status !== 'loaded') .find((i) => i?.pluginName === pluginName); if (loadedPluginInfo) { return { @@ -362,15 +356,15 @@ const PluginsPage: React.FC = (props) => { enabled, status: notLoadedPluginInfo?.status, errorMessage: - notLoadedPluginInfo?.status === 'Failed' ? notLoadedPluginInfo?.errorMessage : undefined, + notLoadedPluginInfo?.status === 'failed' ? notLoadedPluginInfo?.errorMessage : undefined, errorCause: - notLoadedPluginInfo?.status === 'Failed' + notLoadedPluginInfo?.status === 'failed' ? notLoadedPluginInfo?.errorCause?.toString() : undefined, }; }); }, [consolePluginsLoaded, consolePlugins, pluginInfo, enabledPlugins, cspViolations]); - return ; + return ; }; const ConsoleOperatorConfigPluginsPage: React.FC = developmentMode @@ -425,7 +419,7 @@ export type ConsolePluginTableRow = { name: string; version?: string; description?: string; - status: DynamicPluginInfo['status']; + status: PluginInfoEntry['status']; enabled: boolean; errorMessage?: string; hasCSPViolations?: boolean; @@ -439,11 +433,10 @@ type TableColumn = { type ConsolePluginsTableProps = ConsoleOperatorConfigPageProps & { rows: ConsolePluginTableRow[]; - loaded: boolean; }; type ConsolePluginStatusProps = { - status: DynamicPluginInfo['status']; + status: PluginInfoEntry['status']; errorMessage?: string; }; diff --git a/frontend/packages/console-app/src/components/console-operator/ConsolePluginDescriptionDetail.tsx b/frontend/packages/console-app/src/components/console-operator/ConsolePluginDescriptionDetail.tsx index 6f8c87def28..362b22dbae3 100644 --- a/frontend/packages/console-app/src/components/console-operator/ConsolePluginDescriptionDetail.tsx +++ b/frontend/packages/console-app/src/components/console-operator/ConsolePluginDescriptionDetail.tsx @@ -1,24 +1,23 @@ import * as React from 'react'; import { DetailsItemComponentProps } from '@console/dynamic-plugin-sdk/src/extensions/details-item'; -import { isLoadedDynamicPluginInfo } from '@console/plugin-sdk/src'; import { usePluginInfo } from '@console/plugin-sdk/src/api/usePluginInfo'; import { DASH } from '@console/shared/src/constants'; const ConsolePluginDescriptionDetail: React.FC = ({ obj }) => { const pluginName = React.useMemo(() => obj?.metadata?.name, [obj?.metadata?.name]); - const [pluginInfoEntries] = usePluginInfo(); + const pluginInfoEntries = usePluginInfo(); const pluginInfo = React.useMemo( () => pluginInfoEntries.find((entry) => - isLoadedDynamicPluginInfo(entry) + entry.status === 'loaded' ? entry.metadata.name === pluginName : entry.pluginName === pluginName, ), [pluginInfoEntries, pluginName], ); - return isLoadedDynamicPluginInfo(pluginInfo) ? ( + return pluginInfo?.status === 'loaded' ? ( <>{pluginInfo.metadata.customProperties?.console?.description || DASH} ) : ( <>{DASH} diff --git a/frontend/packages/console-app/src/components/console-operator/ConsolePluginEnabledStatusDetail.tsx b/frontend/packages/console-app/src/components/console-operator/ConsolePluginEnabledStatusDetail.tsx index 195fb5e8091..a3e514da01f 100644 --- a/frontend/packages/console-app/src/components/console-operator/ConsolePluginEnabledStatusDetail.tsx +++ b/frontend/packages/console-app/src/components/console-operator/ConsolePluginEnabledStatusDetail.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { DASH } from '@console/dynamic-plugin-sdk/src/app/constants'; import { DetailsItemComponentProps } from '@console/dynamic-plugin-sdk/src/extensions/details-item'; -import { isLoadedDynamicPluginInfo } from '@console/plugin-sdk/src'; import { usePluginInfo } from '@console/plugin-sdk/src/api/usePluginInfo'; import { ConsolePluginEnabledStatus, @@ -10,7 +9,7 @@ import { } from './ConsoleOperatorConfig'; const ConsolePluginEnabledStatusDetail: React.FC = ({ obj }) => { - const [pluginInfoEntries] = usePluginInfo(); + const pluginInfoEntries = usePluginInfo(); const { consoleOperatorConfig, consoleOperatorConfigLoaded } = useConsoleOperatorConfigData(); const pluginName = React.useMemo(() => obj?.metadata?.name, [obj?.metadata?.name]); @@ -18,7 +17,7 @@ const ConsolePluginEnabledStatusDetail: React.FC = ({ const pluginInfo = React.useMemo( () => pluginInfoEntries.find((entry) => - isLoadedDynamicPluginInfo(entry) + entry.status === 'loaded' ? entry.metadata.name === pluginName : entry.pluginName === pluginName, ), @@ -28,12 +27,12 @@ const ConsolePluginEnabledStatusDetail: React.FC = ({ consoleOperatorConfig?.spec?.plugins, ]); - return consoleOperatorConfigLoaded ? ( + return consoleOperatorConfigLoaded && pluginName ? ( diff --git a/frontend/packages/console-app/src/components/console-operator/ConsolePluginStatusDetail.tsx b/frontend/packages/console-app/src/components/console-operator/ConsolePluginStatusDetail.tsx index 97753a86ff4..3c01d98f587 100644 --- a/frontend/packages/console-app/src/components/console-operator/ConsolePluginStatusDetail.tsx +++ b/frontend/packages/console-app/src/components/console-operator/ConsolePluginStatusDetail.tsx @@ -1,18 +1,17 @@ import * as React from 'react'; import { DetailsItemComponentProps } from '@console/dynamic-plugin-sdk/src/extensions/details-item'; -import { isLoadedDynamicPluginInfo } from '@console/plugin-sdk/src'; import { usePluginInfo } from '@console/plugin-sdk/src/api/usePluginInfo'; import { DASH } from '@console/shared/src/constants'; import { ConsolePluginStatus } from './ConsoleOperatorConfig'; const ConsolePluginStatusDetail: React.FC = ({ obj }) => { - const [pluginInfoEntries] = usePluginInfo(); + const pluginInfoEntries = usePluginInfo(); const pluginName = React.useMemo(() => obj?.metadata?.name, [obj?.metadata?.name]); const pluginInfo = React.useMemo( () => pluginInfoEntries.find((entry) => - isLoadedDynamicPluginInfo(entry) + entry.status === 'loaded' ? entry.metadata.name === pluginName : entry.pluginName === pluginName, ), @@ -22,7 +21,7 @@ const ConsolePluginStatusDetail: React.FC = ({ obj }) return pluginInfo ? ( ) : ( <>{DASH} diff --git a/frontend/packages/console-app/src/components/console-operator/ConsolePluginVersionDetail.tsx b/frontend/packages/console-app/src/components/console-operator/ConsolePluginVersionDetail.tsx index 199546b8a13..6b3ecee366c 100644 --- a/frontend/packages/console-app/src/components/console-operator/ConsolePluginVersionDetail.tsx +++ b/frontend/packages/console-app/src/components/console-operator/ConsolePluginVersionDetail.tsx @@ -1,25 +1,24 @@ import * as React from 'react'; import { DetailsItemComponentProps } from '@console/dynamic-plugin-sdk/src/extensions/details-item'; -import { isLoadedDynamicPluginInfo } from '@console/plugin-sdk/src'; import { usePluginInfo } from '@console/plugin-sdk/src/api/usePluginInfo'; import { DASH } from '@console/shared/src/constants'; const ConsolePluginVersionDetail: React.FC = ({ obj }) => { - const [pluginInfoEntries] = usePluginInfo(); + const pluginInfoEntries = usePluginInfo(); const pluginName = React.useMemo(() => obj?.metadata?.name, [obj?.metadata?.name]); const pluginInfo = React.useMemo( () => pluginInfoEntries.find((entry) => - isLoadedDynamicPluginInfo(entry) + entry.status === 'loaded' ? entry.metadata.name === pluginName : entry.pluginName === pluginName, ), [pluginInfoEntries, pluginName], ); - return isLoadedDynamicPluginInfo(pluginInfo) ? <>{pluginInfo.metadata.version} : <>{DASH}; + return pluginInfo?.status === 'loaded' ? <>{pluginInfo.metadata.version} : <>{DASH}; }; export default ConsolePluginVersionDetail; diff --git a/frontend/packages/console-app/src/components/dashboards-page/dynamic-plugins-health-resource/DynamicPluginsPopover.tsx b/frontend/packages/console-app/src/components/dashboards-page/dynamic-plugins-health-resource/DynamicPluginsPopover.tsx index 5deca91790c..cc8b6805719 100644 --- a/frontend/packages/console-app/src/components/dashboards-page/dynamic-plugins-health-resource/DynamicPluginsPopover.tsx +++ b/frontend/packages/console-app/src/components/dashboards-page/dynamic-plugins-health-resource/DynamicPluginsPopover.tsx @@ -8,21 +8,22 @@ import { PluginCSPViolations } from '@console/internal/actions/ui'; import { ConsoleOperatorConfigModel, ConsolePluginModel } from '@console/internal/models'; import { ConsolePluginKind, referenceForModel } from '@console/internal/module/k8s'; import { RootState } from '@console/internal/redux'; -import { isLoadedDynamicPluginInfo, isNotLoadedDynamicPluginInfo } from '@console/plugin-sdk/src'; import { usePluginInfo } from '@console/plugin-sdk/src/api/usePluginInfo'; import { StatusPopupSection } from '@console/shared/src/components/dashboard/status-card/StatusPopup'; import NotLoadedDynamicPlugins from './NotLoadedDynamicPlugins'; const DynamicPluginsPopover: React.FC = ({ consolePlugins }) => { const { t } = useTranslation(); - const [pluginInfoEntries] = usePluginInfo(); + const pluginInfoEntries = usePluginInfo(); const cspViolations = useSelector(({ UI }) => UI.get('pluginCSPViolations'), ); - const notLoadedDynamicPluginInfo = pluginInfoEntries.filter(isNotLoadedDynamicPluginInfo); - const failedPlugins = notLoadedDynamicPluginInfo.filter((plugin) => plugin.status === 'Failed'); - const pendingPlugins = notLoadedDynamicPluginInfo.filter((plugin) => plugin.status === 'Pending'); - const loadedPlugins = pluginInfoEntries.filter(isLoadedDynamicPluginInfo); + const notLoadedDynamicPluginInfo = pluginInfoEntries.filter( + (plugin) => plugin.status !== 'loaded', + ); + const failedPlugins = notLoadedDynamicPluginInfo.filter((plugin) => plugin.status === 'failed'); + const pendingPlugins = notLoadedDynamicPluginInfo.filter((plugin) => plugin.status === 'pending'); + const loadedPlugins = pluginInfoEntries.filter((plugin) => plugin.status === 'loaded'); const loadedPluginsWithCSPViolations = loadedPlugins.filter( (plugin) => cspViolations[plugin.metadata.name] ?? false, ); diff --git a/frontend/packages/console-app/src/components/dashboards-page/dynamic-plugins-health-resource/status.ts b/frontend/packages/console-app/src/components/dashboards-page/dynamic-plugins-health-resource/status.ts index 2661e8bad20..3179cbd5bf5 100644 --- a/frontend/packages/console-app/src/components/dashboards-page/dynamic-plugins-health-resource/status.ts +++ b/frontend/packages/console-app/src/components/dashboards-page/dynamic-plugins-health-resource/status.ts @@ -3,13 +3,13 @@ import { pluginStore } from '@console/internal/plugins'; export const getDynamicPluginHealthState = (): SubsystemHealth => { const dynamicPluginInfo = pluginStore.getPluginInfo(); - if (dynamicPluginInfo.some((plugin) => plugin.status === 'Failed')) { + if (dynamicPluginInfo.some((plugin) => plugin.status === 'failed')) { return { state: HealthState.ERROR }; } - if (dynamicPluginInfo.some((plugin) => plugin.status === 'Pending')) { + if (dynamicPluginInfo.some((plugin) => plugin.status === 'pending')) { return { state: HealthState.PROGRESS }; } - if (dynamicPluginInfo.every((plugin) => plugin.status === 'Loaded')) { + if (dynamicPluginInfo.every((plugin) => plugin.status === 'loaded')) { return { state: HealthState.OK }; } return { state: HealthState.UNKNOWN }; diff --git a/frontend/packages/console-app/src/hooks/useCSPViolationDetector.tsx b/frontend/packages/console-app/src/hooks/useCSPViolationDetector.tsx index e3d05edf6e0..9f04eac1b08 100644 --- a/frontend/packages/console-app/src/hooks/useCSPViolationDetector.tsx +++ b/frontend/packages/console-app/src/hooks/useCSPViolationDetector.tsx @@ -5,7 +5,6 @@ import { useTranslation } from 'react-i18next'; import { useDispatch, useSelector } from 'react-redux'; import { setPluginCSPViolations, PluginCSPViolations } from '@console/internal/actions/ui'; import { RootState } from '@console/internal/redux'; -import { isLoadedDynamicPluginInfo } from '@console/plugin-sdk/src'; import { usePluginStore } from '@console/plugin-sdk/src/api/usePluginStore'; import { useToast } from '@console/shared/src/components/toast'; import { IS_PRODUCTION } from '@console/shared/src/constants/common'; @@ -104,13 +103,13 @@ export const useCSPViolationDetector = () => { const pluginInfo = pluginStore .getPluginInfo() .find((entry) => - isLoadedDynamicPluginInfo(entry) + entry.status === 'loaded' ? entry.metadata.name === pluginName : entry.pluginName === pluginName, ); const validPlugin = !!pluginInfo; - const pluginIsLoaded = validPlugin && pluginInfo.status === 'Loaded'; + const pluginIsLoaded = validPlugin && pluginInfo.status === 'loaded'; // eslint-disable-next-line no-console console.warn( diff --git a/frontend/packages/console-dynamic-plugin-sdk/src/runtime/__tests__/plugin-dependencies.spec.ts b/frontend/packages/console-dynamic-plugin-sdk/src/runtime/__tests__/plugin-dependencies.spec.ts index 31fa9ecfd98..9739f59470d 100644 --- a/frontend/packages/console-dynamic-plugin-sdk/src/runtime/__tests__/plugin-dependencies.spec.ts +++ b/frontend/packages/console-dynamic-plugin-sdk/src/runtime/__tests__/plugin-dependencies.spec.ts @@ -28,7 +28,7 @@ describe('resolvePluginDependencies', () => { const getLoadedDynamicPluginInfo = ( manifest: StandardConsolePluginManifest, ): LoadedDynamicPluginInfo => ({ - status: 'Loaded', + status: 'loaded', pluginID: getPluginID(manifest), metadata: _.omit(manifest, ['extensions', 'loadScripts', 'registrationMethod']), enabled: true, @@ -37,14 +37,14 @@ describe('resolvePluginDependencies', () => { const getPendingDynamicPluginInfo = ( manifest: StandardConsolePluginManifest, ): NotLoadedDynamicPluginInfo => ({ - status: 'Pending', + status: 'pending', pluginName: manifest.name, }); const getFailedDynamicPluginInfo = ( manifest: StandardConsolePluginManifest, ): NotLoadedDynamicPluginInfo => ({ - status: 'Failed', + status: 'failed', pluginName: manifest.name, errorMessage: `Test error message for plugin ${manifest.name}`, }); diff --git a/frontend/packages/console-dynamic-plugin-sdk/src/runtime/plugin-dependencies.ts b/frontend/packages/console-dynamic-plugin-sdk/src/runtime/plugin-dependencies.ts index 6743081e075..6fe3d045550 100644 --- a/frontend/packages/console-dynamic-plugin-sdk/src/runtime/plugin-dependencies.ts +++ b/frontend/packages/console-dynamic-plugin-sdk/src/runtime/plugin-dependencies.ts @@ -119,14 +119,14 @@ export const resolvePluginDependencies = ( const unsubListener = subscribeToDynamicPlugins((entries) => { const loadedPlugins = entries.reduce>((acc, e) => { - if (e.status === 'Loaded' && preloadPluginNames.includes(e.metadata.name)) { + if (e.status === 'loaded' && preloadPluginNames.includes(e.metadata.name)) { acc[e.metadata.name] = e.metadata.version; } return acc; }, {}); const failedPluginNames = entries.reduce((acc, e) => { - if (e.status === 'Failed' && preloadPluginNames.includes(e.pluginName)) { + if (e.status === 'failed' && preloadPluginNames.includes(e.pluginName)) { acc.push(e.pluginName); } return acc; diff --git a/frontend/packages/console-plugin-sdk/src/__tests__/store.spec.ts b/frontend/packages/console-plugin-sdk/src/__tests__/store.spec.ts index 78acd38f276..16af874cbcc 100644 --- a/frontend/packages/console-plugin-sdk/src/__tests__/store.spec.ts +++ b/frontend/packages/console-plugin-sdk/src/__tests__/store.spec.ts @@ -282,11 +282,11 @@ describe('PluginStore', () => { expect(store.getAllowedDynamicPluginNames()).toEqual(['TestA', 'TestB']); expect(store.getPluginInfo()).toEqual([ { - status: 'Pending', + status: 'pending', pluginName: 'TestA', }, { - status: 'Pending', + status: 'pending', pluginName: 'TestB', }, ]); @@ -582,7 +582,7 @@ describe('PluginStore', () => { expect(store.getExtensions()).toEqual([]); expect(store.getPluginInfo()).toEqual([ { - status: 'Loaded', + status: 'loaded', pluginID: 'Test@1.2.3', metadata: _.omit(manifest, ['extensions', 'loadScripts', 'registrationMethod']), enabled: false, @@ -954,11 +954,11 @@ describe('PluginStore', () => { expect(store.getPluginInfo()).toEqual([ { - status: 'Pending', + status: 'pending', pluginName: 'TestA', }, { - status: 'Pending', + status: 'pending', pluginName: 'TestB', }, ]); @@ -967,13 +967,13 @@ describe('PluginStore', () => { expect(store.getPluginInfo()).toEqual([ { - status: 'Loaded', + status: 'loaded', pluginID: 'TestA@1.2.3', metadata: _.omit(manifest, ['extensions', 'loadScripts', 'registrationMethod']), enabled: false, }, { - status: 'Pending', + status: 'pending', pluginName: 'TestB', }, ]); @@ -982,26 +982,26 @@ describe('PluginStore', () => { expect(store.getPluginInfo()).toEqual([ { - status: 'Loaded', + status: 'loaded', pluginID: 'TestA@1.2.3', metadata: _.omit(manifest, ['extensions', 'loadScripts', 'registrationMethod']), enabled: true, }, { - status: 'Pending', + status: 'pending', pluginName: 'TestB', }, ]); expect(store.getPluginInfo()).toEqual([ { - status: 'Loaded', + status: 'loaded', pluginID: 'TestA@1.2.3', metadata: _.omit(manifest, ['extensions', 'loadScripts', 'registrationMethod']), enabled: true, }, { - status: 'Pending', + status: 'pending', pluginName: 'TestB', }, ]); @@ -1010,13 +1010,13 @@ describe('PluginStore', () => { expect(store.getPluginInfo()).toEqual([ { - status: 'Loaded', + status: 'loaded', pluginID: 'TestA@1.2.3', metadata: _.omit(manifest, ['extensions', 'loadScripts', 'registrationMethod']), enabled: true, }, { - status: 'Failed', + status: 'failed', pluginName: 'TestB', errorMessage: 'Test error message', errorCause: new Error('Boom'), diff --git a/frontend/packages/console-plugin-sdk/src/api/usePluginInfo.ts b/frontend/packages/console-plugin-sdk/src/api/usePluginInfo.ts index bbb218ba592..f6d1b68bf5d 100644 --- a/frontend/packages/console-plugin-sdk/src/api/usePluginInfo.ts +++ b/frontend/packages/console-plugin-sdk/src/api/usePluginInfo.ts @@ -13,7 +13,7 @@ import { subscribeToDynamicPlugins } from './pluginSubscriptionService'; * * ```ts * const Example = () => { - * const [pluginInfoEntries, allPluginsProcessed] = usePluginInfo(); + * const pluginInfoEntries = usePluginInfo(); * // process plugin entries and render your component * }; * ``` @@ -22,19 +22,17 @@ import { subscribeToDynamicPlugins } from './pluginSubscriptionService'; * * @returns Console dynamic plugin runtime information. */ -export const usePluginInfo = (): [DynamicPluginInfo[], boolean] => { +export const usePluginInfo = (): DynamicPluginInfo[] => { const forceRender = useForceRender(); const isMountedRef = useRef(true); const unsubscribeRef = useRef(null); const pluginInfoEntriesRef = useRef([]); - const allPluginsProcessedRef = useRef(false); const trySubscribe = useCallback(() => { if (unsubscribeRef.current === null) { unsubscribeRef.current = subscribeToDynamicPlugins((pluginInfoEntries) => { pluginInfoEntriesRef.current = pluginInfoEntries; - allPluginsProcessedRef.current = pluginInfoEntries.every((i) => i.status !== 'Pending'); isMountedRef.current && forceRender(); }); } @@ -57,5 +55,5 @@ export const usePluginInfo = (): [DynamicPluginInfo[], boolean] => { [tryUnsubscribe], ); - return [pluginInfoEntriesRef.current, allPluginsProcessedRef.current]; + return pluginInfoEntriesRef.current; }; diff --git a/frontend/packages/console-plugin-sdk/src/store.ts b/frontend/packages/console-plugin-sdk/src/store.ts index 7814e16c558..344ee1b9c49 100644 --- a/frontend/packages/console-plugin-sdk/src/store.ts +++ b/frontend/packages/console-plugin-sdk/src/store.ts @@ -32,13 +32,6 @@ export const getGatingFlagNames = (extensions: Extension[]): string[] => ..._.flatMap(extensions.map((e) => e.flags.disallowed)), ]); -export const isLoadedDynamicPluginInfo = (i: DynamicPluginInfo): i is LoadedDynamicPluginInfo => - i?.status === 'Loaded'; - -export const isNotLoadedDynamicPluginInfo = ( - i: DynamicPluginInfo, -): i is NotLoadedDynamicPluginInfo => i.status === 'Failed' || i.status === 'Pending'; - /** * Provides access to Console plugins and their extensions. * @@ -58,8 +51,6 @@ export class PluginStore { // Extensions contributed by dynamic plugins which are currently in use private dynamicPluginExtensions: LoadedExtension[]; - private i18nNamespaces: Set; - private readonly staticPlugins: StaticPlugin[]; // Static plugins that were disabled by loading replacement dynamic plugins @@ -76,11 +67,7 @@ export class PluginStore { private readonly listeners: VoidFunction[] = []; - constructor( - staticPlugins: ActivePlugin[] = [], - allowedDynamicPluginNames: string[] = [], - i18nNamespaces: string[] = [], - ) { + constructor(staticPlugins: ActivePlugin[] = [], allowedDynamicPluginNames: string[] = []) { this.staticPlugins = staticPlugins.map((plugin) => ({ name: plugin.name, extensions: plugin.extensions.map((e, index) => @@ -91,7 +78,6 @@ export class PluginStore { })); this.allowedDynamicPluginNames = _.uniq(allowedDynamicPluginNames); - this.i18nNamespaces = new Set(i18nNamespaces); this.updateExtensions(); } @@ -103,10 +89,6 @@ export class PluginStore { return [...this.allowedDynamicPluginNames]; } - getI18nNamespaces() { - return Array.from(this.i18nNamespaces); - } - subscribe(listener: VoidFunction): VoidFunction { let isSubscribed = true; this.listeners.push(listener); @@ -245,7 +227,7 @@ export class PluginStore { const loadedPluginEntries = Array.from(this.loadedDynamicPlugins.entries()).reduce( (acc, [pluginID, plugin]) => { acc.push({ - status: 'Loaded', + status: 'loaded', pluginID, metadata: _.omit(plugin.manifest, ['extensions', 'loadScripts', 'registrationMethod']), enabled: plugin.enabled, @@ -258,7 +240,7 @@ export class PluginStore { const failedPluginEntries = Array.from(this.failedDynamicPlugins.entries()).reduce( (acc, [pluginName, plugin]) => { acc.push({ - status: 'Failed', + status: 'failed', pluginName, errorMessage: plugin.errorMessage, errorCause: plugin.errorCause, @@ -275,7 +257,7 @@ export class PluginStore { ) .reduce((acc, pluginName) => { acc.push({ - status: 'Pending', + status: 'pending', pluginName, }); return acc; @@ -327,7 +309,7 @@ type FailedDynamicPlugin = { }; export type LoadedDynamicPluginInfo = { - status: 'Loaded'; + status: 'loaded'; pluginID: string; metadata: DynamicPluginMetadata; enabled: boolean; @@ -335,11 +317,11 @@ export type LoadedDynamicPluginInfo = { export type NotLoadedDynamicPluginInfo = | { - status: 'Pending'; + status: 'pending'; pluginName: string; } | { - status: 'Failed'; + status: 'failed'; pluginName: string; errorMessage: string; errorCause?: unknown; diff --git a/frontend/packages/integration-tests-cypress/tests/app/demo-dynamic-plugin.cy.ts b/frontend/packages/integration-tests-cypress/tests/app/demo-dynamic-plugin.cy.ts index ee87ad497ad..1bba663030d 100644 --- a/frontend/packages/integration-tests-cypress/tests/app/demo-dynamic-plugin.cy.ts +++ b/frontend/packages/integration-tests-cypress/tests/app/demo-dynamic-plugin.cy.ts @@ -55,7 +55,7 @@ const enableDemoPlugin = (enable: boolean) => { }); cy.log(`Running plugin test on ci using PLUGIN_PULL_SPEC: ${PLUGIN_PULL_SPEC}`); cy.byTestID(`${PLUGIN_NAME}-status`) - .should('include.text', enable ? 'Loaded' : '-') + .should('include.text', enable ? 'loaded' : '-') .then(() => { if (!enable) { cy.byLegacyTestID(PLUGIN_NAME).click(); diff --git a/frontend/public/components/about-modal.tsx b/frontend/public/components/about-modal.tsx index 5fc024a5362..4b438f55297 100644 --- a/frontend/public/components/about-modal.tsx +++ b/frontend/public/components/about-modal.tsx @@ -10,7 +10,6 @@ import { Trans, useTranslation } from 'react-i18next'; import { useClusterVersion } from '@console/shared/src/hooks/version'; import { BlueArrowCircleUpIcon } from '@console/shared/src/components/status/icons'; import { useCanClusterUpgrade } from '@console/shared/src/hooks/useCanClusterUpgrade'; -import { isLoadedDynamicPluginInfo } from '@console/plugin-sdk/src'; import { usePluginInfo } from '@console/plugin-sdk/src/api/usePluginInfo'; import { getBrandingDetails, MASTHEAD_TYPE, useCustomLogoURL } from './utils/branding'; import { ReleaseNotesLink } from './utils/release-notes-link'; @@ -33,11 +32,11 @@ import redHatFedoraWatermarkImg from '../imgs/red-hat-fedora-watermark.svg'; const DynamicPlugins: React.FC = () => { const { t } = useTranslation(); - const [pluginInfoEntries] = usePluginInfo(); + const pluginInfoEntries = usePluginInfo(); const [items, setItems] = React.useState([]); React.useEffect(() => { - const loadedPlugins = pluginInfoEntries.filter(isLoadedDynamicPluginInfo); + const loadedPlugins = pluginInfoEntries.filter((plugin) => plugin.status === 'loaded'); const sortedLoadedPlugins = loadedPlugins.sort((a, b) => a.metadata.name.localeCompare(b.metadata.name), ); diff --git a/frontend/public/components/app-contents.tsx b/frontend/public/components/app-contents.tsx index 5f97cda6aa4..3a53badc15c 100644 --- a/frontend/public/components/app-contents.tsx +++ b/frontend/public/components/app-contents.tsx @@ -155,10 +155,15 @@ const HorizontalPodRedirect = () => { }; const AppContents: React.FC<{}> = () => { - const [, allPluginsProcessed] = usePluginInfo(); + const pluginInfoEntries = usePluginInfo(); const location = useLocation(); const [pluginPageRoutes, inactivePluginPageRoutes] = usePluginRoutes(); + const allPluginsProcessed = React.useMemo( + () => pluginInfoEntries.every((i) => i.status !== 'pending'), + [pluginInfoEntries], + ); + const contentRouter = ( {pluginPageRoutes} diff --git a/frontend/public/components/notification-drawer.tsx b/frontend/public/components/notification-drawer.tsx index 9dfb603fc19..bde6d9ada5f 100644 --- a/frontend/public/components/notification-drawer.tsx +++ b/frontend/public/components/notification-drawer.tsx @@ -14,7 +14,7 @@ import { useTranslation } from 'react-i18next'; import i18next from 'i18next'; import { useDispatch } from 'react-redux'; import { Link, NavigateFunction, useNavigate } from 'react-router-dom-v5-compat'; -import { isNotLoadedDynamicPluginInfo, DynamicPluginInfo } from '@console/plugin-sdk'; +import { DynamicPluginInfo } from '@console/plugin-sdk'; import { usePluginInfo } from '@console/plugin-sdk/src/api/usePluginInfo'; import * as UIActions from '@console/internal/actions/ui'; import { resourcePath } from '@console/internal/components/utils/resource-link'; @@ -162,9 +162,7 @@ const getUpdateNotificationEntries = ( const newerChannelVersion = splitClusterVersionChannel(newerChannel)?.version; const entries = []; - const failedPlugins = pluginInfoEntries - .filter(isNotLoadedDynamicPluginInfo) - .filter((plugin) => plugin.status === 'Failed'); + const failedPlugins = pluginInfoEntries.filter((plugin) => plugin.status === 'failed'); if (!_.isEmpty(updateData)) { entries.push( @@ -245,7 +243,7 @@ export const NotificationDrawer: FC = ({ const { t } = useTranslation(); const clusterID = getClusterID(useClusterVersion()); const showServiceLevelNotification = useShowServiceLevelNotifications(clusterID); - const [pluginInfoEntries] = usePluginInfo(); + const pluginInfoEntries = usePluginInfo(); const dispatch = useDispatch(); const clusterVersion: ClusterVersionKind = useClusterVersion(); const [alerts, , loadError] = useNotificationAlerts(); diff --git a/frontend/public/i18n.js b/frontend/public/i18n.js index 9cece429003..aafa4bac3da 100644 --- a/frontend/public/i18n.js +++ b/frontend/public/i18n.js @@ -6,7 +6,6 @@ import Pseudo from 'i18next-pseudo'; import { transformNamespace } from 'i18next-v4-format-converter'; import { getLastLanguage } from '@console/app/src/components/user-preferences/language/getLastLanguage'; -import { pluginStore } from './plugins'; import { dateTimeFormatter, fromNow } from './components/utils/datetime'; const params = new URLSearchParams(window.location.search); @@ -66,7 +65,6 @@ export const init = () => { 'helm-plugin', 'insights-plugin', 'knative-plugin', - 'lso-plugin', 'metal3-plugin', 'notification-drawer', 'olm', @@ -77,7 +75,7 @@ export const init = () => { 'topology', 'vsphere-plugin', 'webterminal-plugin', - ...pluginStore.getI18nNamespaces(), + ...Array.from(new Set(window.SERVER_FLAGS.i18nNamespaces ?? [])), ], defaultNS: 'public', nsSeparator: '~', diff --git a/frontend/public/plugins.ts b/frontend/public/plugins.ts index bb75020b82a..71a0f43af8e 100644 --- a/frontend/public/plugins.ts +++ b/frontend/public/plugins.ts @@ -17,10 +17,6 @@ const getEnabledDynamicPluginNames = () => { return allPluginNames.filter((pluginName) => !disabledPluginNames.includes(pluginName)); }; -const getI18nNamespaces = () => { - return window.SERVER_FLAGS.i18nNamespaces; -}; - // Console active plugins module has its source generated during webpack build, // so we use dynamic require() instead of the usual static import statement. const activePlugins = @@ -29,9 +25,8 @@ const activePlugins = : []; const dynamicPluginNames = getEnabledDynamicPluginNames(); -const i18nNamespaces = getI18nNamespaces(); -export const pluginStore = new PluginStore(activePlugins, dynamicPluginNames, i18nNamespaces); +export const pluginStore = new PluginStore(activePlugins, dynamicPluginNames); if (process.env.NODE_ENV !== 'production') { // Expose Console plugin store for debugging