ENCOA-289

This commit is contained in:
Carlos-Mesquita
2024-12-24 11:52:34 +00:00
parent 8d7b47312e
commit bac2a08748
3 changed files with 74 additions and 7 deletions

View File

@@ -199,7 +199,7 @@ const UserImportSummary: React.FC<Props> = ({ parsedExcel, newUsers, enlistedUse
</> </>
</Modal> </Modal>
<Modal isOpen={showEnlistedModal} onClose={() => setShowEnlistedModal(false)}> <Modal isOpen={showEnlistedModal} onClose={() => setShowEnlistedModal(false)} maxWidth='max-w-[85%]'>
<> <>
<div className="flex items-center gap-2 mb-6"> <div className="flex items-center gap-2 mb-6">
<FaUsers className="w-5 h-5 text-blue-500" /> <FaUsers className="w-5 h-5 text-blue-500" />

View File

@@ -87,7 +87,15 @@ export default function BatchCreateUser({ user, entities = [], permissions, onFi
const [isExpiryDateEnabled, setIsExpiryDateEnabled] = useState(true); const [isExpiryDateEnabled, setIsExpiryDateEnabled] = useState(true);
const [type, setType] = useState<Type>("student"); const [type, setType] = useState<Type>("student");
const [showHelp, setShowHelp] = useState(false); const [showHelp, setShowHelp] = useState(false);
const [entity, setEntity] = useState((entities || [])[0]?.id || undefined) const [entity, setEntity] = useState<{id: string | null, label: string | null}| undefined>(() => {
if (!entities?.length) {
return undefined;
}
return {
id: entities[0].id,
label: entities[0].label
};
});
const { openFilePicker, filesContent, clear } = useFilePicker({ const { openFilePicker, filesContent, clear } = useFilePicker({
accept: ".xlsx", accept: ".xlsx",
@@ -291,11 +299,28 @@ export default function BatchCreateUser({ user, entities = [], permissions, onFi
if (!!crossRefEmails) { if (!!crossRefEmails) {
const existingEmails = new Set(crossRefEmails.map((x: any) => x.email)); const existingEmails = new Set(crossRefEmails.map((x: any) => x.email));
const dupes = infos.filter(info => existingEmails.has(info.email)); const dupes = infos.filter(info => existingEmails.has(info.email));
const newUsersList = infos.filter(info => !existingEmails.has(info.email)); const newUsersList = infos
.filter(info => !existingEmails.has(info.email))
.map(info => ({
...info,
entityLabels: [entity!.label!]
}));
setNewUsers(newUsersList); setNewUsers(newUsersList);
setDuplicatedUsers(dupes);
const {data: emailEntityMap} = await axios.post("/api/users/controller?op=getEntities", {
emails: dupes.map((x) => x.email)
});
const withLabels = dupes.map((u) => ({
...u,
entityLabels: emailEntityMap.find((e: any) => e.email === u.email)?.entityLabels || []
}))
setDuplicatedUsers(withLabels);
} else { } else {
setNewUsers(infos); const withLabel = infos.map(info => ({
...info,
entityLabels: [entity!.label!]
}));
setNewUsers(withLabel);
} }
} catch (error) { } catch (error) {
toast.error("Something went wrong, please try again later!"); toast.error("Something went wrong, please try again later!");
@@ -305,7 +330,7 @@ export default function BatchCreateUser({ user, entities = [], permissions, onFi
if (infos.length > 0) { if (infos.length > 0) {
crossReferenceEmails(); crossReferenceEmails();
} }
}, [infos]); }, [infos, entity]);
const makeUsers = async () => { const makeUsers = async () => {
const newUsersSentence = newUsers.length > 0 ? `create ${newUsers.length} user(s)` : undefined; const newUsersSentence = newUsers.length > 0 ? `create ${newUsers.length} user(s)` : undefined;
@@ -459,7 +484,16 @@ export default function BatchCreateUser({ user, entities = [], permissions, onFi
<Select <Select
defaultValue={{ value: (entities || [])[0]?.id, label: (entities || [])[0]?.label }} defaultValue={{ value: (entities || [])[0]?.id, label: (entities || [])[0]?.label }}
options={entities.map((e) => ({ value: e.id, label: e.label }))} options={entities.map((e) => ({ value: e.id, label: e.label }))}
onChange={(e) => setEntity(e?.value || undefined)} onChange={(e) => {
if (!e) {
setEntity(undefined);
return;
}
setEntity({
id: e?.value,
label: e?.label
});
}}
isClearable={checkAccess(user, ["admin", "developer"])} isClearable={checkAccess(user, ["admin", "developer"])}
/> />
</div> </div>

View File

@@ -38,6 +38,9 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
await assignToEntity(req.body); await assignToEntity(req.body);
res.status(200).json({"ok": true}); res.status(200).json({"ok": true});
break; break;
case 'getEntities':
res.status(200).json(await getEntities(req.body.emails))
break;
default: default:
res.status(400).json({ error: 'Invalid operation!' }) res.status(400).json({ error: 'Invalid operation!' })
} }
@@ -276,6 +279,36 @@ async function getIds(emails: string[]): Promise<Array<{ email: string; id: stri
})); }));
} }
async function getEntities(emails: string[]): Promise<Array<{ email: string; entityLabels: string[] }>> {
const users = await db.collection('users')
.find({ email: { $in: emails } })
.project({ email: 1, entities: 1, _id: 0 })
.toArray();
const entityIds = [...new Set(
users.flatMap(user =>
(user.entities || []).map((entity: any) => entity.id)
)
)];
const entityRecords = await db.collection('entities')
.find({ id: { $in: entityIds } })
.project({ id: 1, label: 1, _id: 0 })
.toArray();
const entityMap = new Map(
entityRecords.map(entity => [entity.id, entity.label])
);
return users.map(user => ({
email: user.email,
entityLabels: (user.entities || [])
.map((entity: any) => entityMap.get(entity.id))
.filter((label: string): label is string => !!label)
}));
}
async function assignToEntity(body: any) { async function assignToEntity(body: any) {
const { ids, entity } = body; const { ids, entity } = body;