Merged develop into addedAccess-bugfixes
This commit is contained in:
@@ -2,7 +2,7 @@ import { ApprovalWorkflow } from "@/interfaces/approval.workflow";
|
||||
import axios from "axios";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
export default function useApprovalWorkflows() {
|
||||
export default function useApprovalWorkflows(entitiesString?: string) {
|
||||
const [workflows, setWorkflows] = useState<ApprovalWorkflow[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isError, setIsError] = useState(false);
|
||||
@@ -10,7 +10,7 @@ export default function useApprovalWorkflows() {
|
||||
const getData = useCallback(() => {
|
||||
setIsLoading(true);
|
||||
axios
|
||||
.get<ApprovalWorkflow[]>(`/api/approval-workflows`)
|
||||
.get<ApprovalWorkflow[]>(`/api/approval-workflows`, {params: { entityIds: entitiesString }})
|
||||
.then((response) => setWorkflows(response.data))
|
||||
.catch((error) => {
|
||||
setIsError(true);
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Module } from "@/interfaces";
|
||||
import { getApprovalWorkflowByFormIntaker, createApprovalWorkflow } from "@/utils/approval.workflows.be";
|
||||
import client from "@/lib/mongodb";
|
||||
|
||||
export async function createApprovalWorkflowsOnExamCreation(examAuthor: string, examEntities: string[], examId: string, examModule: string) {
|
||||
const db = client.db(process.env.MONGODB_DB);
|
||||
|
||||
/* export async function createApprovalWorkflowsOnExamCreation(examAuthor: string, examEntities: string[], examId: string, examModule: string) {
|
||||
const results = await Promise.all(
|
||||
examEntities.map(async (entity) => {
|
||||
const configuredWorkflow = await getApprovalWorkflowByFormIntaker(entity, examAuthor);
|
||||
@@ -27,6 +30,50 @@ export async function createApprovalWorkflowsOnExamCreation(examAuthor: string,
|
||||
const successCount = results.filter((r) => r.created).length;
|
||||
const totalCount = examEntities.length;
|
||||
|
||||
return {
|
||||
successCount,
|
||||
totalCount,
|
||||
};
|
||||
} */
|
||||
|
||||
// TEMPORARY BEHAVIOUR! ONLY THE FIRST CONFIGURED WORKFLOW FOUND IS STARTED
|
||||
export async function createApprovalWorkflowOnExamCreation(examAuthor: string, examEntities: string[], examId: string, examModule: string) {
|
||||
let successCount = 0;
|
||||
let totalCount = 0;
|
||||
|
||||
for (const entity of examEntities) {
|
||||
const configuredWorkflow = await getApprovalWorkflowByFormIntaker(entity, examAuthor);
|
||||
|
||||
if (!configuredWorkflow) {
|
||||
continue;
|
||||
}
|
||||
|
||||
totalCount = 1; // a workflow was found
|
||||
|
||||
configuredWorkflow.modules.push(examModule as Module);
|
||||
configuredWorkflow.name = examId;
|
||||
configuredWorkflow.examId = examId;
|
||||
configuredWorkflow.entityId = entity;
|
||||
configuredWorkflow.startDate = Date.now();
|
||||
|
||||
try {
|
||||
await createApprovalWorkflow("active-workflows", configuredWorkflow);
|
||||
successCount = 1;
|
||||
break; // Stop after the first success
|
||||
} catch (error: any) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
if (totalCount === 0) { // current behaviour: if no workflow was found skip approval process
|
||||
await db.collection(examModule).updateOne(
|
||||
{ id: examId },
|
||||
{ $set: { id: examId, isDiagnostic: false }},
|
||||
{ upsert: true }
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
successCount,
|
||||
totalCount,
|
||||
|
||||
@@ -19,5 +19,9 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
|
||||
return res.status(403).json({ ok: false });
|
||||
}
|
||||
|
||||
return res.status(200).json(await getApprovalWorkflows("active-workflows"));
|
||||
}
|
||||
const entityIdsString = req.query.entityIds as string;
|
||||
|
||||
const entityIdsArray = entityIdsString.split(",");
|
||||
|
||||
return res.status(200).json(await getApprovalWorkflows("active-workflows", entityIdsArray));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import { Module } from "@/interfaces";
|
||||
import { Exam, ExamBase, InstructorGender, Variant } from "@/interfaces/exam";
|
||||
import { createApprovalWorkflowsOnExamCreation } from "@/lib/createWorkflowsOnExamCreation";
|
||||
import { createApprovalWorkflowOnExamCreation } from "@/lib/createWorkflowsOnExamCreation";
|
||||
import client from "@/lib/mongodb";
|
||||
import { sessionOptions } from "@/lib/session";
|
||||
import { mapBy } from "@/utils";
|
||||
@@ -49,7 +49,7 @@ async function POST(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { module } = req.query as { module: string };
|
||||
|
||||
const session = client.startSession();
|
||||
const entities = isAdmin(user) ? [] : mapBy(user.entities, "id"); // might need to change this with new approval workflows logic.. if an admin creates an exam no workflow is started because workflows must have entities configured.
|
||||
const entities = isAdmin(user) ? [] : mapBy(user.entities, "id");
|
||||
|
||||
try {
|
||||
const exam = {
|
||||
@@ -78,6 +78,10 @@ async function POST(req: NextApiRequest, res: NextApiResponse) {
|
||||
throw new Error("Name already exists");
|
||||
}
|
||||
|
||||
if (isAdmin(user)) {
|
||||
exam.isDiagnostic = false;
|
||||
}
|
||||
|
||||
await db.collection(module).updateOne(
|
||||
{ id: req.body.id },
|
||||
{ $set: { id: req.body.id, ...exam } },
|
||||
@@ -90,37 +94,41 @@ async function POST(req: NextApiRequest, res: NextApiResponse) {
|
||||
// if it doesn't enter the next if condition it means the exam was updated and not created, so we can send this response.
|
||||
responseStatus = 200;
|
||||
responseMessage = `Successfully updated exam with ID: "${exam.id}"`;
|
||||
// TODO maybe find a way to start missing approval workflows in case they were only configured after exam creation.
|
||||
|
||||
// create workflow only if exam is being created for the first time
|
||||
if (docSnap === null) {
|
||||
try {
|
||||
const { successCount, totalCount } = await createApprovalWorkflowsOnExamCreation(exam.createdBy, exam.entities, exam.id, module);
|
||||
const { successCount, totalCount } = await createApprovalWorkflowOnExamCreation(exam.createdBy, exam.entities, exam.id, module);
|
||||
|
||||
if (successCount === totalCount) {
|
||||
if (isAdmin(user)) {
|
||||
responseStatus = 200;
|
||||
responseMessage = `Successfully created exam "${exam.id}" and started its Approval Workflow(s)`;
|
||||
responseMessage = `Successfully created exam "${exam.id}" and skipped Approval Workflow due to admin rights.`;
|
||||
} else if (successCount === totalCount) {
|
||||
responseStatus = 200;
|
||||
responseMessage = `Successfully created exam "${exam.id}" and started its Approval Workflow.`;
|
||||
/* responseMessage = `Successfully created exam "${exam.id}" and started its Approval Workflow(s).`; */
|
||||
} else if (successCount > 0) {
|
||||
responseStatus = 207;
|
||||
responseMessage = `Successfully created exam with ID: "${exam.id}" but was not able to start/find an Approval Workflow for all the author's entities`;
|
||||
responseMessage = `Successfully created exam with ID: "${exam.id}" but was not able to start/find an Approval Workflow for all the author's entities.`;
|
||||
} else {
|
||||
responseStatus = 207;
|
||||
responseMessage = `Successfully created exam with ID: "${exam.id}" but was not able to find any configured Approval Workflow for the author.`;
|
||||
responseMessage = `Successfully created exam with ID: "${exam.id}" but skipping approval process because no approval workflow was found configured for the exam author.`;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Workflow creation error:", error);
|
||||
responseStatus = 207;
|
||||
responseMessage = `Successfully created exam with ID: "${exam.id}" but something went wrong while creating the Approval Workflow(s).`;
|
||||
}
|
||||
} else { // if exam was updated, log the updates
|
||||
} else {
|
||||
// if exam was updated, log the updates
|
||||
const approvalWorkflows = await getApprovalWorkflowsByExamId(exam.id);
|
||||
|
||||
|
||||
if (approvalWorkflows) {
|
||||
const differences = generateExamDifferences(docSnap as Exam, exam as Exam);
|
||||
if (differences) {
|
||||
approvalWorkflows.forEach((workflow) => {
|
||||
const currentStepIndex = workflow.steps.findIndex(step => !step.completed || step.rejected);
|
||||
|
||||
const currentStepIndex = workflow.steps.findIndex((step) => !step.completed || step.rejected);
|
||||
|
||||
if (workflow.steps[currentStepIndex].examChanges === undefined) {
|
||||
workflow.steps[currentStepIndex].examChanges = [...differences];
|
||||
} else {
|
||||
@@ -131,7 +139,7 @@ async function POST(req: NextApiRequest, res: NextApiResponse) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
res.status(responseStatus).json({
|
||||
message: responseMessage,
|
||||
});
|
||||
|
||||
@@ -69,7 +69,11 @@ export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
|
||||
|
||||
if (shouldRedirectHome(user) || !["admin", "developer", "teacher", "corporate", "mastercorporate"].includes(user.type)) return redirect("/");
|
||||
|
||||
const workflows = await getApprovalWorkflows("active-workflows");
|
||||
const entityIDS = mapBy(user.entities, "id");
|
||||
const entities = await getEntitiesWithRoles(isAdmin(user) ? undefined : entityIDS);
|
||||
const allowedEntities = findAllowedEntities(user, entities, "view_workflows");
|
||||
|
||||
const workflows = await getApprovalWorkflows("active-workflows", allowedEntities.map(entity => entity.id));
|
||||
|
||||
const allAssigneeIds: string[] = [
|
||||
...new Set(
|
||||
@@ -81,10 +85,6 @@ export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
|
||||
)
|
||||
];
|
||||
|
||||
const entityIDS = mapBy(user.entities, "id");
|
||||
const entities = await getEntitiesWithRoles(isAdmin(user) ? undefined : entityIDS);
|
||||
const allowedEntities = findAllowedEntities(user, entities, "view_workflows");
|
||||
|
||||
return {
|
||||
props: serialize({
|
||||
user,
|
||||
@@ -103,7 +103,8 @@ interface Props {
|
||||
}
|
||||
|
||||
export default function ApprovalWorkflows({ user, initialWorkflows, workflowsAssignees, userEntitiesWithLabel }: Props) {
|
||||
const { workflows, reload } = useApprovalWorkflows();
|
||||
const entitiesString = userEntitiesWithLabel.map(entity => entity.id).join(",");
|
||||
const { workflows, reload } = useApprovalWorkflows(entitiesString);
|
||||
const currentWorkflows = workflows || initialWorkflows;
|
||||
|
||||
const [filteredWorkflows, setFilteredWorkflows] = useState<ApprovalWorkflow[]>([]);
|
||||
|
||||
@@ -4,11 +4,18 @@ import { ObjectId } from "mongodb";
|
||||
|
||||
const db = client.db(process.env.MONGODB_DB);
|
||||
|
||||
export const getApprovalWorkflows = async (collection: string, ids?: string[]) => {
|
||||
return await db
|
||||
.collection<ApprovalWorkflow>(collection)
|
||||
.find(ids ? { _id: { $in: ids.map((id) => new ObjectId(id)) } } : {})
|
||||
.toArray();
|
||||
export const getApprovalWorkflows = async (collection: string, entityIds?: string[], ids?: string[]) => {
|
||||
const filters: any = {};
|
||||
|
||||
if (ids && ids.length > 0) {
|
||||
filters.id = { $in: ids };
|
||||
}
|
||||
|
||||
if (entityIds && entityIds.length > 0) {
|
||||
filters.entityId = { $in: entityIds };
|
||||
}
|
||||
|
||||
return await db.collection<ApprovalWorkflow>(collection).find(filters).toArray();
|
||||
};
|
||||
|
||||
export const getApprovalWorkflow = async (collection: string, id: string) => {
|
||||
@@ -37,9 +44,9 @@ export const getApprovalWorkflowByFormIntaker = async (entityId: string, formInt
|
||||
export const getApprovalWorkflowsByExamId = async (examId: string) => {
|
||||
return await db
|
||||
.collection<ApprovalWorkflow>("active-workflows")
|
||||
.find({
|
||||
examId,
|
||||
status: { $in: ["pending"] }
|
||||
.find({
|
||||
examId,
|
||||
status: { $in: ["pending"] },
|
||||
})
|
||||
.toArray();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user