Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@
"react-i18next": "^11.12.0",
"react-linkify": "^0.2.2",
"react-modal": "^3.16.3",
"react-redux": "7.2.9",
"react-redux": "8.1.3",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that react-redux is Console provided shared module, using the default config

{ singleton = true, allowFallback = false }

i.e. plugins are built with the assumption that Console provides v7 impl. without plugin provided fallback.

So this is effectively a breaking change in Console provided shared modules.

"react-router": "5.3.x",
"react-router-dom": "5.3.x",
"react-router-dom-v5-compat": "^6.11.2",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useCallback, useMemo } from 'react';
import { ButtonVariant } from '@patternfly/react-core';
import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { useNavigate } from 'react-router-dom-v5-compat';
import { Action, K8sVerb } from '@console/dynamic-plugin-sdk';
import { k8sPatchResource } from '@console/dynamic-plugin-sdk/src/utils/k8s';
Expand All @@ -14,6 +13,7 @@ import {
ClusterRoleBindingKind,
referenceFor,
} from '@console/internal/module/k8s';
import { useConsoleDispatch } from '@console/shared/src/hooks/useConsoleDispatch';
import { useK8sModel } from '@console/shared/src/hooks/useK8sModel';
import { useWarningModal } from '@console/shared/src/hooks/useWarningModal';
import { BindingActionCreator, CommonActionCreator } from './types';
Expand All @@ -37,7 +37,7 @@ export const useBindingActions = (
): Action[] => {
const { t } = useTranslation();
const [model] = useK8sModel(referenceFor(obj));
const dispatch = useDispatch();
const dispatch = useConsoleDispatch();
const startImpersonate = useCallback(
(kind, name) => dispatch(UIActions.startImpersonate(kind, name)),
[dispatch],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom-v5-compat';
import { Action, getImpersonate } from '@console/dynamic-plugin-sdk';
import { useOverlay } from '@console/dynamic-plugin-sdk/src/app/modal-support/useOverlay';
import * as UIActions from '@console/internal/actions/ui';
import { asAccessReview } from '@console/internal/components/utils/rbac';
import { GroupModel } from '@console/internal/models';
import { GroupKind } from '@console/internal/module/k8s';
import { RootState } from '@console/internal/redux';
import { useConsoleDispatch } from '@console/shared/src/hooks/useConsoleDispatch';
import { useConsoleSelector } from '@console/shared/src/hooks/useConsoleSelector';
import AddGroupUsersModal from '../../components/modals/add-group-users-modal';

/**
* Actions specific to Group resources.
*/
export const useGroupActions = (obj: GroupKind): Action[] => {
const { t } = useTranslation();
const dispatch = useDispatch();
const dispatch = useConsoleDispatch();
const navigate = useNavigate();
const launchOverlay = useOverlay();
const impersonate = useSelector((state: RootState) => getImpersonate(state));
const impersonate = useConsoleSelector((state) => getImpersonate(state));

const startImpersonate = useCallback(
(kind: string, name: string) => dispatch(UIActions.startImpersonate(kind, name)),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { useNavigate } from 'react-router-dom-v5-compat';
import { Action } from '@console/dynamic-plugin-sdk/src';
import * as UIActions from '@console/internal/actions/ui';
import { asAccessReview } from '@console/internal/components/utils';
import { UserModel } from '@console/internal/models';
import { referenceFor, UserKind } from '@console/internal/module/k8s';
import { useConsoleDispatch } from '@console/shared/src/hooks/useConsoleDispatch';
import { useK8sModel } from '@console/shared/src/hooks/useK8sModel';
import { useCommonResourceActions } from '../hooks/useCommonResourceActions';

const useImpersonateAction = (resource: UserKind): Action[] => {
const { t } = useTranslation();
const navigate = useNavigate();
const dispatch = useDispatch();
const dispatch = useConsoleDispatch();

const factory = useMemo(
() => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ type FeatureFlagExtensionHookResolverProps = {
setFeatureFlag: SetFeatureFlag;
};

const FeatureFlagExtensionHookResolver: FC<FeatureFlagExtensionHookResolverProps> = ({
export const FeatureFlagExtensionHookResolver: FC<FeatureFlagExtensionHookResolverProps> = ({
handler,
setFeatureFlag,
}) => {
handler(setFeatureFlag);
return null;
};

export default FeatureFlagExtensionHookResolver;
Original file line number Diff line number Diff line change
@@ -1,16 +1,49 @@
import type { FC } from 'react';
import { useCallback, useRef, useEffect } from 'react';
import {
isFeatureFlagHookProvider,
FeatureFlagHookProvider,
useResolvedExtensions,
SetFeatureFlag,
} from '@console/dynamic-plugin-sdk';
import { featureFlagController } from '@console/internal/actions/features';
import FeatureFlagExtensionHookResolver from './FeatureFlagExtensionHookResolver';
import { setFlag } from '@console/internal/actions/flags';
import { useConsoleDispatch } from '@console/shared/src/hooks/useConsoleDispatch';
import { useConsoleSelector } from '@console/shared/src/hooks/useConsoleSelector';
import { FeatureFlagExtensionHookResolver } from './FeatureFlagExtensionHookResolver';

const FeatureFlagExtensionLoader: FC = () => {
const useFeatureFlagController = () => {
const dispatch = useConsoleDispatch();
const flags = useConsoleSelector(({ FLAGS }) => FLAGS);

// Keep a ref to the flags map to avoid time-of-check to time-of-use issues
// if the flags change between render and the callback being invoked
const flagsRef = useRef(flags);

useEffect(() => {
flagsRef.current = flags;
}, [flags]);

return useCallback<SetFeatureFlag>(
(flag, enabled) => {
// Defer dispatch to next event loop tick to avoid "Cannot update a component
// while rendering a different component" error
queueMicrotask(() => {
if (flagsRef.current.get(flag) === enabled) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (flagsRef.current.get(flag) === enabled) {
if (flagsRef.current.get(flag) !== enabled) {
dispatch(setFlag(flag, enabled));
}

return;
}
dispatch(setFlag(flag, enabled));
});
},
[dispatch],
);
};

export const FeatureFlagExtensionLoader: FC = () => {
const [flagProvider, flagProviderResolved] = useResolvedExtensions<FeatureFlagHookProvider>(
isFeatureFlagHookProvider,
);
const featureFlagController = useFeatureFlagController();

if (flagProviderResolved) {
return (
<>
Expand All @@ -32,4 +65,3 @@ const FeatureFlagExtensionLoader: FC = () => {
}
return null;
};
export default FeatureFlagExtensionLoader;
5 changes: 5 additions & 0 deletions frontend/packages/console-dynamic-plugin-sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ This section documents notable changes in Console provided shared modules and ot
- Removed `co-external-link` styling. Use PatternFly Buttons with `variant="link"` instead.
- Removed `co-disabled` styling.

#### Console 4.22.X

- Upgraded from `react-redux` v7 to v8. Plugins must use `react-redux` v8 to be compatible
with Console.

### PatternFly 5+ dynamic modules

Newer versions of `@openshift-console/dynamic-plugin-sdk-webpack` package include support for automatic
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Map as ImmutableMap } from 'immutable';
import type { AnyAction } from 'redux';
import type { ThunkDispatch } from 'redux-thunk';
import type { UserKind } from '@console/internal/module/k8s/types';
import { UserInfo } from '../extensions/console-types';

Expand Down Expand Up @@ -27,3 +29,5 @@ export type SDKStoreState = {
sdkCore: CoreState;
k8s: K8sState;
};

export type SDKDispatch = ThunkDispatch<SDKStoreState, undefined, AnyAction>;
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useMemo, useEffect } from 'react';
import { Map as ImmutableMap } from 'immutable';
import { useSelector, useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import * as k8sActions from '../../../app/k8s/actions/k8s';
import { getReduxIdPayload } from '../../../app/k8s/reducers/k8sSelector';
import { SDKStoreState } from '../../../app/redux-types';
import type { SDKDispatch, SDKStoreState } from '../../../app/redux-types';
import { UseK8sWatchResource } from '../../../extensions/console-types';
import { getIDAndDispatch, getReduxData, NoModelError } from './k8s-watcher';
import { useDeepCompareMemoize } from './useDeepCompareMemoize';
Expand Down Expand Up @@ -33,7 +33,7 @@ export const useK8sWatchResource: UseK8sWatchResource = (initResource) => {

const reduxID = useMemo(() => getIDAndDispatch(resource, k8sModel), [k8sModel, resource]);

const dispatch = useDispatch();
const dispatch = useDispatch<SDKDispatch>();

useEffect(() => {
if (reduxID) {
Expand All @@ -46,9 +46,9 @@ export const useK8sWatchResource: UseK8sWatchResource = (initResource) => {
};
}, [dispatch, reduxID]);

const resourceK8s = useSelector<SDKStoreState, ImmutableMap<string, any>>((state) =>
const resourceK8s = useSelector<SDKStoreState>((state) =>
reduxID ? getReduxIdPayload(state, reduxID.id) : null,
);
) as ImmutableMap<string, any>;

return useMemo(() => {
if (!resource) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { useRef, useMemo, useEffect } from 'react';
import { Map as ImmutableMap, Iterable as ImmutableIterable } from 'immutable';
import { useSelector, useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { createSelectorCreator, defaultMemoize } from 'reselect';
import { K8sModel } from '../../../api/common-types';
import * as k8sActions from '../../../app/k8s/actions/k8s';
import type { SDKDispatch, SDKStoreState } from '../../../app/redux-types';
import { UseK8sWatchResources } from '../../../extensions/console-types';
import {
transformGroupVersionKindToReference,
Expand Down Expand Up @@ -38,9 +39,9 @@ export const useK8sWatchResources: UseK8sWatchResources = (initResources) => {
const resources = useDeepCompareMemoize(initResources, true);
const modelsLoaded = useModelsLoaded();

const allK8sModels = useSelector<OpenShiftReduxRootState, ImmutableMap<string, K8sModel>>(
(state: OpenShiftReduxRootState) => state.k8s.getIn(['RESOURCES', 'models']),
);
const allK8sModels = useSelector<SDKStoreState>((state) =>
state.k8s.getIn(['RESOURCES', 'models']),
) as ImmutableMap<string, K8sModel>;

const prevK8sModels = usePrevious(allK8sModels);
const prevResources = usePrevious(resources);
Expand Down Expand Up @@ -98,7 +99,7 @@ export const useK8sWatchResources: UseK8sWatchResources = (initResources) => {
[k8sModels, modelsLoaded, resources],
);

const dispatch = useDispatch();
const dispatch = useDispatch<SDKDispatch>();
useEffect(() => {
const reduxIDKeys = Object.keys(reduxIDs || {});
reduxIDKeys.forEach((k) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import { useEffect, useMemo } from 'react';
import { Map as ImmutableMap } from 'immutable';
import { useSelector, useDispatch } from 'react-redux';
import {
watchPrometheusQuery,
stopWatchPrometheusQuery,
} from '@console/internal/actions/dashboards';
import { getInstantVectorStats } from '@console/internal/components/graphs/utils';
import { Humanize, HumanizeResult } from '@console/internal/components/utils/types';
import { RESULTS_TYPE } from '@console/internal/reducers/dashboard-results';
import { RootState } from '@console/internal/redux';
import { useConsoleDispatch } from '@console/shared/src/hooks/useConsoleDispatch';
import { useConsoleSelector } from '@console/shared/src/hooks/useConsoleSelector';

/** @deprecated use usePrometheusPoll() instead */
export const usePrometheusQuery: UsePrometheusQuery = (query, humanize) => {
const dispatch = useDispatch();
const dispatch = useConsoleDispatch();
useEffect(() => {
dispatch(watchPrometheusQuery(query));
return () => {
dispatch(stopWatchPrometheusQuery(query));
};
}, [dispatch, query]);

const queryResult = useSelector<RootState, ImmutableMap<string, any>>(({ dashboards }) =>
const queryResult = useConsoleSelector(({ dashboards }) =>
dashboards.getIn([RESULTS_TYPE.PROMETHEUS, query]),
);
) as ImmutableMap<string, any>;
const results = useMemo<[HumanizeResult, any, number]>(() => {
if (!queryResult || !queryResult.get('data')) {
return [{}, null, null] as [HumanizeResult, any, number];
Expand Down
14 changes: 14 additions & 0 deletions frontend/packages/console-shared/src/hooks/useConsoleDispatch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useDispatch } from 'react-redux';
import type { AnyAction } from 'redux';
import type { ThunkDispatch } from 'redux-thunk';
import type { RootState } from '@console/internal/redux';

// TODO: When upgrading to react-redux v9, use the built-in `withTypes` method.
// See: https://github.com/reduxjs/react-redux/releases/tag/v9.1.0

/**
* A hook to access the console redux `dispatch` function.
*
* See {@link useDispatch} for more details.
*/
export const useConsoleDispatch: () => ThunkDispatch<RootState, undefined, AnyAction> = useDispatch;
12 changes: 12 additions & 0 deletions frontend/packages/console-shared/src/hooks/useConsoleSelector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { TypedUseSelectorHook, useSelector } from 'react-redux';
import type { RootState } from '@console/internal/redux';

// TODO: When upgrading to react-redux v9, use the built-in `withTypes` method.
// See: https://github.com/reduxjs/react-redux/releases/tag/v9.1.0

/**
* A hook to access the console redux state.
*
* See {@link useSelector} for more details.
*/
export const useConsoleSelector: TypedUseSelectorHook<RootState> = useSelector;
12 changes: 12 additions & 0 deletions frontend/packages/console-shared/src/hooks/useConsoleStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { useStore } from 'react-redux';
import type store from '@console/internal/redux';

// TODO: When upgrading to react-redux v9, use the built-in `withTypes` method.
// See: https://github.com/reduxjs/react-redux/releases/tag/v9.1.0

/**
* A hook to access the console redux store.
*
* See {@link useStore} for more details.
*/
export const useConsoleStore = useStore as () => typeof store;
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import {
RequestMap,
UseDashboardResources,
} from '@console/dynamic-plugin-sdk/src/api/internal-types';
import { UseDashboardResources } from '@console/dynamic-plugin-sdk/src/api/internal-types';
import {
stopWatchPrometheusQuery,
stopWatchURL,
watchPrometheusQuery,
watchURL,
} from '@console/internal/actions/dashboards';
import { PrometheusResponse } from '@console/internal/components/graphs';
import { RESULTS_TYPE } from '@console/internal/reducers/dashboard-results';
import { RootState } from 'public/redux';
import { useConsoleDispatch } from '@console/shared/src/hooks/useConsoleDispatch';
import { useConsoleSelector } from '@console/shared/src/hooks/useConsoleSelector';
import { useNotificationAlerts } from './useNotificationAlerts';

export const useDashboardResources: UseDashboardResources = ({
Expand All @@ -24,7 +20,7 @@ export const useDashboardResources: UseDashboardResources = ({
notificationAlertLabelSelectors,
);

const dispatch = useDispatch();
const dispatch = useConsoleDispatch();
useEffect(() => {
prometheusQueries?.forEach((query) =>
dispatch(watchPrometheusQuery(query.query, null, query.timespan)),
Expand All @@ -39,10 +35,8 @@ export const useDashboardResources: UseDashboardResources = ({
};
}, [dispatch, prometheusQueries, urls]);

const urlResults = useSelector<RootState, RequestMap<any>>((state) =>
state.dashboards.get(RESULTS_TYPE.URL),
);
const prometheusResults = useSelector<RootState, RequestMap<PrometheusResponse>>((state) =>
const urlResults = useConsoleSelector((state) => state.dashboards.get(RESULTS_TYPE.URL));
const prometheusResults = useConsoleSelector((state) =>
state.dashboards.get(RESULTS_TYPE.PROMETHEUS),
);

Expand Down
Loading