diff --git a/src/components/UserSettings.tsx b/src/components/UserSettings.tsx index 12dbc4d3b..9f3e33725 100644 --- a/src/components/UserSettings.tsx +++ b/src/components/UserSettings.tsx @@ -56,6 +56,7 @@ import ResetPassword from "./modals/ResetPassword"; import IssueNewCertificate from "./modals/IssueNewCertificate"; import AddOtpToken from "./modals/AddOtpToken"; import ActivateStageUsers from "./modals/ActivateStageUsers"; +import RestorePreservedUsers from "./modals/RestorePreservedUsers"; // Utils import { API_VERSION_BACKUP } from "src/utils/utils"; // Navigate @@ -246,6 +247,12 @@ const UserSettings = (props: PropsToUserSettings) => { setIsActivateModalOpen(false); }; + // Preserved users - 'Restore' option + const [isRestoreModalOpen, setIsRestoreModalOpen] = React.useState(false); + const onCloseRestoreModal = () => { + setIsRestoreModalOpen(false); + }; + // Kebab const [isKebabOpen, setIsKebabOpen] = useState(false); @@ -318,7 +325,9 @@ const UserSettings = (props: PropsToUserSettings) => { const preservedDropdownItems = [ Stage, - Restore, + setIsRestoreModalOpen(true)}> + Restore + , setIsDeleteModalOpen(true)}> Delete , @@ -624,6 +633,13 @@ const UserSettings = (props: PropsToUserSettings) => { selectedUids={selectedUsers} onSuccess={() => navigate(URL_PREFIX + "/stage-users")} /> + navigate(URL_PREFIX + "/preserved-users")} + /> ); }; diff --git a/src/components/modals/RestorePreservedUsers.tsx b/src/components/modals/RestorePreservedUsers.tsx index c70349bc1..df03b57cd 100644 --- a/src/components/modals/RestorePreservedUsers.tsx +++ b/src/components/modals/RestorePreservedUsers.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React from "react"; // PatternFly import { Button, @@ -14,30 +14,16 @@ import UsersDisplayTable from "src/components/tables/UsersDisplayTable"; import { useAppDispatch } from "src/store/hooks"; import { removeUser as removePreservedUser } from "src/store/Identity/preservedUsers-slice"; // RPC -import { - Command, - BatchRPCResponse, - useBatchMutCommandMutation, -} from "src/services/rpc"; -import { FetchBaseQueryError } from "@reduxjs/toolkit/dist/query"; -import { SerializedError } from "@reduxjs/toolkit"; -// Modals -import ErrorModal from "./ErrorModal"; -// Data types -import { ErrorData } from "src/utils/datatypes/globalDataTypes"; +import { BatchRPCResponse, useRestoreUserMutation } from "src/services/rpc"; // Hooks import useAlerts from "src/hooks/useAlerts"; -interface SelectedUsersData { - selectedUsers: string[]; - updateSelectedUsers: (newSelectedUsers: string[]) => void; -} - export interface PropsToPreservedUsers { show: boolean; handleModalToggle: () => void; - selectedUsersData: SelectedUsersData; - onRefresh?: () => void; + selectedUids: string[]; + updateSelectedUids: (newSelectedUids: string[]) => void; + onSuccess: () => void; } const RestorePreservedUsers = (props: PropsToPreservedUsers) => { @@ -48,7 +34,7 @@ const RestorePreservedUsers = (props: PropsToPreservedUsers) => { const alerts = useAlerts(); // Define 'executeUserRestoreCommand' to restore a preserved user - const [executeUserRestoreCommand] = useBatchMutCommandMutation(); + const [executeUserRestoreCommand] = useRestoreUserMutation(); // List of fields const fields = [ @@ -66,7 +52,7 @@ const RestorePreservedUsers = (props: PropsToPreservedUsers) => { id: "restore-users-table", pfComponent: ( ), @@ -78,110 +64,48 @@ const RestorePreservedUsers = (props: PropsToPreservedUsers) => { props.handleModalToggle(); }; - // Handle API error data - const [isModalErrorOpen, setIsModalErrorOpen] = useState(false); - const [errorTitle, setErrorTitle] = useState(""); - const [errorMessage, setErrorMessage] = useState(""); - - const closeAndCleanErrorParameters = () => { - setIsModalErrorOpen(false); - setErrorTitle(""); - setErrorMessage(""); - }; - - const onCloseErrorModal = () => { - closeAndCleanErrorParameters(); - }; - - const errorModalActions = [ - , - ]; - - const handleAPIError = (error: FetchBaseQueryError | SerializedError) => { - if ("code" in error) { - setErrorTitle("IPA error " + error.code + ": " + error.name); - if (error.message !== undefined) { - setErrorMessage(error.message); - } - } else if ("data" in error) { - const errorData = error.data as ErrorData; - const errorCode = errorData.code as string; - const errorName = errorData.name as string; - const errorMessage = errorData.error as string; - - setErrorTitle("IPA error " + errorCode + ": " + errorName); - setErrorMessage(errorMessage); - } - setIsModalErrorOpen(true); - }; - const [spinning, setBtnSpinning] = React.useState(false); // Restore preserved user const restoreUsers = () => { - // Prepare user params - const uidsToRestorePayload: Command[] = []; - setBtnSpinning(true); - props.selectedUsersData.selectedUsers.map((uid) => { - const payloadItem = { - method: "user_undel", - params: [uid, {}], - } as Command; - uidsToRestorePayload.push(payloadItem); - }); + // Prepare users params + const uidsToRestorePayload = props.selectedUids; // [API call] Restore elements executeUserRestoreCommand(uidsToRestorePayload).then((response) => { if ("data" in response) { const data = response.data as BatchRPCResponse; const result = data.result; - const error = data.error as FetchBaseQueryError | SerializedError; + const error = data.error; if (result) { - if ("error" in result.results[0] && result.results[0].error) { - const errorData = { - code: result.results[0].error_code, - name: result.results[0].error_name, - error: result.results[0].error, - } as ErrorData; - - const error = { - status: "CUSTOM_ERROR", - data: errorData, - } as FetchBaseQueryError; - - // Handle error - handleAPIError(error); - } else { - // Update data from Redux - props.selectedUsersData.selectedUsers.map((user) => { - dispatch(removePreservedUser(user[0])); - }); - - // Reset selected values - props.selectedUsersData.updateSelectedUsers([]); - - // Refresh data - if (props.onRefresh !== undefined) { - props.onRefresh(); - } - - // Show alert: success - alerts.addAlert( - "restore-users-success", - "Users restored", - "success" - ); - - closeModal(); + // Close modal + closeModal(); + + // Update data from Redux + props.selectedUids.map((user) => { + dispatch(removePreservedUser(user[0])); + }); + + // Reset selected values + props.updateSelectedUids([]); + + // Show alert: success + let successMessage = ""; + if (result.count > 1) { + successMessage = result.count + " users restored"; + } else if (result.count === 1) { + successMessage = result.results[0].summary; } + alerts.addAlert("restore-users-success", successMessage, "success"); + + // Refresh data or navigate + props.onSuccess(); } else if (error) { // Handle error - handleAPIError(error); + alerts.addAlert("restore-users-error", error, "danger"); } } setBtnSpinning(false); @@ -207,33 +131,20 @@ const RestorePreservedUsers = (props: PropsToPreservedUsers) => { , ]; - const modalRestore: JSX.Element = ( - - ); - return ( <> - {modalRestore} - {isModalErrorOpen && ( - - )} + ); }; diff --git a/src/components/modals/StagePreservedUsers.tsx b/src/components/modals/StagePreservedUsers.tsx index efd0fb7ee..ff200da3d 100644 --- a/src/components/modals/StagePreservedUsers.tsx +++ b/src/components/modals/StagePreservedUsers.tsx @@ -27,9 +27,24 @@ import ErrorModal from "./ErrorModal"; import { ErrorData } from "src/utils/datatypes/globalDataTypes"; // Hooks import useAlerts from "src/hooks/useAlerts"; -import { PropsToPreservedUsers } from "./RestorePreservedUsers"; - -const StagePreservedUsers = (props: PropsToPreservedUsers) => { +// Navigation +import { NavigateFunction } from "react-router-dom"; + +interface SelectedUsersData { + selectedUsers: string[]; + updateSelectedUsers: (newSelectedUsers: string[]) => void; +} + +interface PropsToStagePreservedUsers { + show: boolean; + handleModalToggle: () => void; + selectedUsersData: SelectedUsersData; + onRefresh?: () => void; + navigateFunc?: NavigateFunction; + navigateTo?: string; +} + +const StagePreservedUsers = (props: PropsToStagePreservedUsers) => { // Set dispatch (Redux) const dispatch = useAppDispatch(); diff --git a/src/pages/PreservedUsers/PreservedUsers.tsx b/src/pages/PreservedUsers/PreservedUsers.tsx index a5ac3367c..9505372f9 100644 --- a/src/pages/PreservedUsers/PreservedUsers.tsx +++ b/src/pages/PreservedUsers/PreservedUsers.tsx @@ -496,8 +496,9 @@ const PreservedUsers = () => { uid[0])} + updateSelectedUids={updateSelectedUsers} + onSuccess={refreshUsersData} /> ({ + query: (query_args) => { + const batchPayload: Command[] = []; + query_args.map((uid) => { + batchPayload.push({ + method: "user_undel", + params: [[uid], {}], + }); + }); + return getBatchCommand( batchPayload, query_args["version"] || API_VERSION_BACKUP @@ -859,4 +875,5 @@ export const { useAddOtpTokenMutation, useGenerateSubIdsMutation, useActivateUserMutation, + useRestoreUserMutation, } = api;