Skip to content

Commit

Permalink
fix: [M3-6472] - [Marketplace] One Click Cluster - UDF Caching issue (#…
Browse files Browse the repository at this point in the history
…8997)

* fix: [M3-6472] - [Marketplace] One Click Cluster - UDF Caching issue

* PR feedback

* Update packages/manager/src/features/StackScripts/UserDefinedFieldsPanel/FieldTypes/UserDefinedSelect.tsx

Co-authored-by: Banks Nussman <115251059+bnussman-akamai@users.noreply.github.com>

* PR feedback

* Update CHANGELOG.md

---------

Co-authored-by: Banks Nussman <115251059+bnussman-akamai@users.noreply.github.com>
  • Loading branch information
cpathipa and bnussman-akamai authored Apr 17, 2023
1 parent ee30268 commit 2e0805a
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 93 deletions.
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
## [2023-04-03] - v1.90.0

### Added:

- Delete warning to LKE [#8891](https://github.com/linode/manager/pull/8891)
- “to another region” to the title of the Linode Migrate Dialog [#8920](https://github.com/linode/manager/pull/8920)

### Changed:

- Disable Download CA Certificate when DB is provisioning [#8890](https://github.com/linode/manager/pull/8890)
- Update OCC logos to include naming convention [#8927](https://github.com/linode/manager/pull/8927)
- MUI v5 Migration - Features > Billing [#8895](https://github.com/linode/manager/pull/8895)
Expand All @@ -41,29 +43,35 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- React Query for Notifications [#8915](https://github.com/linode/manager/pull/8915)

### Fixed:

- Filtering by `Status` on Linode Details Volumes Table [#8947](https://github.com/linode/manager/pull/8947)
- Tag drawer in LinodesLanding summary view [#8909](https://github.com/linode/manager/pull/8909)
- Crash for Events with a `null` community post `entity` [#8912](https://github.com/linode/manager/pull/8912)
- Incorrect headline in Linode Details Networking table [#8925](https://github.com/linode/manager/pull/8925)
- One Click Cluster UDF Caching issue [#8997](https://github.com/linode/manager/pull/8997)

### Removed:

- Repo clean up, remove old Redux Docs [#8907](https://github.com/linode/manager/pull/8907)

## [2023-03-28] - v1.89.1

### Fixed:

- NodeBalancer Configurations not saving [#8929](https://github.com/linode/manager/pull/8929)

## [2023-03-20] - v1.89.0

### Added:

- One Click Clusters [#8878](​​https://github.com/linode/manager/pull/8878)
- Infinitely Loaded Volume Select [#8876](https://github.com/linode/manager/pull/8876)
- Allow users to select `system` as a theme option [#8869](https://github.com/linode/manager/pull/8869)
- Vite [#8838](https://github.com/linode/manager/pull/8838)
- Resource links to Kubernetes empty state landing page [#8827](https://github.com/linode/manager/pull/8827)

### Changed:

- Updated maintenance and account activation screen logo [#8879](https://github.com/linode/manager/pull/8879)
- Updated `VolumeStatus` type and logic [#8862](https://github.com/linode/manager/pull/8862)
- Temporarily changed Remit To invoice address [#8847](https://github.com/linode/manager/pull/8847)
Expand All @@ -73,26 +81,31 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Use region `label` from `/v4/regions` instead of `dcDisplayNames` constant [#8851](https://github.com/linode/manager/pull/8851)

### Fixed:

- Use our custom dialog for Monthly Network Transfer Pool instead of MUI's [#8874](https://github.com/linode/manager/pull/8874)
- Radio Styles after Vite Upgrade [#8871](https://github.com/linode/manager/pull/8871)
- Disable/hide showAll for PaginationFooter [#8826](https://github.com/linode/manager/pull/8826)
- Invalidate Firewall devices cache when a Linode is deleted [#8848](https://github.com/linode/manager/pull/8848)

### Removed:

- VLANs from Redux [#8872](https://github.com/linode/manager/pull/8872)
- Unused packages + update lint-staged [#8860](https://github.com/linode/manager/pull/8860)
- /core/styles abstraction for tss-react codemod [#8875](https://github.com/linode/manager/pull/8875)

## [2023-03-06] - v1.88.0

### Breaking:

- Remove deprecated `ip_whitelist_enabled` Profile Toggle

### Added:

- Support for local development access from local domain
- Account Logins Show `Successful` or `Failed` Access

### Changed:

- Increased minimum acceptable password strength for Linode root passwords
- Use React Query to fetch and store user preferences, tags, and images
- Use `URLSearchParams` to standardize query string parsing and stringifying
Expand All @@ -102,47 +115,57 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- Use Region ID to dynamically generate LISH URLs

### Removed:

- `wait-on` package for CVE-2023-25166

### Fixed:

- Firewall Rules Table rendering overlapping text
- `validateDOMNesting` warning in console

## [2023-02-21] - v1.87.0

### Added:

- Ability to create Object Storage folders

### Changed:

- Standardize Text tooltip
- Prevent Firewall Rule Drawer reset if the same preset is reselected

## [2023-02-13] - v1.86.0

### Added:

- “Status” column to Linode Backups table

### Changed:

- Migrate to Material UI v5 theme format
- Accessibility improvements to TopMenu icons
- Logo updates
- Account Agreements Query Small Optimization

### Fixed:

- Uneven Breakpoints in Kubernetes Landing Table

## [2023-02-07] - v1.85.0

### Added:

- Databases as a User Permissions Option
- Monthly Network Transfer Pool to select empty state landing pages
- API/CLI usage information to Linode Create

### Changed:

- Improve firewall rule list screen reader support
- UX copy for “Getting Started” playlists

### Fixed:

- API Tokens revocation

## [2023-01-18] - v1.84.0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React from 'react';
import { fireEvent } from '@testing-library/react';
import { renderWithTheme } from 'src/utilities/testHelpers';
import { UserDefinedSelect } from './UserDefinedSelect';

describe('UserDefinedSelect', () => {
it('renders select when oneof has more than 4 options', () => {
const field = {
name: 'selectField',
label: 'Select Field',
oneof: 'option1,option2,option3,option4,option5',
};
const { getByLabelText, getByText } = renderWithTheme(
<UserDefinedSelect
field={field}
value=""
updateFormState={() => {}}
isOptional={false}
/>
);

const selectField = getByLabelText('Select Field');
fireEvent.change(selectField, { target: { value: 'option3' } });

expect(getByText('option3')).toBeInTheDocument();
});

it('renders radio when oneof has 4 or fewer options', () => {
const field = {
name: 'radioField',
label: 'Radio Field',
oneof: 'option1,option2,option3,option4',
};
const updateFormState = jest.fn();
const { getAllByRole } = renderWithTheme(
<UserDefinedSelect
field={field}
value=""
updateFormState={updateFormState}
isOptional={false}
/>
);

const radioElements = getAllByRole('radio');

expect(radioElements.length).toEqual(4);
});

it('calls updateFormState when a new option is selected', () => {
const field = {
name: 'selectField',
label: 'Select Field',
oneof: 'option1,option2,option3,option4',
};
const updateFormState = jest.fn();
const { getAllByRole } = renderWithTheme(
<UserDefinedSelect
field={field}
value=""
updateFormState={updateFormState}
isOptional={false}
/>
);

const radioElements = getAllByRole('radio');

fireEvent.click(radioElements[2]);

expect(updateFormState).toHaveBeenCalledWith('selectField', 'option3');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,25 @@ import { UserDefinedField } from '@linode/api-v4/lib/stackscripts';
import * as React from 'react';
import FormControlLabel from 'src/components/core/FormControlLabel';
import InputLabel from 'src/components/core/InputLabel';
import { createStyles, withStyles, WithStyles } from '@mui/styles';
import { makeStyles } from '@mui/styles';
import { Theme } from '@mui/material/styles';
import MenuItem from 'src/components/MenuItem';
import Notice from 'src/components/Notice';
import Radio from 'src/components/Radio';
import RenderGuard from 'src/components/RenderGuard';
import TextField from 'src/components/TextField';

type ClassNames = 'root' | 'radioGroupLabel';

const styles = (theme: Theme) =>
createStyles({
root: {
margin: `${theme.spacing(3)} 0 0`,
display: 'flex',
flexDirection: 'column',
marginTop: '16px',
},
radioGroupLabel: {
display: 'block',
marginBottom: '4px',
},
});
const useStyles = makeStyles((theme: Theme) => ({
root: {
margin: `${theme.spacing(3)} 0 0`,
display: 'flex',
flexDirection: 'column',
marginTop: '16px',
},
radioGroupLabel: {
display: 'block',
marginBottom: '4px',
},
}));

interface Props {
updateFormState: (key: string, value: any) => void;
Expand All @@ -34,88 +30,66 @@ interface Props {
error?: string;
}

interface State {
oneof: string[];
selectedOption: string;
}

type CombinedProps = Props & WithStyles<ClassNames>;
export const UserDefinedSelect = (props: Props) => {
const classes = useStyles();

class UserDefinedSelect extends React.Component<CombinedProps, State> {
state: State = {
oneof: this.props.field.oneof!.split(','),
selectedOption: '',
};
const { field, value, error, isOptional, updateFormState } = props;

handleSelectOneOf = (e: any) => {
const { updateFormState, field } = this.props;
updateFormState(field.name, e.target.value);
};
const [oneof, setOneof] = React.useState<string[]>(field.oneof!.split(','));

render() {
const { oneof } = this.state;
const { value, error, field, classes, isOptional } = this.props;
React.useEffect(() => {
setOneof(field.oneof!.split(','));
}, [field.oneof]);

/* Display a select if there are more than 2 oneof options, otherwise display as radio. */
if (oneof.length > 4) {
return (
<div>
{error && <Notice error text={error} spacingTop={8} />}
<TextField
label={field.label}
onChange={this.handleSelectOneOf}
value={value}
select
>
{oneof.map((choice: string, index) => {
return (
<MenuItem value={choice} key={index}>
{choice}
</MenuItem>
);
})}
</TextField>
</div>
);
} else {
return (
<div className={classes.root}>
{error && <Notice error text={error} spacingTop={8} />}
<InputLabel className={classes.radioGroupLabel}>
{field.label}
{!isOptional && '*'}
</InputLabel>
const handleSelectOneOf = (e: React.ChangeEvent<HTMLInputElement>) => {
const selectedValue = e.target.value;
updateFormState(field.name, selectedValue);
};

if (oneof.length > 4) {
return (
<div>
{error && <Notice error text={error} spacingTop={8} />}
<TextField
label={field.label}
onChange={handleSelectOneOf}
value={value}
select
>
{oneof.map((choice: string, index) => {
return (
<React.Fragment key={index}>
<FormControlLabel
value={choice}
control={
<Radio
name={choice}
checked={!!value && value === choice}
/*
NOTE: Although the API returns a default value and we're auto selecting
a value for the user, it is not necessary to store this value
in the state because it's not necessary for the POST request, since
the backend will automatically POST with that default value
*/
onChange={this.handleSelectOneOf}
data-qa-perm-none-radio
/>
}
label={choice}
/>
</React.Fragment>
<MenuItem value={choice} key={index}>
{choice}
</MenuItem>
);
})}
</div>
);
}
</TextField>
</div>
);
}
}

const styled = withStyles(styles);
return (
<div className={classes.root}>
{error && <Notice error text={error} spacingTop={8} />}
<InputLabel className={classes.radioGroupLabel}>
{field.label}
{!isOptional && '*'}
</InputLabel>

export default styled(RenderGuard<CombinedProps>(UserDefinedSelect));
{oneof.map((choice: string, index) => (
<FormControlLabel
value={choice}
key={index}
control={
<Radio
name={choice}
checked={!!value && value === choice}
onChange={handleSelectOneOf}
data-qa-perm-none-radio
/>
}
label={choice}
/>
))}
</div>
);
};
Loading

0 comments on commit 2e0805a

Please sign in to comment.