From 80876a7a3dfe42cf18819d45ecbc693677702746 Mon Sep 17 00:00:00 2001 From: nshandra <34254522+nshandra@users.noreply.github.com> Date: Tue, 12 Nov 2024 12:08:17 +0100 Subject: [PATCH] refactor: refactor ReplicateUserFromTable.component.js to FC. Adapt ImportTable to the replicate function. --- .../components/import-export/ImportTable.tsx | 37 +++++- .../replicate/ReplicateUserFromTable.tsx | 115 ++++++++++++++++++ 2 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 src/webapp/components/replicate/ReplicateUserFromTable.tsx diff --git a/src/webapp/components/import-export/ImportTable.tsx b/src/webapp/components/import-export/ImportTable.tsx index 765ba3b..7bd8c9c 100644 --- a/src/webapp/components/import-export/ImportTable.tsx +++ b/src/webapp/components/import-export/ImportTable.tsx @@ -6,7 +6,6 @@ import React, { useState, useEffect, useCallback, SetStateAction, ComponentType import InfoDialog from "../../../legacy/components/InfoDialog"; import { generateUid } from "../../../utils/uid"; import i18n from "../../../locales"; -import UserLegacy from "../../../legacy/models/user"; import { ApiUser } from "../../../data/repositories/UserD2ApiRepository"; import { composeValidators, @@ -88,9 +87,10 @@ type ImportTableProps = { title: string; usersFromFile: User[]; columns: Columns[]; - onSave: (users: User[]) => void; + onSave?: (users: User[]) => void; + onSubmit?: (params: { users: User[] }) => void; onRequestClose: () => void; - templateUser?: UserLegacy; + templateUser?: User; actionText: string; warnings: string[]; }; @@ -105,6 +105,7 @@ export const ImportTable: React.FC = props => { templateUser = null, actionText, warnings = [], + onSubmit: customOnSubmit, } = props; const [users, setUsers] = useState(usersFromFile); const [existingUsers, setExistingUsers] = React.useState>({}); @@ -217,14 +218,16 @@ export const ImportTable: React.FC = props => { ); }; - const onSubmit = useCallback( + const defaultOnSubmit = useCallback( ({ users }: { users: User[] }) => { loading.show(true, i18n.t("Importing users")); return compositionRoot.users.import({ users }).run( () => { onRequestClose(); loading.hide(); - onSave([]); + if (onSave) { + onSave([]); + } snackbar.success(i18n.t("Users imported successfully")); }, error => { @@ -236,7 +239,9 @@ export const ImportTable: React.FC = props => { [loading, onRequestClose, onSave, snackbar, compositionRoot.users] ); - const addRow = useCallback((currentUsers: User[]) => { + const onSubmit = customOnSubmit || defaultOnSubmit; + + const defaultAddRow = useCallback((currentUsers: User[]) => { const newUser: User = { ...defaultUser, id: generateUid(), @@ -248,6 +253,26 @@ export const ImportTable: React.FC = props => { setUsers(currentUsers.concat(newUser)); }, []); + const replicateAddRow = useCallback( + (currentUsers: User[]) => { + if (templateUser) { + const existingNames = existingUsersNames.concat(currentUsers.map(user => user.username)); + const makeUsername = (i = 0) => `${templateUser.username}_${i}`; + const index = _.range(1, 1000).find(i => !existingNames.some(username => username === makeUsername(i))); + const newUser = { + ...templateUser, + username: makeUsername(index), + password: UserLogic.DEFAULT_PASSWORD, + id: generateUid(), + }; + setUsers(currentUsers.concat(newUser)); + } + }, + [existingUsersNames, templateUser] + ); + + const addRow = templateUser ? replicateAddRow : defaultAddRow; + const renderTableRow = useCallback( (user: User, rowIndex: number, users: User[]) => { const currentUsername = users[rowIndex]?.username || user.username; diff --git a/src/webapp/components/replicate/ReplicateUserFromTable.tsx b/src/webapp/components/replicate/ReplicateUserFromTable.tsx new file mode 100644 index 0000000..ffeddd6 --- /dev/null +++ b/src/webapp/components/replicate/ReplicateUserFromTable.tsx @@ -0,0 +1,115 @@ +import React, { useCallback, useEffect } from "react"; +import i18n from "../../../locales"; +import { Id } from "../../../domain/entities/Ref"; +import { useAppContext } from "../../contexts/app-context"; +import { ImportTable, Columns } from "../import-export/ImportTable"; +import { User, defaultUser } from "../../../domain/entities/User"; +import { useLoading, useSnackbar } from "@eyeseetea/d2-ui-components"; +import { generateUid } from "../../../utils/uid"; +import { D2Api } from "@eyeseetea/d2-api/2.36"; + +interface ReplicateUserFromTableProps { + userToReplicateId: Id; + onRequestClose: () => void; + settings: any; + api: D2Api; +} + +export const ReplicateUserFromTable: React.FC = props => { + const { compositionRoot } = useAppContext(); + const { userToReplicateId, onRequestClose } = props; + + const [userToReplicate, setUserToReplicate] = React.useState(defaultUser); + const [isMounted, setIsMounted] = React.useState(false); + + const loading = useLoading(); + const snackbar = useSnackbar(); + + useEffect(() => { + compositionRoot.users.get([userToReplicateId]).run( + ([user]) => { + if (!user) { + snackbar.error(i18n.t(`Unable to load user: ${userToReplicateId}`)); + onRequestClose(); + } else { + setUserToReplicate(user); + setIsMounted(true); + } + }, + error => { + snackbar.error(i18n.t(`Error loading user(${userToReplicateId}): ${error}`)); + onRequestClose(); + } + ); + }, [compositionRoot, loading, onRequestClose, snackbar, userToReplicateId]); + + const columns: Columns[] = [ + "username", + "password", + "firstName", + "surname", + "email", + "userRoles", + "userGroups", + "dataViewOrganisationUnits", + "organisationUnits", + ]; + + const replicateUsers = useCallback( + async ({ users }: { users: User[] }) => { + loading.show(true, i18n.t("Replicating users")); + + const newUsers: User[] = users.map(tableUser => { + return { + ...userToReplicate, + id: generateUid(), + username: tableUser.username, + password: tableUser.password, + firstName: tableUser.firstName, + surname: tableUser.surname, + email: tableUser.email, + userGroups: tableUser.userGroups, + userRoles: tableUser.userRoles, + dataViewOrganisationUnits: tableUser.dataViewOrganisationUnits, + organisationUnits: tableUser.organisationUnits, + externalAuth: false, + twoFA: false, + openId: "", + ldapId: "", + }; + }); + + return compositionRoot.users.import({ users: newUsers }).run( + () => { + loading.hide(); + onRequestClose(); + snackbar.success(i18n.t("Users replicated successfully")); + }, + error => { + loading.hide(); + snackbar.error(error); + } + ); + }, + [loading, compositionRoot.users, userToReplicate, onRequestClose, snackbar] + ); + + if (!isMounted) { + return null; + } + + return ( + + ); +}; + +export default ReplicateUserFromTable;