Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v1.96.2 – masterdevelop #9343

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
7 changes: 7 additions & 0 deletions packages/api-v4/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## [2023-06-27] - v0.95.1


### Fixed:

- Updated Entity interface to reflect the possibility of a null label ([#9331](https://github.com/linode/manager/pull/9331))

## [2023-06-26] - v0.95.0

### Added:
Expand Down
2 changes: 1 addition & 1 deletion packages/api-v4/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@linode/api-v4",
"version": "0.95.0",
"version": "0.95.1",
"homepage": "https://github.com/linode/manager/tree/develop/packages/api-v4",
"bugs": {
"url": "https://github.com/linode/manager/issues"
Expand Down
2 changes: 1 addition & 1 deletion packages/api-v4/src/account/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ export interface Notification {

export interface Entity {
id: number;
label: string;
label: string | null;
type: string;
url: string;
}
Expand Down
16 changes: 16 additions & 0 deletions packages/manager/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ 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-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:

- Crash when viewing notifications due to `null` label in event entity ([#9331](https://github.com/linode/manager/pull/9331))

## [2023-06-26] - v1.96.0

### Added:
Expand Down
2 changes: 1 addition & 1 deletion packages/manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "linode-manager",
"author": "Linode",
"description": "The Linode Manager website",
"version": "1.96.0",
"version": "1.96.2",
"private": true,
"bugs": {
"url": "https://github.com/Linode/manager/issues"
Expand Down
16 changes: 0 additions & 16 deletions packages/manager/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 (
<ErrorBoundary fallback={<TheApplicationIsOnFire />}>
{/** Accessibility helper */}
Expand Down
121 changes: 35 additions & 86 deletions packages/manager/src/containers/withLinodes.container.ts
Original file line number Diff line number Diff line change
@@ -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<GetAllData<Linode>>;
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<Linode>;
}

/* 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<ReduxStateProps, OwnProps> = (
ownProps: OwnProps,
linodes: Linode[],
loading: boolean,
error?: APIError[]
) => ReduxStateProps & Partial<StateProps>;

export type Props = DispatchProps & StateProps;

interface Connected {
<ReduxStateProps, OwnProps>(
mapStateToProps: MapProps<ReduxStateProps, OwnProps>
): InferableComponentEnhancerWithProps<
ReduxStateProps & Partial<StateProps> & DispatchProps & OwnProps,
OwnProps
>;
<ReduxStateProps, OwnProps>(): InferableComponentEnhancerWithProps<
ReduxStateProps & DispatchProps & OwnProps,
OwnProps
>;
}

const connected: Connected = <ReduxState extends {}, OwnProps extends {}>(
mapStateToProps?: MapProps<ReduxState, OwnProps>
) =>
connect<
(ReduxState & Partial<StateProps>) | 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 = <Props>(
Component: React.ComponentType<Props & WithLinodesProps>
) => (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;
});
};
13 changes: 13 additions & 0 deletions packages/manager/src/eventMessageGenerator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,5 +141,18 @@ describe('Event message generation', () => {
'created entity <a href="/linodes/10">Weird label with special characters.(?)</a> '
);
});

it('should work when label is null', () => {
const mockEvent = eventFactory.build({
entity: entityFactory.build({
id: 10,
label: null,
}),
});
const message = 'created entity Null label';
const result = applyLinking(mockEvent, message);

expect(result).toEqual('created entity Null label');
});
});
});
12 changes: 6 additions & 6 deletions packages/manager/src/eventMessageGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,19 @@ export const eventMessageCreators: { [index: string]: CreatorsForStatus } = {
},
community_question_reply: {
notification: (e) =>
e.entity
e.entity?.label
? `There has been a reply to your thread "${e.entity.label}".`
: `There has been a reply to your thread.`,
},
community_like: {
notification: (e) =>
e.entity
e.entity?.label
? `A post on "${e.entity.label}" has been liked.`
: `There has been a like on your community post.`,
},
community_mention: {
notification: (e) =>
e.entity
e.entity?.label
? `You have been mentioned in a Community post: ${e.entity.label}.`
: `You have been mentioned in a Community post.`,
},
Expand Down Expand Up @@ -790,7 +790,7 @@ export default (e: Event): string => {
/** finally return some default fallback text */
return e.message
? formatEventWithAPIMessage(e)
: `${e.action}${e.entity ? ` on ${e.entity.label}` : ''}`;
: `${e.action}${e.entity?.label ? ` on ${e.entity.label}` : ''}`;
}

let message = '';
Expand Down Expand Up @@ -872,7 +872,7 @@ export function applyLinking(event: Event, message: string) {

let newMessage = message;

if (event.entity && entityLinkTarget) {
if (event.entity?.label && entityLinkTarget) {
const label = event.entity.label;
const nonTickedLabels = new RegExp(`(?<!\`)${escapeRegExp(label)}`, 'g');

Expand All @@ -882,7 +882,7 @@ export function applyLinking(event: Event, message: string) {
);
}

if (event.secondary_entity && secondaryEntityLinkTarget) {
if (event.secondary_entity?.label && secondaryEntityLinkTarget) {
newMessage = newMessage.replace(
event.secondary_entity.label,
`<a href="${secondaryEntityLinkTarget}">${event.secondary_entity.label}</a>`
Expand Down
26 changes: 8 additions & 18 deletions packages/manager/src/features/Account/EnableManaged.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<boolean>(false);
const [error, setError] = React.useState<string | undefined>();
const [isLoading, setLoading] = React.useState<boolean>(false);

const linodeCount = linodes?.results ?? 0;

const handleClose = () => {
setOpen(false);
setError(undefined);
Expand All @@ -94,7 +90,7 @@ export const EnableManaged = (props: CombinedProps) => {
.catch(handleError);
};

const actions = () => (
const actions = (
<ActionsPanel>
<Button buttonType="secondary" onClick={handleClose} data-qa-cancel>
Cancel
Expand Down Expand Up @@ -137,9 +133,3 @@ export const EnableManaged = (props: CombinedProps) => {
</>
);
};

export default withLinodes<StateProps, Props>(
(ownProps, entities, loading, error) => ({
linodeCount: entities.length,
})
)(EnableManaged);
Loading