Skip to content

Commit

Permalink
Add 'Delete' option
Browse files Browse the repository at this point in the history
The 'Delete' option allows
to remove a given user from
its 'Settings' page. The
solution has been adapted to
the three user pages (Active,
Stage, and Preserved).

Signed-off-by: Carla Martinez <[email protected]>
  • Loading branch information
carma12 committed Dec 18, 2023
1 parent d89de04 commit d6f59a1
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 63 deletions.
44 changes: 41 additions & 3 deletions src/components/UserSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {
import useAlerts from "src/hooks/useAlerts";
// Modals
import DisableEnableUsers from "./modals/DisableEnableUsers";
import DeleteUsers from "./modals/DeleteUsers";

export interface PropsToUserSettings {
originalUser: Partial<User>;
Expand Down Expand Up @@ -115,10 +116,16 @@ const UserSettings = (props: PropsToUserSettings) => {
setIsDisableEnableModalOpen(false);
};

// 'Delete' modal
const [isDeleteModalOpen, setIsDeleteModalOpen] = React.useState(false);
const onCloseDeleteModal = () => {
setIsDeleteModalOpen(false);
};

// Kebab
const [isKebabOpen, setIsKebabOpen] = useState(false);

const dropdownItems = [
const activeDropdownItems = [
<DropdownItem key="reset password">Reset password</DropdownItem>,
<DropdownItem
key="enable"
Expand All @@ -134,7 +141,9 @@ const UserSettings = (props: PropsToUserSettings) => {
>
Disable
</DropdownItem>,
<DropdownItem key="delete">Delete</DropdownItem>,
<DropdownItem key="delete" onClick={() => setIsDeleteModalOpen(true)}>
Delete
</DropdownItem>,
<DropdownItem key="unlock" isDisabled>
Unlock
</DropdownItem>,
Expand All @@ -145,6 +154,21 @@ const UserSettings = (props: PropsToUserSettings) => {
<DropdownItem key="new certificate">New certificate</DropdownItem>,
];

const stageDropdownItems = [
<DropdownItem key="activate">Activate</DropdownItem>,
<DropdownItem key="delete" onClick={() => setIsDeleteModalOpen(true)}>
Delete
</DropdownItem>,
];

const preservedDropdownItems = [
<DropdownItem key="stage">Stage</DropdownItem>,
<DropdownItem key="restore">Restore</DropdownItem>,
<DropdownItem key="delete" onClick={() => setIsDeleteModalOpen(true)}>
Delete
</DropdownItem>,
];

const onKebabToggle = (isOpen: boolean) => {
setIsKebabOpen(isOpen);
};
Expand Down Expand Up @@ -224,7 +248,13 @@ const UserSettings = (props: PropsToUserSettings) => {
idKebab="toggle-action-buttons"
isKebabOpen={isKebabOpen}
isPlain={true}
dropdownItems={dropdownItems}
dropdownItems={
props.from === "active-users"
? activeDropdownItems
: props.from === "stage-users"
? stageDropdownItems
: preservedDropdownItems
}
/>
),
},
Expand Down Expand Up @@ -395,6 +425,14 @@ const UserSettings = (props: PropsToUserSettings) => {
singleUser={true}
onRefresh={props.onRefresh}
/>
<DeleteUsers
show={isDeleteModalOpen}
from={props.from}
handleModalToggle={onCloseDeleteModal}
selectedUsersData={selectedUsersData}
fromSettings={true}
onRefresh={props.onRefresh}
/>
</>
);
};
Expand Down
50 changes: 25 additions & 25 deletions src/components/modals/DeleteUsers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ import ErrorModal from "./ErrorModal";
import { ErrorData } from "src/utils/datatypes/globalDataTypes";
// Hooks
import useAlerts from "src/hooks/useAlerts";
// Routing
import { useNavigate } from "react-router-dom";
import { URL_PREFIX } from "src/navigation/NavRoutes";

interface ButtonsData {
updateIsDeleteButtonDisabled?: (value: boolean) => void;
Expand All @@ -46,25 +49,20 @@ export interface PropsToDeleteUsers {
from: "active-users" | "stage-users" | "preserved-users";
handleModalToggle: () => void;
selectedUsersData: SelectedUsersData;
buttonsData: ButtonsData;
// NOTE: 'onRefresh' is handled as { (User) => void | undefined } as a temporal solution
// until the C.L. is adapted in 'stage-' and 'preserved users' (otherwise
// the operation will fail for those components)
onRefresh?: () => void;
// NOTE: 'onOpenAddModal' is handled as { () => void | undefined } as a temporal solution
// until the C.L. is adapted in 'stage-' and 'preserved users' (otherwise
// the operation will fail for those components)
buttonsData?: ButtonsData;
onRefresh: () => void;
onOpenDeleteModal?: () => void;
// NOTE: 'onCloseAddModal' is handled as { () => void | undefined } as a temporal solution
// until the C.L. is adapted in 'stage-' and 'preserved users' (otherwise
// the operation will fail for those components)
onCloseDeleteModal?: () => void;
fromSettings?: boolean | false;
}

const DeleteUsers = (props: PropsToDeleteUsers) => {
// Set dispatch (Redux)
const dispatch = useAppDispatch();

// Redirect
const navigate = useNavigate();

// Alerts
const alerts = useAlerts();

Expand Down Expand Up @@ -248,18 +246,18 @@ const DeleteUsers = (props: PropsToDeleteUsers) => {
props.selectedUsersData.updateSelectedUsers([]);

// Disable 'Delete' button
if (
props.from === "active-users" &&
props.buttonsData.updateIsDeleteButtonDisabled !== undefined
) {
props.buttonsData.updateIsDeleteButtonDisabled(true);
if (props.buttonsData !== undefined) {
if (
props.from === "active-users" &&
props.buttonsData.updateIsDeleteButtonDisabled !== undefined
) {
props.buttonsData.updateIsDeleteButtonDisabled(true);
}
props.buttonsData.updateIsDeletion(true);
}
props.buttonsData.updateIsDeletion(true);

// Refresh data
if (props.onRefresh !== undefined) {
props.onRefresh();
}
props.onRefresh();

// Show alert: success
if (isDeleteChecked) {
Expand All @@ -275,7 +273,9 @@ const DeleteUsers = (props: PropsToDeleteUsers) => {
"success"
);
}

// Redirect to main page
navigate(URL_PREFIX + "/active-users");
// Close modal
closeModal();
}
} else if (error) {
Expand All @@ -295,7 +295,7 @@ const DeleteUsers = (props: PropsToDeleteUsers) => {
onClick={() => {
deleteUsers(props.selectedUsersData.selectedUsers);
}}
form="active-users-remove-users-modal"
form="remove-users-modal"
spinnerAriaValueText="Deleting"
spinnerAriaLabel="Deleting"
isLoading={spinning}
Expand Down Expand Up @@ -325,7 +325,7 @@ const DeleteUsers = (props: PropsToDeleteUsers) => {
modalPosition="top"
offPosition="76px"
title={title}
formId="active-users-remove-users-modal"
formId="remove-users-modal"
fields={fields}
show={props.show}
onClose={closeModal}
Expand All @@ -341,7 +341,7 @@ const DeleteUsers = (props: PropsToDeleteUsers) => {
onClick={() => {
deleteUsers(props.selectedUsersData.selectedUsers);
}}
form="active-users-remove-users-modal"
form="remove-users-modal"
spinnerAriaValueText="Preserving"
spinnerAriaLabel="Preserving"
isLoading={spinning}
Expand All @@ -360,7 +360,7 @@ const DeleteUsers = (props: PropsToDeleteUsers) => {
modalPosition="top"
offPosition="76px"
title={title}
formId="active-users-remove-users-modal"
formId="remove-users-modal"
fields={fields}
show={props.show}
onClose={closeModal}
Expand Down
64 changes: 37 additions & 27 deletions src/components/tables/UsersDisplayTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,35 +33,45 @@ const UsersDisplayTable = (props: PropsToDisplayUsersTable) => {

// Given userIds, retrieve full user info to display into table
const usersToDisplay: User[] = [];
switch (props.from) {
case "active-users":
activeUsersListCopy.map((user) => {
props.usersToDisplay.map((selected) => {
if (user.uid[0] === selected[0]) {
usersToDisplay.push(user);
}
const [usersToDisplayList, setUsersToDisplayList] = React.useState<User[]>(
[]
);

// Given its `uids`, get full user info to display
React.useEffect(() => {
switch (props.from) {
case "active-users":
activeUsersListCopy.map((user) => {
props.usersToDisplay.map((selected) => {
if (user.uid[0] === selected[0] || user.uid[0] === selected) {
usersToDisplay.push(user);
}
});
});
});
break;
case "stage-users":
stageUsersListCopy.map((user) => {
props.usersToDisplay.map((selected) => {
if (user.uid === selected) {
usersToDisplay.push(user);
}
setUsersToDisplayList(usersToDisplay);
break;
case "stage-users":
stageUsersListCopy.map((user) => {
props.usersToDisplay.map((selected) => {
if (user.uid === selected || user.uid[0] === selected) {
usersToDisplay.push(user);
}
});
});
});
break;
case "preserved-users":
preservedUsersListCopy.map((user) => {
props.usersToDisplay.map((selected) => {
if (user.uid === selected) {
usersToDisplay.push(user);
}
setUsersToDisplayList(usersToDisplay);
break;
case "preserved-users":
preservedUsersListCopy.map((user) => {
props.usersToDisplay.map((selected) => {
if (user.uid === selected || user.uid[0] === selected) {
usersToDisplay.push(user);
}
});
});
});
break;
}
setUsersToDisplayList(usersToDisplay);
break;
}
}, [props.usersToDisplay]);

// Define column names
const columnNames = {
Expand All @@ -83,7 +93,7 @@ const UsersDisplayTable = (props: PropsToDisplayUsersTable) => {
</Tr>
);

const body = usersToDisplay.map((user) => (
const body = usersToDisplayList.map((user) => (
<Tr key={user.uid} id={user.uid}>
<Td dataLabel={columnNames.userLogin}>{user.uid}</Td>
<Td dataLabel={columnNames.firstName}>{user.givenname}</Td>
Expand Down
18 changes: 10 additions & 8 deletions src/utils/ipaObjectUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,16 @@ export function convertApiObj(
dateValues: Set<string>
) {
const obj = {};
for (const [key, value] of Object.entries(apiRecord)) {
if (simpleValues.has(key)) {
obj[key] = convertToString(value as BasicType);
} else if (dateValues.has(key)) {
// TODO convert to Datetime object
obj[key] = value;
} else {
obj[key] = value;
if (apiRecord !== undefined) {
for (const [key, value] of Object.entries(apiRecord)) {
if (simpleValues.has(key)) {
obj[key] = convertToString(value as BasicType);
} else if (dateValues.has(key)) {
// TODO convert to Datetime object
obj[key] = value;
} else {
obj[key] = value;
}
}
}
return obj;
Expand Down

0 comments on commit d6f59a1

Please sign in to comment.