diff --git a/src/components/users/partials/wizard/EditUserGeneralTab.tsx b/src/components/users/partials/wizard/EditUserGeneralTab.tsx index 10161aeb3e..180ae05b2f 100644 --- a/src/components/users/partials/wizard/EditUserGeneralTab.tsx +++ b/src/components/users/partials/wizard/EditUserGeneralTab.tsx @@ -4,6 +4,7 @@ import { Field } from "../../../shared/Field"; import { FormikProps } from "formik"; import { NotificationComponent } from "../../../shared/Notifications"; import ModalContent from "../../../shared/modals/ModalContent"; +import { PasswordStrengthIndicator } from "./NewUserGeneralTab"; /** * This component renders the general user information tab in the users details modal. @@ -105,6 +106,9 @@ const EditUserGeneralTab = ({ } /> + ); diff --git a/src/components/users/partials/wizard/NewUserGeneralTab.tsx b/src/components/users/partials/wizard/NewUserGeneralTab.tsx index 6d981a137d..d97fc42f8e 100644 --- a/src/components/users/partials/wizard/NewUserGeneralTab.tsx +++ b/src/components/users/partials/wizard/NewUserGeneralTab.tsx @@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next"; import cn from "classnames"; import ModalContent from "../../../shared/modals/ModalContent"; import { ParseKeys } from "i18next"; +import WizardNavigationButtons from "../../../shared/wizard/WizardNavigationButtons"; /** * This component renders the general user information tab for new users in the new users wizard. @@ -19,100 +20,112 @@ interface RequiredFormProps { const NewUserGeneralTab = ({ formik, + nextPage, }: { formik: FormikProps + nextPage: (values: T) => void, }) => { const { t } = useTranslation(); return ( - -
- - {/* Fields for user information needed */} -
- - + +
+ + {/* Fields for user information needed */} +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
-
- - -
-
- - -
-
- - -
-
- - -
- -
- + + + {/* Navigation buttons */} + + ); }; -const PasswordStrengthIndicator = ({ +export const PasswordStrengthIndicator = ({ password, }: { password: string diff --git a/src/components/users/partials/wizard/NewUserSummaryPage.tsx b/src/components/users/partials/wizard/NewUserSummaryPage.tsx new file mode 100644 index 0000000000..900217c94d --- /dev/null +++ b/src/components/users/partials/wizard/NewUserSummaryPage.tsx @@ -0,0 +1,62 @@ +import WizardNavigationButtons from "../../../shared/wizard/WizardNavigationButtons"; +import { useTranslation } from "react-i18next"; +import Notifications from "../../../shared/Notifications"; +import { FormikProps } from "formik"; +import { initialFormValuesNewUser } from "../../../../configs/modalConfig"; +import ModalContentTable from "../../../shared/modals/ModalContentTable"; + +/** + * This component renders the summary page for new groups in the new group wizard. + */ +const NewUserSummaryPage = ({ + formik, + previousPage, +}: { + formik: FormikProps, + previousPage?: (values: T) => void, +}) => { + const { t } = useTranslation(); + + // get values of objects in field that should be shown + const getValues = (fields: { name: string }[]) => { + const names = []; + for (const field of fields) { + names.push(field.name); + } + return names; + }; + + return ( + <> + + + +
+
{t("USERS.USERS.DETAILS.TABS.SUMMARY")}
+
+ + + + + + + + + + + +
{t("USERS.USERS.DETAILS.TABS.USER")}{formik.values.name}
{t("USERS.USERS.DETAILS.TABS.ROLES")}{getValues(formik.values.roles).join(", ")}
+
+
+
+ {/* Button for navigation to next page */} + + + ); +}; + +export default NewUserSummaryPage; diff --git a/src/components/users/partials/wizard/NewUserWizard.tsx b/src/components/users/partials/wizard/NewUserWizard.tsx index 6e9f458c81..6fec5e8908 100644 --- a/src/components/users/partials/wizard/NewUserWizard.tsx +++ b/src/components/users/partials/wizard/NewUserWizard.tsx @@ -1,7 +1,4 @@ -import { useState } from "react"; import { Formik } from "formik"; -import { useTranslation } from "react-i18next"; -import cn from "classnames"; import NewUserGeneralTab from "./NewUserGeneralTab"; import UserRolesTab from "./UserRolesTab"; import { initialFormValuesNewUser } from "../../../../configs/modalConfig"; @@ -9,9 +6,10 @@ import { getUsernames } from "../../../../selectors/userSelectors"; import { NewUserSchema } from "../../../../utils/validate"; import { NewUser, postNewUser, UserRole } from "../../../../slices/userSlice"; import { useAppDispatch, useAppSelector } from "../../../../store"; -import ButtonLikeAnchor from "../../../shared/ButtonLikeAnchor"; -import WizardNavigationButtons from "../../../shared/wizard/WizardNavigationButtons"; import { Role } from "../../../../slices/aclSlice"; +import WizardStepper, { WizardStep } from "../../../shared/wizard/WizardStepper"; +import { usePageFunctions } from "../../../../hooks/wizardHooks"; +import NewUserSummaryPage from "./NewUserSummaryPage"; /** * This component renders the new user wizard @@ -21,16 +19,39 @@ const NewUserWizard = ({ }: { close: () => void, }) => { - const { t } = useTranslation(); const dispatch = useAppDispatch(); const usernames = useAppSelector(state => getUsernames(state)); - const [tab, setTab] = useState(0); + const { + page, + nextPage, + previousPage, + setPage, + pageCompleted, + setPageCompleted, + } = usePageFunctions(0); - const openTab = (tabNr: number) => { - setTab(tabNr); - }; + type StepName = "metadata" | "roles" | "summary"; + type Step = WizardStep & { + name: StepName, + } + + // Caption of steps used by Stepper + const steps: Step[] = [ + { + translation: "USERS.USERS.DETAILS.TABS.USER", + name: "metadata", + }, + { + translation: "USERS.USERS.DETAILS.TABS.ROLES", + name: "roles", + }, + { + translation: "USERS.USERS.DETAILS.TABS.SUMMARY", + name: "summary", + }, + ]; const handleSubmit = (values: { username: string, @@ -54,23 +75,6 @@ const NewUserWizard = ({ return ( <> - {/* Head navigation*/} - - {/* Initialize overall form */} { return ( <> - {tab === 0 && } - {tab === 1 && } - - {/* Navigation buttons and validation */} - formik.handleSubmit()} - previousPage={() => close()} - cancelTranslationString={"CANCEL"} + + {steps[page].name === "metadata" && + + } + {steps[page].name === "roles" && + + } + {steps[page].name === "summary" && + + } ); }} diff --git a/src/components/users/partials/wizard/UserRolesTab.tsx b/src/components/users/partials/wizard/UserRolesTab.tsx index f3a7701683..431f972b26 100644 --- a/src/components/users/partials/wizard/UserRolesTab.tsx +++ b/src/components/users/partials/wizard/UserRolesTab.tsx @@ -4,6 +4,7 @@ import SelectContainer from "../../../shared/wizard/SelectContainer"; import { FormikProps } from "formik"; import { NotificationComponent } from "../../../shared/Notifications"; import ModalContent from "../../../shared/modals/ModalContent"; +import WizardNavigationButtons from "../../../shared/wizard/WizardNavigationButtons"; /** * This component renders the role selection tab of the new user wizard and the user details modal @@ -14,8 +15,12 @@ interface RequiredFormProps { const UserRolesTab = ({ formik, + nextPage, + previousPage, }: { formik: FormikProps + nextPage?: (values: T) => void, // For create modal + previousPage?: (values: T) => void, // For create modal }) => { // roles that can be chosen by user const [roles, setRoles] = useState([]); @@ -35,31 +40,41 @@ const UserRolesTab = ({ }, []); return ( - - {!formik.values.manageable && ( - - )} -
- {/* Select container for roles*/} - {!loading && ( - + + {!formik.values.manageable && ( + )} -
-
+
+ {/* Select container for roles*/} + {!loading && ( + + )} +
+ + + {previousPage && nextPage && + + } + ); }; diff --git a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json index b9183c0152..200b3c6d1a 100644 --- a/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json +++ b/src/i18n/org/opencastproject/adminui/languages/lang-en_US.json @@ -1381,7 +1381,8 @@ "USER": "User", "ROLES": "Roles", "EXTERNALROLES": "External Roles", - "EFFECTIVEROLES": "Effective Roles" + "EFFECTIVEROLES": "Effective Roles", + "SUMMARY": "Summary" }, "DESCRIPTION": { "ROLES": "Roles and groups that can be or are already assigned to the user.",