diff --git a/ui/actions/manage-groups/manage-groups.ts b/ui/actions/manage-groups/manage-groups.ts index a42684a40c..206a2f4a89 100644 --- a/ui/actions/manage-groups/manage-groups.ts +++ b/ui/actions/manage-groups/manage-groups.ts @@ -158,10 +158,10 @@ export const updateProviderGroup = async ( const providersJson = formData.get("providers") as string; const rolesJson = formData.get("roles") as string; - const providers = providersJson ? JSON.parse(providersJson) : []; - const roles = rolesJson ? JSON.parse(rolesJson) : []; + const providers = providersJson ? JSON.parse(providersJson) : null; + const roles = rolesJson ? JSON.parse(rolesJson) : null; - const payload: ManageGroupPayload = { + const payload: Partial = { data: { type: "provider-groups", id: providerGroupId, @@ -170,14 +170,15 @@ export const updateProviderGroup = async ( }, }; - // Add relationships only if there are items - if (providers.length >= 0) { - payload.data.relationships!.providers = { data: providers }; + // Add relationships only if changes are detected + if (providers) { + payload.data!.relationships!.providers = { data: providers }; } - if (roles.length >= 0) { - payload.data.relationships!.roles = { data: roles }; + if (roles) { + payload.data!.relationships!.roles = { data: roles }; } + try { const url = `${keyServer}/provider-groups/${providerGroupId}`; const response = await fetch(url, { @@ -192,8 +193,6 @@ export const updateProviderGroup = async ( if (!response.ok) { const errorResponse = await response.json(); - // eslint-disable-next-line no-console - console.error("Error response:", errorResponse); throw new Error( `Failed to update provider group: ${response.status} ${response.statusText}`, ); @@ -203,7 +202,6 @@ export const updateProviderGroup = async ( revalidatePath("/manage-groups"); return parseStringify(data); } catch (error) { - // eslint-disable-next-line no-console console.error("Unexpected error:", error); return { error: getErrorMessage(error), diff --git a/ui/components/manage-groups/forms/edit-group-form.tsx b/ui/components/manage-groups/forms/edit-group-form.tsx index 193800e580..4a58622d2c 100644 --- a/ui/components/manage-groups/forms/edit-group-form.tsx +++ b/ui/components/manage-groups/forms/edit-group-form.tsx @@ -50,10 +50,12 @@ export const EditGroupForm = ({ try { const updatedFields: Partial = {}; + // Detect changes in the name if (values.name !== providerGroupData.name) { updatedFields.name = values.name; } + // Detect changes in providers if ( JSON.stringify(values.providers) !== JSON.stringify(providerGroupData.providers) @@ -61,12 +63,14 @@ export const EditGroupForm = ({ updatedFields.providers = values.providers; } + // Detect changes in roles if ( JSON.stringify(values.roles) !== JSON.stringify(providerGroupData.roles) ) { updatedFields.roles = values.roles; } + // If no changes, notify the user and exit if (Object.keys(updatedFields).length === 0) { toast({ title: "No changes detected", @@ -75,6 +79,7 @@ export const EditGroupForm = ({ return; } + // Create FormData dynamically const formData = new FormData(); if (updatedFields.name) { formData.append("name", updatedFields.name); @@ -94,6 +99,7 @@ export const EditGroupForm = ({ formData.append("roles", JSON.stringify(rolesData)); } + // Call the update action const data = await updateProviderGroup(providerGroupId, formData); if (data?.errors && data.errors.length > 0) { diff --git a/ui/components/ui/custom/custom-dropdown-selection.tsx b/ui/components/ui/custom/custom-dropdown-selection.tsx index e16d18988d..eb89e1adc4 100644 --- a/ui/components/ui/custom/custom-dropdown-selection.tsx +++ b/ui/components/ui/custom/custom-dropdown-selection.tsx @@ -31,66 +31,50 @@ export const CustomDropdownSelection: React.FC< const [selectedValues, setSelectedValues] = useState>( new Set(selectedKeys), ); - const allValues = values.map((item) => item.id); - const memoizedValues = useMemo(() => values, [values]); + const allValues = useMemo(() => values.map((item) => item.id), [values]); - // Update the internal state when selectedKeys changes from props + // Update internal state when selectedKeys changes useEffect(() => { const newSelection = new Set(selectedKeys); - if ( - JSON.stringify(Array.from(selectedValues)) !== - JSON.stringify(Array.from(newSelection)) - ) { - if (selectedKeys.length === allValues.length) { - newSelection.add("all"); - } - setSelectedValues(newSelection); + if (selectedKeys.length === allValues.length) { + newSelection.add("all"); } - }, [selectedKeys, allValues.length, selectedValues]); + setSelectedValues(newSelection); + }, [selectedKeys, allValues]); const onSelectionChange = useCallback( (keys: string[]) => { - setSelectedValues((prevSelected) => { - const newSelection = new Set(keys); + const newSelection = new Set(keys); - // If all values are selected and "all" is not included, - // add "all" automatically - if ( - newSelection.size === allValues.length && - !newSelection.has("all") - ) { - return new Set(["all", ...allValues]); - } else if (prevSelected.has("all")) { - // If "all" was previously selected, remove it + if (newSelection.has("all")) { + // Handle "Select All" behavior + if (newSelection.size === allValues.length + 1) { + setSelectedValues(new Set(["all", ...allValues])); + onChange(name, allValues); // Exclude "all" in the callback + } else { newSelection.delete("all"); - return new Set(allValues.filter((key) => newSelection.has(key))); + setSelectedValues(newSelection); + onChange(name, Array.from(newSelection)); } - return newSelection; - }); - - // Notify the change without including "all" - const selectedValues = keys.filter((key) => key !== "all"); - onChange(name, selectedValues); + } else { + setSelectedValues(newSelection); + onChange(name, Array.from(newSelection)); + } }, [allValues, name, onChange], ); const handleSelectAllClick = useCallback(() => { - setSelectedValues((prevSelected: Set) => { - const newSelection: Set = prevSelected.has("all") - ? new Set() - : new Set(["all", ...allValues]); - - // Notify the change without including "all" - const selectedValues = Array.from(newSelection).filter( - (key) => key !== "all", - ); - onChange(name, selectedValues); - - return newSelection; - }); - }, [allValues, name, onChange]); + if (selectedValues.has("all")) { + setSelectedValues(new Set()); + onChange(name, []); + } else { + const newSelection = new Set(["all", ...allValues]); + setSelectedValues(newSelection); + onChange(name, allValues); + } + }, [allValues, name, onChange, selectedValues]); return (
@@ -119,7 +103,8 @@ export const CustomDropdownSelection: React.FC< wrapper: "checkbox-update", }} value="all" - onClick={handleSelectAllClick} + isSelected={selectedValues.has("all")} + onChange={handleSelectAllClick} > Select All @@ -128,7 +113,7 @@ export const CustomDropdownSelection: React.FC< hideScrollBar className="flex max-h-96 max-w-56 flex-col gap-y-2 py-2" > - {memoizedValues.map(({ id, name }) => ( + {values.map(({ id, name }) => (