diff --git a/packages/manager/CHANGELOG.md b/packages/manager/CHANGELOG.md
index 28a1647bd1b..ae479346b6f 100644
--- a/packages/manager/CHANGELOG.md
+++ b/packages/manager/CHANGELOG.md
@@ -4,8 +4,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).
-## [2023-06-27] - v1.96.1
+## [2023-06-29] - v1.96.2
+
+### Fixed:
+- Issue where Cloud Manager was not displaying all linodes capable of being "cloned" ([#9294](https://github.com/linode/manager/pull/9294))
+- Firewall custom ports validation w/ unit tests ([#9336](https://github.com/linode/manager/pull/9336))
+### Tech Stories:
+
+- React Query - Linodes - General Refactors ([#9294](https://github.com/linode/manager/pull/9294))
+
+## [2023-06-27] - v1.96.1
### Fixed:
diff --git a/packages/manager/package.json b/packages/manager/package.json
index 81fd42b037a..ffe433c5228 100644
--- a/packages/manager/package.json
+++ b/packages/manager/package.json
@@ -2,7 +2,7 @@
"name": "linode-manager",
"author": "Linode",
"description": "The Linode Manager website",
- "version": "1.96.1",
+ "version": "1.96.2",
"private": true,
"bugs": {
"url": "https://github.com/Linode/manager/issues"
diff --git a/packages/manager/src/App.tsx b/packages/manager/src/App.tsx
index 61ce13db465..aeee3c078f4 100644
--- a/packages/manager/src/App.tsx
+++ b/packages/manager/src/App.tsx
@@ -20,7 +20,6 @@ import { ADOBE_ANALYTICS_URL, NUM_ADOBE_SCRIPTS } from './constants';
import { reportException } from './exceptionReporting';
import { useAuthentication } from './hooks/useAuthentication';
import useFeatureFlagsLoad from './hooks/useFeatureFlagLoad';
-import useLinodes from './hooks/useLinodes';
import { loadScript } from './hooks/useScript';
import { oauthClientsEventHandler } from './queries/accountOAuth';
import { databaseEventsHandler } from './queries/databases';
@@ -59,12 +58,6 @@ const BaseApp = withFeatureFlagProvider(
const { enqueueSnackbar } = useSnackbar();
- const {
- linodes: {
- error: { read: linodesError },
- },
- } = useLinodes();
-
const [goToOpen, setGoToOpen] = React.useState(false);
const theme = preferences?.theme;
@@ -263,15 +256,6 @@ const BaseApp = withFeatureFlagProvider(
};
}, [handleMigrationEvent]);
- /**
- * in the event that we encounter an "invalid OAuth token" error from the API,
- * we can simply refrain from rendering any content since the user will
- * imminently be redirected to the login page.
- */
- if (hasOauthError(linodesError)) {
- return null;
- }
-
return (
}>
{/** Accessibility helper */}
diff --git a/packages/manager/src/containers/withLinodes.container.ts b/packages/manager/src/containers/withLinodes.container.ts
index 7655fc204b8..cf3fc95186d 100644
--- a/packages/manager/src/containers/withLinodes.container.ts
+++ b/packages/manager/src/containers/withLinodes.container.ts
@@ -1,91 +1,40 @@
-import { Linode } from '@linode/api-v4/lib/linodes';
-import { APIError, Filter, Params } from '@linode/api-v4/lib/types';
-import { path } from 'ramda';
-import { connect, InferableComponentEnhancerWithProps } from 'react-redux';
-import { ApplicationState } from 'src/store';
-import { requestLinodes } from 'src/store/linodes/linode.requests';
-import { State } from 'src/store/linodes/linodes.reducer';
-import { LinodeWithMaintenanceAndDisplayStatus } from 'src/store/linodes/types';
-import { ThunkDispatch } from 'src/store/types';
-import { GetAllData } from 'src/utilities/getAll';
-
-export interface DispatchProps {
- getLinodes: (
- params?: Params,
- filters?: Filter
- ) => Promise>;
+import React from 'react';
+import { CreateLinodeRequest, Linode } from '@linode/api-v4/lib/linodes';
+import { APIError } from '@linode/api-v4/lib/types';
+import {
+ useAllLinodesQuery,
+ useCreateLinodeMutation,
+} from 'src/queries/linodes/linodes';
+
+interface Actions {
+ createLinode: (data: CreateLinodeRequest) => Promise;
}
-/* tslint:disable-next-line */
-export interface StateProps {
- linodesError?: APIError[];
- linodesLoading: State['loading'];
- linodesData: LinodeWithMaintenanceAndDisplayStatus[];
- linodesLastUpdated: State['lastUpdated'];
- linodesResults: State['results'];
+export interface WithLinodesProps {
+ linodesError: APIError[] | null;
+ linodesLoading: boolean;
+ linodesData: Linode[] | undefined;
+ linodeActions: Actions;
}
-type MapProps = (
- ownProps: OwnProps,
- linodes: Linode[],
- loading: boolean,
- error?: APIError[]
-) => ReduxStateProps & Partial;
-
-export type Props = DispatchProps & StateProps;
-
-interface Connected {
- (
- mapStateToProps: MapProps
- ): InferableComponentEnhancerWithProps<
- ReduxStateProps & Partial & DispatchProps & OwnProps,
- OwnProps
- >;
- (): InferableComponentEnhancerWithProps<
- ReduxStateProps & DispatchProps & OwnProps,
- OwnProps
- >;
-}
-
-const connected: Connected = (
- mapStateToProps?: MapProps
-) =>
- connect<
- (ReduxState & Partial) | StateProps,
- DispatchProps,
- OwnProps,
- ApplicationState
- >(
- (state, ownProps) => {
- const {
- loading,
- error,
- itemsById,
- lastUpdated,
- results,
- } = state.__resources.linodes;
- const linodes = Object.values(itemsById);
- if (mapStateToProps) {
- return mapStateToProps(
- ownProps,
- linodes,
- loading,
- path(['read'], error)
- );
- }
-
- return {
- linodesError: path(['read'], error),
- linodesLoading: loading,
- linodesData: linodes,
- linodesResults: results,
- linodesLastUpdated: lastUpdated,
- };
+export const withLinodes = (
+ Component: React.ComponentType
+) => (props: Props) => {
+ const {
+ data: linodesData,
+ isLoading: linodesLoading,
+ error: linodesError,
+ } = useAllLinodesQuery();
+
+ const { mutateAsync: createLinode } = useCreateLinodeMutation();
+
+ return React.createElement(Component, {
+ ...props,
+ linodesData,
+ linodesLoading,
+ linodesError,
+ linodeActions: {
+ createLinode,
},
- (dispatch: ThunkDispatch) => ({
- getLinodes: (params, filter) =>
- dispatch(requestLinodes({ params, filter })),
- })
- );
-
-export default connected;
+ });
+};
diff --git a/packages/manager/src/features/Account/EnableManaged.tsx b/packages/manager/src/features/Account/EnableManaged.tsx
index 84e2a859676..486c9682966 100644
--- a/packages/manager/src/features/Account/EnableManaged.tsx
+++ b/packages/manager/src/features/Account/EnableManaged.tsx
@@ -9,27 +9,20 @@ import Typography from 'src/components/core/Typography';
import ExternalLink from 'src/components/ExternalLink';
import Grid from '@mui/material/Unstable_Grid2';
import { SupportLink } from 'src/components/SupportLink';
-import withLinodes, {
- DispatchProps,
-} from 'src/containers/withLinodes.container';
import { pluralize } from 'src/utilities/pluralize';
import { updateAccountSettingsData } from 'src/queries/accountSettings';
import { useQueryClient } from 'react-query';
+import { useLinodesQuery } from 'src/queries/linodes/linodes';
interface Props {
isManaged: boolean;
}
-interface StateProps {
- linodeCount: number;
-}
-
-type CombinedProps = Props & StateProps & DispatchProps;
-
interface ContentProps {
isManaged: boolean;
openConfirmationModal: () => void;
}
+
export const ManagedContent = (props: ContentProps) => {
const { isManaged, openConfirmationModal } = props;
@@ -66,13 +59,16 @@ export const ManagedContent = (props: ContentProps) => {
);
};
-export const EnableManaged = (props: CombinedProps) => {
- const { isManaged, linodeCount } = props;
+export const EnableManaged = (props: Props) => {
+ const { isManaged } = props;
const queryClient = useQueryClient();
+ const { data: linodes } = useLinodesQuery();
const [isOpen, setOpen] = React.useState(false);
const [error, setError] = React.useState();
const [isLoading, setLoading] = React.useState(false);
+ const linodeCount = linodes?.results ?? 0;
+
const handleClose = () => {
setOpen(false);
setError(undefined);
@@ -94,7 +90,7 @@ export const EnableManaged = (props: CombinedProps) => {
.catch(handleError);
};
- const actions = () => (
+ const actions = (