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

refactor: [M3-6908] - Replace react-select in Profile #10780

Merged
merged 19 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
d012b8e
refactor: [M3-6908] - Replace react-select in Profile
carrillo-erik Aug 13, 2024
6b7baf6
Update PhoneVerification styles
carrillo-erik Aug 20, 2024
aee6afa
Comment out styles
carrillo-erik Aug 20, 2024
6e4a51a
Updates to Autocomplete to allow custom styles for PopperComponent
carrillo-erik Aug 21, 2024
5b08296
Reapply updates to CreateAPITokenDrawer
carrillo-erik Aug 21, 2024
b6807a0
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Aug 21, 2024
230812b
Add changeset
carrillo-erik Aug 21, 2024
d3d2a98
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Aug 22, 2024
c9308f2
Revert changes to TimezoneForm
carrillo-erik Aug 22, 2024
a176f78
Fix more styling issues and mobile view
carrillo-erik Aug 22, 2024
25983a1
Fix broken unit tests in CreateAPITokenDrawer
carrillo-erik Aug 23, 2024
ff18e58
Fix broken unit test in TimezoneForm
carrillo-erik Aug 23, 2024
9b8bd24
Fix e2e test in Billing
carrillo-erik Aug 23, 2024
438dc0c
Fix failing e2e and console errors mentioned in PR review
carrillo-erik Aug 27, 2024
ec934c1
Fix styling issues from PR review
carrillo-erik Aug 28, 2024
dc365cf
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Sep 4, 2024
f5889f2
Fix selected option highlight in Question Component
carrillo-erik Sep 4, 2024
306dbd1
Merge branch 'develop' of https://github.com/linode/manager into refa…
carrillo-erik Sep 11, 2024
965139d
Fix failing test, ui bug, and 3rd party auth bug
carrillo-erik Sep 11, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/manager": Tech Stories
---

Replace 'react-select' with Autocomplete in Profile ([#10780](https://github.com/linode/manager/pull/10780))
mjac0bs marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ const setSecurityQuestionAnswer = (
answer: string
) => {
getSecurityQuestion(questionNumber).within(() => {
cy.get('[data-qa-enhanced-select]')
cy.findByLabelText(`Question ${questionNumber}`)
.should('be.visible')
.click()
.type(`${question}{enter}`);
Expand Down
6 changes: 5 additions & 1 deletion packages/manager/src/MainContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,11 @@ const Kubernetes = React.lazy(() =>
}))
);
const ObjectStorage = React.lazy(() => import('src/features/ObjectStorage'));
const Profile = React.lazy(() => import('src/features/Profile/Profile'));
const Profile = React.lazy(() =>
import('src/features/Profile/Profile').then((module) => ({
default: module.Profile,
}))
);
const NodeBalancers = React.lazy(
() => import('src/features/NodeBalancers/NodeBalancers')
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import DoneIcon from '@mui/icons-material/Done';
import Popper, { PopperProps } from '@mui/material/Popper';
import Popper from '@mui/material/Popper';
import { styled } from '@mui/material/styles';
import React from 'react';

import { omittedProps } from 'src/utilities/omittedProps';

import type { PopperProps } from '@mui/material/Popper';

export const StyledListItem = styled('li', {
label: 'StyledListItem',
shouldForwardProp: omittedProps(['selectAllOption']),
Expand Down
29 changes: 19 additions & 10 deletions packages/manager/src/components/Autocomplete/Autocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import MuiAutocomplete from '@mui/material/Autocomplete';
import React from 'react';

import { Box } from 'src/components/Box';
import { TextField, TextFieldProps } from 'src/components/TextField';
import { TextField } from 'src/components/TextField';

import { CircleProgress } from '../CircleProgress';
import { InputAdornment } from '../InputAdornment';
Expand All @@ -15,6 +15,8 @@ import {
} from './Autocomplete.styles';

import type { AutocompleteProps } from '@mui/material/Autocomplete';
import type { SxProps } from '@mui/system';
import type { TextFieldProps } from 'src/components/TextField';

export interface EnhancedAutocompleteProps<
T extends { label: string },
Expand All @@ -25,6 +27,8 @@ export interface EnhancedAutocompleteProps<
AutocompleteProps<T, Multiple, DisableClearable, FreeSolo>,
'renderInput'
> {
/** Removes "select all" option for mutliselect */
disableSelectAll?: boolean;
/** Provides a hint with error styling to assist users. */
errorText?: string;
/** Provides a hint with normal styling to assist users. */
Expand All @@ -38,8 +42,10 @@ export interface EnhancedAutocompleteProps<
placeholder?: string;
/** Label for the "select all" option. */
selectAllLabel?: string;
/** Removes "select all" option for mutliselect */
disableSelectAll?: boolean;
/**
* The prop that allows defining CSS style overrides for the PopperComponent.
*/
sxPopperComponent?: SxProps;
textFieldProps?: Partial<TextFieldProps>;
}

Expand Down Expand Up @@ -71,6 +77,7 @@ export const Autocomplete = <
clearOnBlur,
defaultValue,
disablePortal = true,
disableSelectAll = false,
errorText = '',
helperText,
label,
Expand All @@ -86,9 +93,9 @@ export const Autocomplete = <
placeholder,
renderOption,
selectAllLabel = '',
sxPopperComponent,
textFieldProps,
value,
disableSelectAll = false,
...rest
} = props;

Expand All @@ -103,6 +110,14 @@ export const Autocomplete = <

return (
<MuiAutocomplete
PopperComponent={(props) => {
return <CustomPopper {...props} sx={sxPopperComponent} />;
}}
options={
multiple && !disableSelectAll && options.length > 0
? optionsWithSelectAll
: options
}
renderInput={(params) => (
<TextField
errorText={errorText}
Expand Down Expand Up @@ -157,7 +172,6 @@ export const Autocomplete = <
);
}}
ChipProps={{ deleteIcon: <CloseIcon /> }}
PopperComponent={CustomPopper}
clearOnBlur={clearOnBlur}
data-qa-autocomplete
defaultValue={defaultValue}
Expand All @@ -169,11 +183,6 @@ export const Autocomplete = <
multiple={multiple}
noOptionsText={noOptionsText || <i>You have no options to choose from</i>}
onBlur={onBlur}
options={
multiple && !disableSelectAll && options.length > 0
? optionsWithSelectAll
: options
}
popupIcon={<KeyboardArrowDownIcon />}
value={value}
{...rest}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ const props = {

describe('Create API Token Drawer', () => {
it('checks API Token Drawer rendering', () => {
const { getByTestId, getByText } = renderWithTheme(
const { getAllByTestId, getByTestId, getByText } = renderWithTheme(
<CreateAPITokenDrawer {...props} />
);
const drawerTitle = getByText('Add Personal Access Token');
expect(drawerTitle).toBeVisible();

const labelTitle = getByText(/Label/);
const labelField = getByTestId('textfield-input');
const labelField = getAllByTestId('textfield-input');
expect(labelTitle).toBeVisible();
expect(labelField).toBeEnabled();
expect(labelField[0]).toBeEnabled();

const expiry = getByText(/Expiry/);
expect(expiry).toBeVisible();
Expand All @@ -67,12 +67,12 @@ describe('Create API Token Drawer', () => {
})
);

const { getByLabelText, getByTestId, getByText } = renderWithTheme(
const { getAllByTestId, getByLabelText, getByText } = renderWithTheme(
<CreateAPITokenDrawer {...props} />
);

const labelField = getByTestId('textfield-input');
await userEvent.type(labelField, 'my-test-token');
const labelField = getAllByTestId('textfield-input');
await userEvent.type(labelField[0], 'my-test-token');

const selectAllNoAccessPermRadioButton = getByLabelText(
'Select no access for all'
Expand Down Expand Up @@ -110,8 +110,10 @@ describe('Create API Token Drawer', () => {
});

it('Should default to 6 months for expiration', () => {
const { getByText } = renderWithTheme(<CreateAPITokenDrawer {...props} />);
getByText('In 6 months');
const { getAllByRole } = renderWithTheme(
<CreateAPITokenDrawer {...props} />
);
expect(getAllByRole('combobox')[0]).toHaveDisplayValue('In 6 months');
});

it('Should show the Child Account Access scope for a parent user account with the parent/child feature flag on', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { DateTime } from 'luxon';
import * as React from 'react';

import { ActionsPanel } from 'src/components/ActionsPanel/ActionsPanel';
import { Autocomplete } from 'src/components/Autocomplete/Autocomplete';
import { Drawer } from 'src/components/Drawer';
import Select, { Item } from 'src/components/EnhancedSelect/Select';
import { FormControl } from 'src/components/FormControl';
import { FormHelperText } from 'src/components/FormHelperText';
import { Notice } from 'src/components/Notice/Notice';
Expand All @@ -30,14 +30,15 @@ import {
StyledSelectCell,
} from './APITokenDrawer.styles';
import {
Permission,
allScopesAreTheSame,
basePermNameMap,
hasAccessBeenSelectedForAllScopes,
permTuplesToScopeString,
scopeStringToPermTuples,
} from './utils';

import type { Permission } from './utils';

type Expiry = [string, string];

export const genExpiryTups = (): Expiry[] => {
Expand Down Expand Up @@ -172,10 +173,6 @@ export const CreateAPITokenDrawer = (props: Props) => {
form.setFieldValue('scopes', newScopes);
};

const handleExpiryChange = (e: Item<string>) => {
form.setFieldValue('expiry', e.value);
};

// Permission scopes with a different default when Selecting All for the specified access level.
const excludedScopesFromSelectAll: ExcludedScope[] = [
{
Expand Down Expand Up @@ -214,11 +211,26 @@ export const CreateAPITokenDrawer = (props: Props) => {
value={form.values.label}
/>
<FormControl data-testid="expiry-select">
<Select
isClearable={false}
<Autocomplete
onChange={(_, selected) =>
form.setFieldValue('expiry', selected.value)
}
sx={{
'&& .MuiAutocomplete-inputRoot': {
paddingLeft: 1,
paddingRight: 0,
},
'&& .MuiInput-input': {
padding: '0px 2px',
},
}}
sxPopperComponent={{
'&& .MuiAutocomplete-listbox': {
padding: 0,
},
}}
disableClearable
label="Expiry"
name="expiry"
onChange={handleExpiryChange}
options={expiryList}
value={expiryList.find((item) => item.value === form.values.expiry)}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { styled } from '@mui/material/styles';

import { Autocomplete } from 'src/components/Autocomplete/Autocomplete';
import { Box } from 'src/components/Box';
import Select from 'src/components/EnhancedSelect/Select';
import { FormHelperText } from 'src/components/FormHelperText';
import { TextField } from 'src/components/TextField';
import { Typography } from 'src/components/Typography';
import { FormHelperText } from 'src/components/FormHelperText';

export const StyledCodeSentMessageBox = styled(Box, {
label: 'StyledCodeSentMessageBox',
Expand All @@ -19,18 +19,21 @@ export const StyledPhoneNumberTitle = styled(Typography, {
marginTop: theme.spacing(1.5),
}));

export const StyledButtonContainer = styled(Box, {
label: 'StyledButtonContainer',
export const StyledLabel = styled(Typography, {
label: 'StyledLabel',
})(({ theme }) => ({
gap: theme.spacing(),
[theme.breakpoints.down('md')]: {
marginTop: theme.spacing(2),
},
color: theme.name === 'light' ? '#555' : '#c9cacb',
fontSize: '.875rem',
lineHeight: '1',
marginBottom: '8px',
marginTop: theme.spacing(2),
padding: 0,
}));

export const StyledInputContainer = styled(Box, {
label: 'StyledInputContainer',
})<{ isPhoneInputFocused: boolean }>(({ isPhoneInputFocused, theme }) => ({
mjac0bs marked this conversation as resolved.
Show resolved Hide resolved
backgroundColor: theme.name === 'dark' ? '#343438' : undefined,
border: theme.name === 'light' ? '1px solid #ccc' : '1px solid #222',
transition: 'border-color 225ms ease-in-out',
width: 'fit-content',
Expand All @@ -46,9 +49,16 @@ export const StyledInputContainer = styled(Box, {
})),
}));

export const StyledPhoneNumberInput = styled(TextField, {
label: 'StyledPhoneNumberInput',
})(() => ({
export const StyledISOCodeSelect = styled(Autocomplete, {
label: 'StyledISOCodeSelect',
})(({ theme }) => ({
'& .MuiAutocomplete-inputRoot': {
border: 'unset',
},
'&& .MuiInputBase-root svg': {
color: `${theme.palette.primary.main}`,
opacity: '1',
},
'&.Mui-focused': {
borderColor: 'unset',
boxShadow: 'none',
Expand All @@ -57,17 +67,13 @@ export const StyledPhoneNumberInput = styled(TextField, {
borderColor: 'unset',
boxShadow: 'unset',
},
border: 'unset',
minWidth: '300px',
height: '34px',
width: '70px !important',
}));

export const StyledSelect = styled(Select, {
label: 'StyledSelect',
})(({ theme }) => ({
'& .MuiInputBase-input .react-select__indicators svg': {
color: `${theme.palette.primary.main} !important`,
opacity: '1 !important',
},
export const StyledPhoneNumberInput = styled(TextField, {
label: 'StyledPhoneNumberInput',
})(() => ({
'&.Mui-focused': {
borderColor: 'unset',
boxShadow: 'none',
Expand All @@ -77,19 +83,7 @@ export const StyledSelect = styled(Select, {
boxShadow: 'unset',
},
border: 'unset',
height: '34px',
width: '70px !important',
}));

export const StyledLabel = styled(Typography, {
label: 'StyledLabel',
})(({ theme }) => ({
color: theme.name === 'light' ? '#555' : '#c9cacb',
fontSize: '.875rem',
lineHeight: '1',
marginBottom: '8px',
marginTop: theme.spacing(2),
padding: 0,
minWidth: '300px',
}));

export const StyledFormHelperText = styled(FormHelperText, {
Expand All @@ -102,3 +96,12 @@ export const StyledFormHelperText = styled(FormHelperText, {
top: 42,
width: '100%',
}));

export const StyledButtonContainer = styled(Box, {
label: 'StyledButtonContainer',
})(({ theme }) => ({
gap: theme.spacing(),
[theme.breakpoints.down('md')]: {
marginTop: theme.spacing(2),
},
}));
Loading
Loading