Continued with the entities for the batch users
This commit is contained in:
@@ -17,6 +17,8 @@ import ReactDatePicker from "react-datepicker";
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import usePermissions from "@/hooks/usePermissions";
|
import usePermissions from "@/hooks/usePermissions";
|
||||||
import countryCodes from "country-codes-list";
|
import countryCodes from "country-codes-list";
|
||||||
|
import { EntityWithRoles } from "@/interfaces/entity";
|
||||||
|
import Select from "@/components/Low/Select";
|
||||||
|
|
||||||
const EMAIL_REGEX = new RegExp(/^[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*$/);
|
const EMAIL_REGEX = new RegExp(/^[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*@[a-zA-Z0-9]+(?:\.[a-zA-Z0-9]+)*$/);
|
||||||
|
|
||||||
@@ -65,10 +67,11 @@ interface Props {
|
|||||||
user: User;
|
user: User;
|
||||||
users: User[];
|
users: User[];
|
||||||
permissions: PermissionType[];
|
permissions: PermissionType[];
|
||||||
|
entities: EntityWithRoles[]
|
||||||
onFinish: () => void;
|
onFinish: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function BatchCreateUser({user, users, permissions, onFinish}: Props) {
|
export default function BatchCreateUser({user, users, entities = [], permissions, onFinish}: Props) {
|
||||||
const [infos, setInfos] = useState<
|
const [infos, setInfos] = useState<
|
||||||
{
|
{
|
||||||
email: string;
|
email: string;
|
||||||
@@ -89,6 +92,7 @@ export default function BatchCreateUser({user, users, permissions, onFinish}: Pr
|
|||||||
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 {openFilePicker, filesContent, clear} = useFilePicker({
|
const {openFilePicker, filesContent, clear} = useFilePicker({
|
||||||
accept: ".xlsx",
|
accept: ".xlsx",
|
||||||
@@ -122,6 +126,7 @@ export default function BatchCreateUser({user, users, permissions, onFinish}: Pr
|
|||||||
groupName: group,
|
groupName: group,
|
||||||
corporate,
|
corporate,
|
||||||
studentID,
|
studentID,
|
||||||
|
entity,
|
||||||
demographicInformation: {
|
demographicInformation: {
|
||||||
country: countryItem?.countryCode,
|
country: countryItem?.countryCode,
|
||||||
passport_id: passport_id?.toString().trim() || undefined,
|
passport_id: passport_id?.toString().trim() || undefined,
|
||||||
@@ -206,15 +211,28 @@ export default function BatchCreateUser({user, users, permissions, onFinish}: Pr
|
|||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
<div className="border-mti-gray-platinum flex flex-col gap-4 rounded-xl border p-4">
|
<div className="border-mti-gray-platinum flex flex-col gap-4 rounded-xl border p-4">
|
||||||
<div className="flex items-end justify-between">
|
<div className="grid grid-cols-2 -md:grid-cols-1 gap-4">
|
||||||
<label className="text-mti-gray-dim text-base font-normal">Choose an Excel file</label>
|
<div className="flex flex-col gap-4">
|
||||||
<div className="tooltip cursor-pointer" data-tip="Excel File Format" onClick={() => setShowHelp(true)}>
|
<div className="flex items-end justify-between">
|
||||||
<BsQuestionCircleFill />
|
<label className="text-mti-gray-dim text-base font-normal">Choose an Excel file</label>
|
||||||
|
<div className="tooltip cursor-pointer" data-tip="Excel File Format" onClick={() => setShowHelp(true)}>
|
||||||
|
<BsQuestionCircleFill />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button onClick={openFilePicker} isLoading={isLoading} disabled={isLoading}>
|
||||||
|
{filesContent.length > 0 ? filesContent[0].name : "Choose a file"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className={clsx("flex flex-col gap-4")}>
|
||||||
|
<label className="font-normal text-base text-mti-gray-dim">Entity</label>
|
||||||
|
<Select
|
||||||
|
defaultValue={{ value: (entities || [])[0]?.id, label: (entities || [])[0]?.label }}
|
||||||
|
options={entities.map((e) => ({ value: e.id, label: e.label }))}
|
||||||
|
onChange={(e) => setEntity(e?.value || undefined)}
|
||||||
|
isClearable={checkAccess(user, ["admin", "developer"])}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button onClick={openFilePicker} isLoading={isLoading} disabled={isLoading}>
|
|
||||||
{filesContent.length > 0 ? filesContent[0].name : "Choose a file"}
|
|
||||||
</Button>
|
|
||||||
{user && checkAccess(user, ["developer", "admin", "corporate", "mastercorporate"]) && (
|
{user && checkAccess(user, ["developer", "admin", "corporate", "mastercorporate"]) && (
|
||||||
<>
|
<>
|
||||||
<div className="-md:flex-row -md:items-center flex justify-between gap-2 md:flex-col 2xl:flex-row 2xl:items-center">
|
<div className="-md:flex-row -md:items-center flex justify-between gap-2 md:flex-col 2xl:flex-row 2xl:items-center">
|
||||||
@@ -260,7 +278,7 @@ export default function BatchCreateUser({user, users, permissions, onFinish}: Pr
|
|||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
)}
|
)}
|
||||||
<Button className="my-auto" onClick={makeUsers} disabled={infos.length === 0}>
|
<Button className="my-auto" onClick={makeUsers} disabled={infos.length === 0 || !entity}>
|
||||||
Create
|
Create
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import { FirebaseScrypt } from 'firebase-scrypt';
|
|||||||
import { firebaseAuthScryptParams } from "@/firebase";
|
import { firebaseAuthScryptParams } from "@/firebase";
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { getEntityWithRoles } from "@/utils/entities.be";
|
||||||
|
import { findBy } from "@/utils";
|
||||||
|
|
||||||
export default withIronSessionApiRoute(handler, sessionOptions);
|
export default withIronSessionApiRoute(handler, sessionOptions);
|
||||||
|
|
||||||
@@ -47,7 +49,10 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
const salt = crypto.randomBytes(16).toString('base64');
|
const salt = crypto.randomBytes(16).toString('base64');
|
||||||
const hash = await scrypt.hash(user.passport_id, salt);
|
const hash = await scrypt.hash(user.passport_id, salt);
|
||||||
|
|
||||||
currentUser.entities = [{ id: currentUser.entity!, role: "90ce8f08-08c8-41e4-9848-f1500ddc3930" }]
|
const entity = await getEntityWithRoles(currentUser.entity!)
|
||||||
|
const defaultRole = findBy(entity?.roles || [], "isDefault", true)
|
||||||
|
|
||||||
|
currentUser.entities = [{ id: entity?.id || "", role: defaultRole?.id || "" }]
|
||||||
delete currentUser.entity
|
delete currentUser.entity
|
||||||
|
|
||||||
currentUser.email = currentUser.email.toLowerCase();
|
currentUser.email = currentUser.email.toLowerCase();
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import { getGroup, getGroups, getUserCorporate, getUserGroups, getUserNamedGroup
|
|||||||
import { uniq } from "lodash";
|
import { uniq } from "lodash";
|
||||||
import { getSpecificUsers, getUser } from "@/utils/users.be";
|
import { getSpecificUsers, getUser } from "@/utils/users.be";
|
||||||
import client from "@/lib/mongodb";
|
import client from "@/lib/mongodb";
|
||||||
|
import { getEntityWithRoles } from "@/utils/entities.be";
|
||||||
|
import { findBy } from "@/utils";
|
||||||
|
|
||||||
const DEFAULT_DESIRED_LEVELS = {
|
const DEFAULT_DESIRED_LEVELS = {
|
||||||
reading: 9,
|
reading: 9,
|
||||||
@@ -65,6 +67,9 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
.then(async (userCredentials) => {
|
.then(async (userCredentials) => {
|
||||||
const userId = userCredentials.user.uid;
|
const userId = userCredentials.user.uid;
|
||||||
|
|
||||||
|
const entityWithRole = await getEntityWithRoles(entity)
|
||||||
|
const defaultRole = findBy(entityWithRole?.roles || [], "isDefault", true)
|
||||||
|
|
||||||
const user = {
|
const user = {
|
||||||
...req.body,
|
...req.body,
|
||||||
bio: "",
|
bio: "",
|
||||||
@@ -78,7 +83,7 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
isFirstLogin: false,
|
isFirstLogin: false,
|
||||||
isVerified: true,
|
isVerified: true,
|
||||||
registrationDate: new Date(),
|
registrationDate: new Date(),
|
||||||
entities: [{ id: entity, role: "90ce8f08-08c8-41e4-9848-f1500ddc3930" }],
|
entities: [{ id: entity, role: defaultRole?.id || "" }],
|
||||||
subscriptionExpirationDate: expiryDate || null,
|
subscriptionExpirationDate: expiryDate || null,
|
||||||
...((maker.type === "corporate" || maker.type === "mastercorporate") && type === "corporate"
|
...((maker.type === "corporate" || maker.type === "mastercorporate") && type === "corporate"
|
||||||
? {
|
? {
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ export default function Admin({ user, entities, permissions }: Props) {
|
|||||||
<ToastContainer />
|
<ToastContainer />
|
||||||
<Layout user={user} className="gap-6">
|
<Layout user={user} className="gap-6">
|
||||||
<Modal isOpen={modalOpen === "batchCreateUser"} onClose={() => setModalOpen(undefined)}>
|
<Modal isOpen={modalOpen === "batchCreateUser"} onClose={() => setModalOpen(undefined)}>
|
||||||
<BatchCreateUser user={user} users={users} permissions={permissions} onFinish={() => setModalOpen(undefined)} />
|
<BatchCreateUser user={user} entities={entities} users={users} permissions={permissions} onFinish={() => setModalOpen(undefined)} />
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal isOpen={modalOpen === "batchCreateCode"} onClose={() => setModalOpen(undefined)}>
|
<Modal isOpen={modalOpen === "batchCreateCode"} onClose={() => setModalOpen(undefined)}>
|
||||||
<BatchCodeGenerator user={user} users={users} permissions={permissions} onFinish={() => setModalOpen(undefined)} />
|
<BatchCodeGenerator user={user} users={users} permissions={permissions} onFinish={() => setModalOpen(undefined)} />
|
||||||
|
|||||||
Reference in New Issue
Block a user