Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
useAccountUsersInfiniteQuery,
useAllAccountUsersQuery,
useUpdateChildAccountDelegatesQuery,
} from '@linode/queries';
import { ActionsPanel, Autocomplete, Notice, Typography } from '@linode/ui';
Expand Down Expand Up @@ -41,6 +42,7 @@ export const UpdateDelegationForm = ({
}: DelegationsFormProps) => {
const theme = useTheme();
const [inputValue, setInputValue] = React.useState<string>('');
const [allUserSelected, setAllUserSelected] = React.useState<boolean>(false);
const debouncedInputValue = useDebouncedValue(inputValue);

const { data: permissions } = usePermissions('account', [
Expand All @@ -55,13 +57,26 @@ export const UpdateDelegationForm = ({
const { data, error, fetchNextPage, hasNextPage, isFetching } =
useAccountUsersInfiniteQuery(apiFilter);

const {
data: allUsers,
isFetching: isFetchingAllUsers,
refetch: refetchAllUsers,
} = useAllAccountUsersQuery(allUserSelected, {
user_type: 'parent',
});

const users =
data?.pages.flatMap((page) => {
return page.data.map((user) => ({
label: user.username,
value: user.username,
}));
}) ?? [];
allUserSelected && allUsers
? allUsers.map((user) => ({
label: user.username,
value: user.username,
}))
: (data?.pages.flatMap((page) => {
return page.data.map((user) => ({
label: user.username,
value: user.username,
}));
}) ?? []);

const { mutateAsync: updateDelegates } =
useUpdateChildAccountDelegatesQuery();
Expand All @@ -78,6 +93,7 @@ export const UpdateDelegationForm = ({
handleSubmit,
reset,
setError,
setValue,
} = form;

const onSubmit = async (values: UpdateDelegationsFormValues) => {
Expand All @@ -99,9 +115,21 @@ export const UpdateDelegationForm = ({
}
};

const onSelectAllClick = async () => {
setAllUserSelected(true);
const { data } = await refetchAllUsers();
if (data) {
setValue(
'users',
data.map((user) => ({ label: user.username, value: user.username }))
);
}
};

const handleClose = () => {
reset();
onClose();
setAllUserSelected(false);
};

return (
Expand Down Expand Up @@ -135,12 +163,13 @@ export const UpdateDelegationForm = ({
render={({ field, fieldState }) => (
<Autocomplete
data-testid="delegates-autocomplete"
disabled={isFetchingAllUsers}
errorText={fieldState.error?.message ?? error?.[0].reason}
isOptionEqualToValue={(option, value) =>
option.value === value.value
}
label={'Delegate Users'}
loading={isFetching}
loading={isFetching || isFetchingAllUsers}
multiple
noMarginTop
onChange={(_, newValue) => {
Expand All @@ -149,6 +178,11 @@ export const UpdateDelegationForm = ({
onInputChange={(_, value) => {
setInputValue(value);
}}
onSelectAllClick={(isSelectAllActive) => {
if (isSelectAllActive && !allUserSelected) {
onSelectAllClick();
}
}}
options={users}
placeholder={getPlaceholder(
'delegates',
Expand Down
20 changes: 19 additions & 1 deletion packages/ui/src/components/Autocomplete/Autocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export interface EnhancedAutocompleteProps<
noMarginTop?: boolean;
/** Element to show when the Autocomplete search yields no results. */
noOptionsText?: JSX.Element | string;
/** Handler called when the Select All option is clicked. */
onSelectAllClick?: (
event: React.MouseEvent<HTMLLIElement, MouseEvent>,
) => void;
placeholder?: string;
renderInput?: (_params: AutocompleteRenderInputParams) => React.ReactNode;
/** Label for the "select all" option. */
Expand Down Expand Up @@ -96,6 +100,7 @@ export const Autocomplete = <
keepSearchEnabledOnMobile = false,
onBlur,
onChange,
onSelectAllClick,
options,
placeholder,
renderInput,
Expand Down Expand Up @@ -191,16 +196,29 @@ export const Autocomplete = <
const isSelectAllOption = option === selectAllOption;
const ListItem = isSelectAllOption ? StyledListItem : 'li';

// If this is the Select All option, add a click handler
const handleClick = (
event: React.MouseEvent<HTMLLIElement, MouseEvent>,
) => {
if (isSelectAllOption && onSelectAllClick) {
onSelectAllClick(event);
}
if (props.onClick) {
props.onClick(event);
}
};

return renderOption ? (
renderOption(props, option, state, ownerState)
) : (
<ListItem
{...props}
data-pendo-id={
rest.getOptionLabel ? rest.getOptionLabel(option) : option.label
} // Adding data-pendo-id for better tracking in Pendo analytics, using the option label as the identifier for the option element.
}
data-qa-option
key={props.key}
onClick={isSelectAllOption ? handleClick : props.onClick}
>
<>
<Box
Expand Down