= (prop
{props.pod.spec.containers.find((c) => c.name === status.name).image}
|
- {props.loaded ? (
+ {props.imageManifestVuln.loaded ? (
withVuln(
vulnFor(status),
(vuln) => (
@@ -400,30 +399,30 @@ export const ContainerVulnerabilities: FC = (prop
export const ImageManifestVulnPodTab: FC = (props) => {
const params = useParams();
+ const [imageManifestVuln, loaded, loadError] = useK8sWatchResource({
+ isList: true,
+ kind: referenceForModel(ImageManifestVulnModel),
+ namespace: params.ns,
+ selector: {
+ matchLabels: { [podKey(props.obj)]: 'true' },
+ },
+ });
+
return (
-
- {/* FIXME(alecmerdler): Hack because `Firehose` injects props without TypeScript knowing about it */}
-
-
+
);
};
export type ContainerVulnerabilitiesProps = {
- loaded: boolean;
pod: PodKind;
- imageManifestVuln: FirehoseResult;
+ imageManifestVuln: {
+ data: ImageManifestVuln[];
+ loaded: boolean;
+ loadError?: unknown;
+ };
};
export type ImageManifestVulnPageProps = {
diff --git a/frontend/packages/operator-lifecycle-manager/src/components/__tests__/catalog-source.spec.tsx b/frontend/packages/operator-lifecycle-manager/src/components/__tests__/catalog-source.spec.tsx
index d3886e9a18..483b54cbe6 100644
--- a/frontend/packages/operator-lifecycle-manager/src/components/__tests__/catalog-source.spec.tsx
+++ b/frontend/packages/operator-lifecycle-manager/src/components/__tests__/catalog-source.spec.tsx
@@ -1,10 +1,11 @@
-import { cloneElement } from 'react';
import { screen } from '@testing-library/react';
import * as _ from 'lodash';
import * as Router from 'react-router-dom-v5-compat';
import { DetailsPage } from '@console/internal/components/factory';
-import { Firehose } from '@console/internal/components/utils';
-import { useK8sWatchResource } from '@console/internal/components/utils/k8s-watch-hook';
+import {
+ useK8sWatchResource,
+ useK8sWatchResources,
+} from '@console/internal/components/utils/k8s-watch-hook';
import { referenceForModel } from '@console/internal/module/k8s';
import { renderWithProviders } from '@console/shared/src/test-utils/unit-test-utils';
import { testCatalogSource, testPackageManifest, dummyPackageManifest } from '../../../mocks';
@@ -18,6 +19,7 @@ import {
jest.mock('@console/internal/components/utils/k8s-watch-hook', () => ({
useK8sWatchResource: jest.fn(),
+ useK8sWatchResources: jest.fn(),
}));
jest.mock('react-router-dom-v5-compat', () => ({
@@ -35,10 +37,6 @@ jest.mock('@console/internal/components/factory', () => ({
jest.mock('@console/internal/components/utils', () => ({
...jest.requireActual('@console/internal/components/utils'),
- Firehose: jest.fn(({ children }) => {
- const props = { packageManifest: { loaded: false } };
- return typeof children === 'function' ? children(props) : children;
- }),
LoadingBox: jest.fn(() => 'Loading...'),
ResourceSummary: jest.fn(() => null),
SectionHeading: jest.fn(() => null),
@@ -86,8 +84,8 @@ jest.mock('@patternfly/react-core', () => ({
}));
const mockDetailsPage = (DetailsPage as unknown) as jest.Mock;
-const mockFirehose = (Firehose as unknown) as jest.Mock;
const mockUseK8sWatchResource = useK8sWatchResource as jest.Mock;
+const mockUseK8sWatchResources = useK8sWatchResources as jest.Mock;
describe('CatalogSourceDetails', () => {
let obj;
@@ -169,7 +167,7 @@ describe('CreateSubscriptionYAML', () => {
hash: '',
key: 'default',
});
- mockFirehose.mockClear();
+ mockUseK8sWatchResources.mockClear();
});
afterEach(() => {
@@ -177,12 +175,9 @@ describe('CreateSubscriptionYAML', () => {
});
it('displays package name in the subscription YAML when loaded', () => {
- mockFirehose.mockImplementationOnce((firehoseProps) => {
- const childElement = firehoseProps.children;
- return cloneElement(childElement, {
- packageManifest: { loaded: true, data: testPackageManifest },
- operatorGroup: { loaded: true, data: [] },
- });
+ mockUseK8sWatchResources.mockReturnValue({
+ packageManifest: { loaded: true, data: testPackageManifest, loadError: null },
+ operatorGroup: { loaded: true, data: [], loadError: null },
});
renderWithProviders();
@@ -191,12 +186,9 @@ describe('CreateSubscriptionYAML', () => {
});
it('displays loading indicator when package manifest is not yet loaded', () => {
- mockFirehose.mockImplementationOnce((firehoseProps) => {
- const childElement = firehoseProps.children;
- return cloneElement(childElement, {
- packageManifest: { loaded: false },
- operatorGroup: { loaded: false },
- });
+ mockUseK8sWatchResources.mockReturnValue({
+ packageManifest: { loaded: false, data: undefined, loadError: null },
+ operatorGroup: { loaded: false, data: undefined, loadError: null },
});
renderWithProviders();
@@ -205,12 +197,9 @@ describe('CreateSubscriptionYAML', () => {
});
it('displays subscription YAML with default channel information', () => {
- mockFirehose.mockImplementationOnce((firehoseProps) => {
- const childElement = firehoseProps.children;
- return cloneElement(childElement, {
- packageManifest: { loaded: true, data: testPackageManifest },
- operatorGroup: { loaded: true, data: [] },
- });
+ mockUseK8sWatchResources.mockReturnValue({
+ packageManifest: { loaded: true, data: testPackageManifest, loadError: null },
+ operatorGroup: { loaded: true, data: [], loadError: null },
});
renderWithProviders();
diff --git a/frontend/packages/operator-lifecycle-manager/src/components/catalog-source.tsx b/frontend/packages/operator-lifecycle-manager/src/components/catalog-source.tsx
index 959d28f20d..44db6831e0 100644
--- a/frontend/packages/operator-lifecycle-manager/src/components/catalog-source.tsx
+++ b/frontend/packages/operator-lifecycle-manager/src/components/catalog-source.tsx
@@ -15,9 +15,7 @@ import type {
RowFunctionArgs,
} from '@console/internal/components/factory';
import { DetailsPage, Table, TableData, MultiListPage } from '@console/internal/components/factory';
-import type { FirehoseResult } from '@console/internal/components/utils';
import {
- Firehose,
LoadingBox,
ConsoleEmptyState,
navFactory,
@@ -27,6 +25,7 @@ import {
ResourceSummary,
DetailsItem,
} from '@console/internal/components/utils';
+import { useK8sWatchResources } from '@console/internal/components/utils/k8s-watch-hook';
import i18n from '@console/internal/i18n';
import { ConfigMapModel } from '@console/internal/models';
import type { K8sKind, K8sModel } from '@console/internal/module/k8s';
@@ -213,12 +212,30 @@ export const CatalogSourceDetailsPage: FC = (props) => {
export const CreateSubscriptionYAML: FC = (props) => {
type CreateProps = {
- packageManifest: { loaded: boolean; data?: PackageManifestKind };
- operatorGroup: { loaded: boolean; data?: OperatorGroupKind[] };
+ packageManifest: { loaded: boolean; data?: PackageManifestKind; loadError?: unknown };
+ operatorGroup: { loaded: boolean; data?: OperatorGroupKind[]; loadError?: unknown };
};
const { t } = useTranslation();
const params = useParams();
const location = useLocation();
+
+ const resources = useK8sWatchResources<{
+ packageManifest: PackageManifestKind;
+ operatorGroup: OperatorGroupKind[];
+ }>({
+ packageManifest: {
+ kind: referenceForModel(PackageManifestModel),
+ isList: false,
+ name: new URLSearchParams(location.search).get('pkg'),
+ namespace: new URLSearchParams(location.search).get('catalogNamespace'),
+ },
+ operatorGroup: {
+ kind: referenceForModel(OperatorGroupModel),
+ isList: true,
+ namespace: params.ns,
+ },
+ });
+
const Create = requireOperatorGroup(
withFallback(
(createProps) => {
@@ -256,26 +273,11 @@ export const CreateSubscriptionYAML: FC = (props) => {
);
return (
-
- {/* FIXME(alecmerdler): Hack because `Firehose` injects props without TypeScript knowing about it */}
-
-
+
);
};
@@ -546,8 +548,8 @@ type DisabledPopoverProps = {
};
type FlattenArgType = {
- catalogSources?: FirehoseResult;
- packageManifests?: FirehoseResult;
+ catalogSources?: { data?: CatalogSourceKind[]; loaded?: boolean; loadError?: unknown };
+ packageManifests?: { data?: PackageManifestKind[]; loaded?: boolean; loadError?: unknown };
operatorHub: OperatorHubKind;
};
diff --git a/frontend/packages/operator-lifecycle-manager/src/components/operator-hub/operator-hub-page.tsx b/frontend/packages/operator-lifecycle-manager/src/components/operator-hub/operator-hub-page.tsx
index 9e93b08d51..4fb03b0236 100644
--- a/frontend/packages/operator-lifecycle-manager/src/components/operator-hub/operator-hub-page.tsx
+++ b/frontend/packages/operator-lifecycle-manager/src/components/operator-hub/operator-hub-page.tsx
@@ -4,7 +4,8 @@ import * as _ from 'lodash';
import { Trans, useTranslation } from 'react-i18next';
import { useParams, Link } from 'react-router-dom-v5-compat';
import { OPERATOR_BACKED_SERVICE_CATALOG_TYPE_ID } from '@console/dev-console/src/const';
-import { Firehose, skeletonCatalog, StatusBox } from '@console/internal/components/utils';
+import { skeletonCatalog, StatusBox } from '@console/internal/components/utils';
+import { useK8sWatchResources } from '@console/internal/components/utils/k8s-watch-hook';
import type {
CloudCredentialKind,
InfrastructureKind,
@@ -247,12 +248,69 @@ export const OperatorHubList: FC = ({
);
};
-export const OperatorHubPage = withFallback((props) => {
+export const OperatorHubPage = withFallback(() => {
const params = useParams();
const isSoftwareCatalogEnabled = useIsSoftwareCatalogEnabled();
const isOperatorBackedServiceEnabled = isCatalogTypeEnabled(
OPERATOR_BACKED_SERVICE_CATALOG_TYPE_ID,
);
+
+ const resources = useK8sWatchResources<{
+ operatorGroups: OperatorGroupKind[];
+ marketplacePackageManifests: PackageManifestKind[];
+ packageManifests: PackageManifestKind[];
+ subscriptions: SubscriptionKind[];
+ clusterServiceVersions: ClusterServiceVersionKind[];
+ cloudCredentials: CloudCredentialKind;
+ infrastructure: InfrastructureKind;
+ authentication: AuthenticationKind;
+ }>({
+ operatorGroups: {
+ isList: true,
+ kind: referenceForModel(OperatorGroupModel),
+ },
+ marketplacePackageManifests: {
+ isList: true,
+ kind: referenceForModel(PackageManifestModel),
+ namespace: params.ns,
+ selector: { matchLabels: { 'openshift-marketplace': 'true' } },
+ },
+ packageManifests: {
+ isList: true,
+ kind: referenceForModel(PackageManifestModel),
+ namespace: params.ns,
+ selector: fromRequirements([
+ { key: 'opsrc-owner-name', operator: 'DoesNotExist' },
+ { key: 'csc-owner-name', operator: 'DoesNotExist' },
+ ]),
+ },
+ subscriptions: {
+ isList: true,
+ kind: referenceForModel(SubscriptionModel),
+ },
+ clusterServiceVersions: {
+ kind: referenceForModel(ClusterServiceVersionModel),
+ namespaced: true,
+ isList: true,
+ namespace: params.ns,
+ },
+ cloudCredentials: {
+ kind: referenceForModel(CloudCredentialModel),
+ name: 'cluster',
+ },
+ infrastructure: {
+ kind: referenceForModel(InfrastructureModel),
+ name: 'cluster',
+ },
+ authentication: {
+ kind: referenceForModel(AuthenticationModel),
+ name: 'cluster',
+ },
+ });
+
+ const loaded = Object.values(resources).every((r) => r.loaded);
+ const loadError = Object.values(resources).find((r) => r.loadError)?.loadError;
+
return (
<>
OperatorHub
@@ -278,62 +336,12 @@ export const OperatorHubPage = withFallback((props) => {
)
}
/>
-
- {/* FIXME(alecmerdler): Hack because `Firehose` injects props without TypeScript knowing about it */}
-
-
+
>
);
diff --git a/frontend/packages/operator-lifecycle-manager/src/components/operator-hub/operator-hub-subscribe.tsx b/frontend/packages/operator-lifecycle-manager/src/components/operator-hub/operator-hub-subscribe.tsx
index 31584038fd..94ea45b97c 100644
--- a/frontend/packages/operator-lifecycle-manager/src/components/operator-hub/operator-hub-subscribe.tsx
+++ b/frontend/packages/operator-lifecycle-manager/src/components/operator-hub/operator-hub-subscribe.tsx
@@ -22,7 +22,6 @@ import { RadioGroup } from '@console/internal/components/radio';
import {
documentationURLs,
FieldLevelHelp,
- Firehose,
getDocumentationURL,
getURLSearchParams,
history,
@@ -33,7 +32,10 @@ import {
resourcePathFromModel,
StatusBox,
} from '@console/internal/components/utils';
-import { useK8sWatchResource } from '@console/internal/components/utils/k8s-watch-hook';
+import {
+ useK8sWatchResource,
+ useK8sWatchResources,
+} from '@console/internal/components/utils/k8s-watch-hook';
import { useAccessReview } from '@console/internal/components/utils/rbac';
import {
ConsoleOperatorConfigModel,
@@ -1220,40 +1222,45 @@ const OperatorHubSubscribe: FC = (props) => (
);
-export const OperatorHubSubscribePage: FC = (props) => {
- return (
- {
+ const [activeNamespace] = useActiveNamespace();
+ const resources = useK8sWatchResources<{
+ operatorGroup: OperatorGroupKind[];
+ packageManifest: PackageManifestKind[];
+ subscription: SubscriptionKind[];
+ }>({
+ operatorGroup: {
+ isList: true,
+ kind: referenceForModel(OperatorGroupModel),
+ },
+ packageManifest: {
+ isList: true,
+ kind: referenceForModel(PackageManifestModel),
+ namespace: new URLSearchParams(window.location.search).get('catalogNamespace'),
+ fieldSelector: `metadata.name=${new URLSearchParams(window.location.search).get('pkg')}`,
+ selector: {
+ matchLabels: {
+ catalog: new URLSearchParams(window.location.search).get('catalog'),
},
- ]}
- >
- {/* FIXME(alecmerdler): Hack because `Firehose` injects props without TypeScript knowing about it */}
-
-
+ },
+ },
+ subscription: {
+ isList: true,
+ kind: referenceForModel(SubscriptionModel),
+ },
+ });
+
+ const loaded = Object.values(resources).every((r) => r.loaded);
+ const loadError = Object.values(resources).find((r) => r.loadError)?.loadError;
+
+ return (
+
);
};
diff --git a/frontend/packages/operator-lifecycle-manager/src/components/operator-install-page.tsx b/frontend/packages/operator-lifecycle-manager/src/components/operator-install-page.tsx
index 15dfb7ade1..f90b6af861 100644
--- a/frontend/packages/operator-lifecycle-manager/src/components/operator-install-page.tsx
+++ b/frontend/packages/operator-lifecycle-manager/src/components/operator-install-page.tsx
@@ -13,19 +13,19 @@ import {
import { useTranslation } from 'react-i18next';
import type { LinkProps } from 'react-router-dom-v5-compat';
import { useParams, Link } from 'react-router-dom-v5-compat';
+import type { WatchK8sResultsObject } from '@console/dynamic-plugin-sdk';
import { ResourceStatus, StatusIconAndText } from '@console/dynamic-plugin-sdk';
import { useK8sWatchResource } from '@console/dynamic-plugin-sdk/src/api/core-api';
import { useOverlay } from '@console/dynamic-plugin-sdk/src/app/modal-support/useOverlay';
import { SyncMarkdownView } from '@console/internal/components/markdown-view';
import { ErrorModal } from '@console/internal/components/modals/error-modal';
-import type { FirehoseResult } from '@console/internal/components/utils';
import {
- Firehose,
LoadingInline,
ResourceLink,
resourcePathFromModel,
useAccessReview,
} from '@console/internal/components/utils';
+import { useK8sWatchResources } from '@console/internal/components/utils/k8s-watch-hook';
import type { K8sResourceKind } from '@console/internal/module/k8s';
import { k8sPatch, referenceForModel, referenceFor } from '@console/internal/module/k8s';
import { DocumentTitle } from '@console/shared/src/components/document-title/DocumentTitle';
@@ -512,46 +512,43 @@ const OperatorInstallStatus: FC = ({ resources }) => {
export const OperatorInstallStatusPage: FC = () => {
const { pkg, currentCSV, targetNamespace } = useParams();
- const installPageResources = [
- {
+ const resources = useK8sWatchResources<{
+ clusterServiceVersion: ClusterServiceVersionKind;
+ subscription: SubscriptionKind;
+ installPlans: InstallPlanKind[];
+ }>({
+ clusterServiceVersion: {
kind: referenceForModel(ClusterServiceVersionModel),
namespaced: true,
isList: false,
name: currentCSV,
namespace: targetNamespace,
- prop: 'clusterServiceVersion',
},
- {
+ subscription: {
kind: referenceForModel(SubscriptionModel),
namespaced: true,
isList: false,
name: pkg,
namespace: targetNamespace,
optional: true,
- prop: 'subscription',
},
- {
+ installPlans: {
kind: referenceForModel(InstallPlanModel),
- prop: 'installPlans',
namespaced: true,
namespace: targetNamespace,
isList: true,
optional: true,
},
- ];
+ });
- return (
-
-
-
- );
+ return ;
};
export type OperatorInstallPageProps = {
resources?: {
- clusterServiceVersion: FirehoseResult;
- subscription: FirehoseResult;
- installPlans: FirehoseResult;
+ clusterServiceVersion: WatchK8sResultsObject;
+ subscription: WatchK8sResultsObject;
+ installPlans: WatchK8sResultsObject;
};
};
type InstallSuccededMessageProps = {
diff --git a/frontend/packages/operator-lifecycle-manager/src/components/topology/sidebar/TopologyOperatorBackedResources.tsx b/frontend/packages/operator-lifecycle-manager/src/components/topology/sidebar/TopologyOperatorBackedResources.tsx
index 2ab169267d..3219e0cd0d 100644
--- a/frontend/packages/operator-lifecycle-manager/src/components/topology/sidebar/TopologyOperatorBackedResources.tsx
+++ b/frontend/packages/operator-lifecycle-manager/src/components/topology/sidebar/TopologyOperatorBackedResources.tsx
@@ -1,8 +1,10 @@
import type { ReactElement, FC } from 'react';
+import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom-v5-compat';
import type { TopologyDataObject } from '@console/dynamic-plugin-sdk/src/extensions/topology-types';
-import { Firehose, ResourceIcon, StatusBox } from '@console/internal/components/utils';
+import { ResourceIcon, StatusBox } from '@console/internal/components/utils';
+import { useK8sWatchResources } from '@console/internal/components/utils/k8s-watch-hook';
import type { GroupVersionKind, K8sResourceKind } from '@console/internal/module/k8s';
import {
modelFor,
@@ -27,11 +29,9 @@ import type { OperatorGroupData } from './types';
type OperatorResourcesProps = {
namespace: string;
- resources?: {
- [kind: string]: { data: K8sResourceKind[] };
+ resources: {
+ [kind: string]: { data: K8sResourceKind[]; loaded: boolean; loadError?: unknown };
};
- loaded?: boolean;
- loadError?: string;
flatten: (resources: { [kind: string]: { data: K8sResourceKind[] } }) => K8sResourceKind[];
linkForResource?: (obj: K8sResourceKind) => ReactElement;
};
@@ -39,12 +39,12 @@ type OperatorResourcesProps = {
const OperatorResources: FC = ({
namespace,
resources,
- loaded,
- loadError,
flatten,
linkForResource,
}) => {
const { t } = useTranslation();
+ const loaded = Object.values(resources).every((r) => r.loaded);
+ const loadError = Object.values(resources).find((r) => r.loadError)?.loadError;
const manifestResources = flatten(resources);
return (
= ({
kind,
})) as CRDDescription['resources']);
- const firehoseResources = resourcesToGet.reduce((acc, descriptor) => {
- const { name, kind, version } = descriptor;
- const group = name ? name.substring(name.indexOf('.') + 1) : '';
- const reference = group ? referenceForGroupVersionKind(group)(version)(kind) : kind;
- const model = modelFor(reference);
- acc.push({
- prop: kind,
- kind: model && !model.crd ? kind : reference,
- namespaced: model ? model.namespaced : true,
- namespace,
- isList: true,
- optional: true,
- });
- return acc;
- }, []);
+ const watchedResources = useMemo(() => {
+ return resourcesToGet.reduce((acc, descriptor) => {
+ const { name, kind, version } = descriptor;
+ const group = name ? name.substring(name.indexOf('.') + 1) : '';
+ const reference = group ? referenceForGroupVersionKind(group)(version)(kind) : kind;
+ const model = modelFor(reference);
+ acc[kind] = {
+ kind: model && !model.crd ? kind : reference,
+ namespaced: model ? model.namespaced : true,
+ namespace,
+ isList: true,
+ optional: true,
+ };
+ return acc;
+ }, {});
+ }, [namespace, resourcesToGet]);
+
+ const resources = useK8sWatchResources<{ [key: string]: K8sResourceKind[] }>(watchedResources);
return (
-
-
-
+
);
};
diff --git a/frontend/packages/shipwright-plugin/src/components/build-form/PushSecretDropdown.tsx b/frontend/packages/shipwright-plugin/src/components/build-form/PushSecretDropdown.tsx
index ea579a3c7c..369485665d 100644
--- a/frontend/packages/shipwright-plugin/src/components/build-form/PushSecretDropdown.tsx
+++ b/frontend/packages/shipwright-plugin/src/components/build-form/PushSecretDropdown.tsx
@@ -1,8 +1,9 @@
import type { ReactNode, FC } from 'react';
import * as fuzzy from 'fuzzysearch';
import { useTranslation } from 'react-i18next';
-import { Firehose } from '@console/internal/components/utils';
+import { useK8sWatchResource } from '@console/internal/components/utils/k8s-watch-hook';
import { SecretModel } from '@console/internal/models';
+import type { SecretKind } from '@console/internal/module/k8s';
import type { ResourceDropdownProps } from '@console/shared/src/components/dropdown/ResourceDropdown';
import { ResourceDropdown } from '@console/shared/src/components/dropdown/ResourceDropdown';
@@ -25,26 +26,32 @@ const PushSecretDropdown: FC = (props) => {
item.type === 'kubernetes.io/dockercfg' || item.type === 'kubernetes.io/dockerconfigjson'
);
};
+ const [secrets, loaded, loadError] = useK8sWatchResource({
+ isList: true,
+ kind: SecretModel.kind,
+ namespace: props.namespace,
+ optional: true,
+ });
+
const resources = [
{
- isList: true,
+ data: secrets,
+ loaded,
+ loadError,
kind: SecretModel.kind,
- namespace: props.namespace,
- prop: SecretModel.id,
- optional: true,
},
];
+
return (
-
-
-
+
);
};
diff --git a/frontend/packages/topology/src/components/dropdowns/ApplicationDropdown.tsx b/frontend/packages/topology/src/components/dropdowns/ApplicationDropdown.tsx
index 338e34c1cf..7da36fd71e 100644
--- a/frontend/packages/topology/src/components/dropdowns/ApplicationDropdown.tsx
+++ b/frontend/packages/topology/src/components/dropdowns/ApplicationDropdown.tsx
@@ -1,7 +1,7 @@
import type { FC } from 'react';
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
-import { Firehose } from '@console/internal/components/utils';
+import { useK8sWatchResources } from '@console/internal/components/utils/k8s-watch-hook';
import { ResourceDropdown } from '@console/shared';
import type { ResourceDropdownProps } from '../../../../console-shared/src/components/dropdown/ResourceDropdown';
import { getBaseWatchedResources } from '../../data-transforms/transform-utils';
@@ -13,24 +13,17 @@ type ApplicationDropdownProps = Omit = ({ namespace, ...props }) => {
const { t } = useTranslation();
- const resources = useMemo(() => {
- // Use only base watched resources since dynamic factories are handled separately
- // and ApplicationDropdown primarily needs the base resources for application labels
- const watchedBaseResources = getBaseWatchedResources(namespace);
- return Object.keys(watchedBaseResources).map((key) => ({
- ...watchedBaseResources[key],
- prop: key,
- }));
- }, [namespace]);
+ const watchedBaseResources = useMemo(() => getBaseWatchedResources(namespace), [namespace]);
+
+ const resources = useK8sWatchResources(watchedBaseResources);
return (
-
-
-
+
);
};
|