From 889f8078d2dfe936153c96c298eacd5e9f838acb Mon Sep 17 00:00:00 2001 From: Christie Molloy Date: Tue, 27 Oct 2020 19:45:35 -0400 Subject: [PATCH] add multiple group delete functionality (#185) * add multiple group delete functionality * fix the deleting bug and deleting during filering * fix stans comment * format files * fix lint * fix lint * fix messages * fix modal * fix error mark found --- src/groups/GroupsCreateModal.tsx | 2 +- src/groups/GroupsList.tsx | 27 ++++++++++++- src/groups/GroupsSection.tsx | 69 +++++++++++++++++++++++++------- src/groups/messages.json | 9 +++-- 4 files changed, 85 insertions(+), 22 deletions(-) diff --git a/src/groups/GroupsCreateModal.tsx b/src/groups/GroupsCreateModal.tsx index d89077d3e6..d78c806d05 100644 --- a/src/groups/GroupsCreateModal.tsx +++ b/src/groups/GroupsCreateModal.tsx @@ -48,9 +48,9 @@ export const GroupsCreateModal = ({ await httpClient.doPost(`/admin/realms/${realm}/groups`, { name: createGroupName, }); + refresh(); setIsCreateModalOpen(false); setCreateGroupName(""); - refresh(); addAlert(t("groupCreated"), AlertVariant.success); } catch (error) { addAlert( diff --git a/src/groups/GroupsList.tsx b/src/groups/GroupsList.tsx index 9b1b6a19e1..9194d8b4f8 100644 --- a/src/groups/GroupsList.tsx +++ b/src/groups/GroupsList.tsx @@ -16,6 +16,8 @@ import { useAlerts } from "../components/alert/Alerts"; export type GroupsListProps = { list?: GroupRepresentation[]; refresh: () => void; + tableRowSelectedArray: number[]; + setTableRowSelectedArray: (tableRowSelectedArray: number[]) => void; }; type FormattedData = { @@ -23,7 +25,12 @@ type FormattedData = { selected: boolean; }; -export const GroupsList = ({ list, refresh }: GroupsListProps) => { +export const GroupsList = ({ + list, + refresh, + tableRowSelectedArray, + setTableRowSelectedArray, +}: GroupsListProps) => { const { t } = useTranslation("groups"); const httpClient = useContext(HttpClientContext)!; const columnGroupName: keyof GroupRepresentation = "name"; @@ -67,7 +74,22 @@ export const GroupsList = ({ list, refresh }: GroupsListProps) => { }); } else { localRow = [...formattedData]; - localRow[rowId].selected = isSelected; + const localTableRow = [...tableRowSelectedArray]; + if (localRow[rowId].selected !== isSelected) { + localRow[rowId].selected = isSelected; + } + + if (localTableRow.includes(rowId)) { + const index = localTableRow.indexOf(rowId); + if (index === 0) { + localTableRow.shift(); + } else { + localTableRow.splice(index, 1); + } + setTableRowSelectedArray(localTableRow); + } else { + setTableRowSelectedArray([rowId, ...tableRowSelectedArray]); + } setFormattedData(localRow); } } @@ -89,6 +111,7 @@ export const GroupsList = ({ list, refresh }: GroupsListProps) => { `/admin/realms/${realm}/groups/${list![rowId].id}` ); refresh(); + setTableRowSelectedArray([]); addAlert(t("Group deleted"), AlertVariant.success); } catch (error) { addAlert(`${t("clientDeleteError")} ${error}`, AlertVariant.danger); diff --git a/src/groups/GroupsSection.tsx b/src/groups/GroupsSection.tsx index 6b438930dd..e78153cbfa 100644 --- a/src/groups/GroupsSection.tsx +++ b/src/groups/GroupsSection.tsx @@ -11,6 +11,8 @@ import { import { TableToolbar } from "../components/table-toolbar/TableToolbar"; import { ViewHeader } from "../components/view-header/ViewHeader"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; +import { RealmContext } from "../context/realm-context/RealmContext"; +import { useAlerts } from "../components/alert/Alerts"; import { Button, Dropdown, @@ -20,6 +22,7 @@ import { PageSectionVariants, Spinner, ToolbarItem, + AlertVariant, } from "@patternfly/react-core"; import "./GroupsSection.css"; @@ -27,24 +30,28 @@ export const GroupsSection = () => { const { t } = useTranslation("groups"); const httpClient = useContext(HttpClientContext)!; const [rawData, setRawData] = useState<{ [key: string]: any }[]>(); - const [filteredData, setFilteredData] = useState(); + const [filteredData, setFilteredData] = useState<{ [key: string]: any }[]>(); const [isKebabOpen, setIsKebabOpen] = useState(false); const [createGroupName, setCreateGroupName] = useState(""); const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); + const [tableRowSelectedArray, setTableRowSelectedArray] = useState< + Array + >([]); const columnID: keyof GroupRepresentation = "id"; const membersLength: keyof GroupRepresentation = "membersLength"; const columnGroupName: keyof GroupRepresentation = "name"; + const { addAlert } = useAlerts(); + const { realm } = useContext(RealmContext); const loader = async () => { const groups = await httpClient.doGet( - "/admin/realms/master/groups" + `/admin/realms/${realm}/groups` ); const groupsData = groups.data!; - const getMembers = async (id: number) => { const response = await httpClient.doGet< ServerGroupMembersRepresentation[] - >(`/admin/realms/master/groups/${id}/members`); + >(`/admin/realms/${realm}/groups/${id}/members`); const responseData = response.data!; return responseData.length; }; @@ -60,7 +67,7 @@ export const GroupsSection = () => { return object; } ); - + setFilteredData(updatedObject); setRawData(updatedObject); }; @@ -90,6 +97,31 @@ export const GroupsSection = () => { setIsCreateModalOpen(!isCreateModalOpen); }; + const multiDelete = async () => { + if (tableRowSelectedArray.length !== 0) { + const deleteGroup = async (rowId: number) => { + try { + await httpClient.doDelete( + `/admin/realms/${realm}/groups/${ + filteredData ? filteredData![rowId].id : rawData![rowId].id + }` + ); + loader(); + } catch (error) { + addAlert(`${t("groupDeleteError")} ${error}`, AlertVariant.danger); + } + }; + + const chainedPromises = tableRowSelectedArray.map((rowId: number) => { + deleteGroup(rowId); + }); + + await Promise.all(chainedPromises) + .then(() => addAlert(t("groupsDeleted"), AlertVariant.success)) + .then(() => setTableRowSelectedArray([])); + } + }; + return ( <> @@ -122,8 +154,12 @@ export const GroupsSection = () => { isOpen={isKebabOpen} isPlain dropdownItems={[ - - {t("delete")} + multiDelete()} + > + {t("common:Delete")} , ]} /> @@ -135,6 +171,8 @@ export const GroupsSection = () => { )} {filteredData && filteredData.length === 0 && ( @@ -146,14 +184,6 @@ export const GroupsSection = () => { /> )} - ) : ( { message={t("noGroupsInThisRealm")} instructions={t("noGroupsInThisRealmInstructions")} primaryActionText={t("createGroup")} + onPrimaryAction={() => handleModalToggle()} /> )} + ); diff --git a/src/groups/messages.json b/src/groups/messages.json index aebc6ed485..5649f86524 100644 --- a/src/groups/messages.json +++ b/src/groups/messages.json @@ -8,7 +8,6 @@ "search": "Search", "members": "Members", "moveTo": "Move to", - "delete": "Delete", "tableOfGroups": "Table of groups", "name": "Name", "groupsDescription": "Description goes here", @@ -17,8 +16,10 @@ "createAGroup": "Create a group", "create": "Create", "noSearchResults": "No search results", - "noSearchResultsInstructions" : "Click on the search bar above to search for groups", - "noGroupsInThisRealm" : "No groups in this Realm", - "noGroupsInThisRealmInstructions" : "You haven't created any groups in this realm. Create a group to get started." + "noSearchResultsInstructions": "Click on the search bar above to search for groups", + "noGroupsInThisRealm": "No groups in this realm", + "noGroupsInThisRealmInstructions": "You haven't created any groups in this realm. Create a group to get started.", + "groupsDeleted": "Groups deleted", + "groupDeleteError": "Error deleting group" } }