implement initialization of approval workflows on exam creation.
This commit is contained in:
@@ -17,6 +17,7 @@ import ListeningComponents from "./listening/components";
|
||||
import ReadingComponents from "./reading/components";
|
||||
import SpeakingComponents from "./speaking/components";
|
||||
import SectionPicker from "./Shared/SectionPicker";
|
||||
import { getExamById } from "@/utils/exams";
|
||||
|
||||
|
||||
const LevelSettings: React.FC = () => {
|
||||
@@ -213,6 +214,28 @@ const LevelSettings: React.FC = () => {
|
||||
URL.revokeObjectURL(url);
|
||||
});
|
||||
|
||||
const requestBody = await (async () => {
|
||||
const handledExam = await getExamById("level", result.data.id);
|
||||
|
||||
return {
|
||||
examAuthor: handledExam?.createdBy ?? "Unknown Author",
|
||||
examId: handledExam?.id ?? "Unknown ID",
|
||||
examModule: "level"
|
||||
};
|
||||
})();
|
||||
await axios.post(`/api/approval-workflows`, requestBody)
|
||||
.then(() => {
|
||||
toast.success(`Approval Workflow for exam has been created`);
|
||||
})
|
||||
.catch((reason) => {
|
||||
if (reason.response.status === 404) {
|
||||
toast.error("No configured workflow found for examAuthor.");
|
||||
}
|
||||
else {
|
||||
toast.error("Something went wrong while creating approval workflow, please try again later.");
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error: any) {
|
||||
console.error('Error submitting exam:', error);
|
||||
toast.error(
|
||||
|
||||
@@ -17,6 +17,7 @@ import { usePersistentExamStore } from "@/stores/exam";
|
||||
import { playSound } from "@/utils/sound";
|
||||
import { toast } from "react-toastify";
|
||||
import ListeningComponents from "./components";
|
||||
import { getExamById } from "@/utils/exams";
|
||||
|
||||
const ListeningSettings: React.FC = () => {
|
||||
const router = useRouter();
|
||||
@@ -151,6 +152,28 @@ const ListeningSettings: React.FC = () => {
|
||||
playSound("sent");
|
||||
toast.success(`Submitted Exam ID: ${result.data.id}`);
|
||||
|
||||
const requestBody = await (async () => {
|
||||
const handledExam = await getExamById("listening", result.data.id);
|
||||
|
||||
return {
|
||||
examAuthor: handledExam?.createdBy ?? "Unknown Author",
|
||||
examId: handledExam?.id ?? "Unknown ID",
|
||||
examModule: "listening"
|
||||
};
|
||||
})();
|
||||
await axios.post(`/api/approval-workflows`, requestBody)
|
||||
.then(() => {
|
||||
toast.success(`Approval Workflow for exam has been created`);
|
||||
})
|
||||
.catch((reason) => {
|
||||
if (reason.response.status === 404) {
|
||||
toast.error("No configured workflow found for examAuthor.");
|
||||
}
|
||||
else {
|
||||
toast.error("Something went wrong while creating approval workflow, please try again later.");
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
toast.error('No audio sections found in the exam! Please either import them or generate them.');
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import axios from "axios";
|
||||
import { playSound } from "@/utils/sound";
|
||||
import { toast } from "react-toastify";
|
||||
import ReadingComponents from "./components";
|
||||
import { getExamById } from "@/utils/exams";
|
||||
|
||||
const ReadingSettings: React.FC = () => {
|
||||
const router = useRouter();
|
||||
@@ -89,11 +90,29 @@ const ReadingSettings: React.FC = () => {
|
||||
.then((result) => {
|
||||
playSound("sent");
|
||||
toast.success(`Submitted Exam ID: ${result.data.id}`);
|
||||
|
||||
return getExamById("reading", result.data.id);
|
||||
})
|
||||
.then((handledExam) => {
|
||||
const requestBody = {
|
||||
examAuthor: handledExam?.createdBy ?? "Unknown Author",
|
||||
examId: handledExam?.id ?? "Unknown ID",
|
||||
examModule: "reading"
|
||||
};
|
||||
|
||||
return axios.post(`/api/approval-workflows`, requestBody);
|
||||
})
|
||||
.then(() => {
|
||||
toast.success(`Approval Workflow for exam has been created`);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
toast.error(error.response.data.error || "Something went wrong while submitting, please try again later.");
|
||||
})
|
||||
if (error.response && error.response.status === 404) {
|
||||
toast.error("No configured workflow found for examAuthor.");
|
||||
} else {
|
||||
// This error could come from either of the requests
|
||||
toast.error(error.response?.data?.error || "Something went wrong, please try again later.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const preview = () => {
|
||||
|
||||
@@ -11,6 +11,7 @@ import openDetachedTab from "@/utils/popout";
|
||||
import axios from "axios";
|
||||
import { playSound } from "@/utils/sound";
|
||||
import SpeakingComponents from "./components";
|
||||
import { getExamById } from "@/utils/exams";
|
||||
|
||||
export interface Avatar {
|
||||
name: string;
|
||||
@@ -195,6 +196,28 @@ const SpeakingSettings: React.FC = () => {
|
||||
URL.revokeObjectURL(url);
|
||||
});
|
||||
|
||||
const requestBody = await (async () => {
|
||||
const handledExam = await getExamById("speaking", result.data.id);
|
||||
|
||||
return {
|
||||
examAuthor: handledExam?.createdBy ?? "Unknown Author",
|
||||
examId: handledExam?.id ?? "Unknown ID",
|
||||
examModule: "speaking"
|
||||
};
|
||||
})();
|
||||
await axios.post(`/api/approval-workflows`, requestBody)
|
||||
.then(() => {
|
||||
toast.success(`Approval Workflow for exam has been created`);
|
||||
})
|
||||
.catch((reason) => {
|
||||
if (reason.response.status === 404) {
|
||||
toast.error("No configured workflow found for examAuthor.");
|
||||
}
|
||||
else {
|
||||
toast.error("Something went wrong while creating approval workflow, please try again later.");
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error: any) {
|
||||
toast.error(
|
||||
"Something went wrong while submitting, please try again later."
|
||||
|
||||
@@ -12,6 +12,8 @@ import axios from "axios";
|
||||
import { playSound } from "@/utils/sound";
|
||||
import { toast } from "react-toastify";
|
||||
import WritingComponents from "./components";
|
||||
import { getExamById } from "@/utils/exams";
|
||||
import { ApprovalWorkflow } from "@/interfaces/approval.workflow";
|
||||
|
||||
const WritingSettings: React.FC = () => {
|
||||
const router = useRouter();
|
||||
@@ -140,6 +142,28 @@ const WritingSettings: React.FC = () => {
|
||||
playSound("sent");
|
||||
toast.success(`Submitted Exam ID: ${result.data.id}`);
|
||||
|
||||
const requestBody = await (async () => {
|
||||
const handledExam = await getExamById("writing", result.data.id);
|
||||
|
||||
return {
|
||||
examAuthor: handledExam?.createdBy ?? "Unknown Author",
|
||||
examId: handledExam?.id ?? "Unknown ID",
|
||||
examModule: "writing"
|
||||
};
|
||||
})();
|
||||
await axios.post(`/api/approval-workflows`, requestBody)
|
||||
.then(() => {
|
||||
toast.success(`Approval Workflow for exam has been created`);
|
||||
})
|
||||
.catch((reason) => {
|
||||
if (reason.response.status === 404) {
|
||||
toast.error("No configured workflow found for examAuthor.");
|
||||
}
|
||||
else {
|
||||
toast.error("Something went wrong while creating approval workflow, please try again later.");
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error: any) {
|
||||
console.error('Error submitting exam:', error);
|
||||
toast.error(
|
||||
|
||||
@@ -9,6 +9,7 @@ export interface ApprovalWorkflow {
|
||||
requester: User["id"],
|
||||
startDate: number,
|
||||
modules: Module[],
|
||||
examId?: string,
|
||||
status: ApprovalWorkflowStatus,
|
||||
steps: WorkflowStep[],
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ async function del(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
const { id } = req.query as { id?: string };
|
||||
|
||||
if (id) return res.status(200).json(await deleteApprovalWorkflow("configured-workflows", id));
|
||||
if (id) return res.status(200).json(await deleteApprovalWorkflow("active-workflows", id));
|
||||
}
|
||||
|
||||
async function put(req: NextApiRequest, res: NextApiResponse) {
|
||||
@@ -41,7 +41,7 @@ async function put(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
if (id && workflow) {
|
||||
workflow._id = new ObjectId(id);
|
||||
await updateApprovalWorkflow("configured-workflows", workflow);
|
||||
await updateApprovalWorkflow("active-workflows", workflow);
|
||||
return res.status(204).end();
|
||||
}
|
||||
}
|
||||
@@ -57,6 +57,6 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { id } = req.query as { id?: string };
|
||||
|
||||
if (id) {
|
||||
return res.status(200).json(await getApprovalWorkflow("configured-workflows", id));
|
||||
return res.status(200).json(await getApprovalWorkflow("active-workflows", id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,5 +33,5 @@ async function post(req: NextApiRequest, res: NextApiResponse) {
|
||||
|
||||
await replaceApprovalWorkflowsByEntities(configuredWorkflows, entitiesIds);
|
||||
|
||||
return res.status(201).json({ ok: true });
|
||||
return res.status(204).end();
|
||||
}
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import { Module } from "@/interfaces";
|
||||
import { sessionOptions } from "@/lib/session";
|
||||
import { requestUser } from "@/utils/api";
|
||||
import { getApprovalWorkflows } from "@/utils/approval.workflows.be";
|
||||
import { createApprovalWorkflow, getApprovalWorkflowByFormIntaker, getApprovalWorkflows } from "@/utils/approval.workflows.be";
|
||||
import { withIronSessionApiRoute } from "iron-session/next";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
export default withIronSessionApiRoute(handler, sessionOptions);
|
||||
|
||||
interface PostRequestBody {
|
||||
examAuthor: string,
|
||||
examId: string,
|
||||
examName: string,
|
||||
examModule: Module,
|
||||
}
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
if (req.method === "GET") return await get(req, res);
|
||||
if (req.method === "POST") return await post(req, res);
|
||||
}
|
||||
|
||||
async function get(req: NextApiRequest, res: NextApiResponse) {
|
||||
@@ -19,5 +28,33 @@ async function get(req: NextApiRequest, res: NextApiResponse) {
|
||||
return res.status(403).json({ ok: false });
|
||||
}
|
||||
|
||||
return res.status(200).json(await getApprovalWorkflows("configured-workflows"));
|
||||
return res.status(200).json(await getApprovalWorkflows("active-workflows"));
|
||||
}
|
||||
|
||||
async function post(req: NextApiRequest, res: NextApiResponse) {
|
||||
const user = await requestUser(req, res);
|
||||
if (!user) return res.status(401).json({ ok: false });
|
||||
|
||||
if (!["admin", "developer", "corporate", "mastercorporate"].includes(user.type)) {
|
||||
return res.status(403).json({ ok: false });
|
||||
}
|
||||
|
||||
const { examAuthor, examId, examModule } = req.body as PostRequestBody;
|
||||
|
||||
if (examAuthor) {
|
||||
const configuredWorkflow = await getApprovalWorkflowByFormIntaker(examAuthor);
|
||||
if(configuredWorkflow) {
|
||||
configuredWorkflow.modules.push(examModule);
|
||||
configuredWorkflow.name = `${examId}`;
|
||||
configuredWorkflow.examId = examId;
|
||||
configuredWorkflow.startDate = Date.now();
|
||||
|
||||
return res.status(201).json(await createApprovalWorkflow("active-workflows", configuredWorkflow));
|
||||
} else {
|
||||
return res.status(404).json("No configured workflow found for examAuthor.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export const getServerSideProps = withIronSessionSsr(async ({ req, res, params }
|
||||
|
||||
const { id } = params as { id: string };
|
||||
|
||||
const workflow: ApprovalWorkflow | null = await getApprovalWorkflow("configured-workflows", id);
|
||||
const workflow: ApprovalWorkflow | null = await getApprovalWorkflow("active-workflows", id);
|
||||
|
||||
if (!workflow)
|
||||
return redirect("/approval-workflows")
|
||||
@@ -161,7 +161,11 @@ export default function Home({ user, initialWorkflow, id, workflowAssignees, wor
|
||||
return;
|
||||
})
|
||||
|
||||
if (selectedStepIndex + 1 < currentWorkflow.steps.length){
|
||||
handleStepClick(selectedStepIndex + 1, currentWorkflow.steps[selectedStepIndex + 1]);
|
||||
} else {
|
||||
setIsPanelOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleRejectStep = () => {
|
||||
|
||||
@@ -20,7 +20,6 @@ import clsx from "clsx";
|
||||
import { withIronSessionSsr } from "iron-session/next";
|
||||
import Head from "next/head";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { useEffect, useState } from "react";
|
||||
import { BsTrash } from "react-icons/bs";
|
||||
import { FaRegEdit } from "react-icons/fa";
|
||||
@@ -98,6 +97,8 @@ export default function ApprovalWorkflows({ user, initialWorkflows, workflowsAss
|
||||
const {workflows, reload} = useApprovalWorkflows();
|
||||
const currentWorkflows = workflows || initialWorkflows;
|
||||
|
||||
console.log(currentWorkflows);
|
||||
|
||||
const [filteredWorkflows, setFilteredWorkflows] = useState<ApprovalWorkflow[]>([]);
|
||||
|
||||
const [statusFilter, setStatusFilter] = useState<CustomStatus>(undefined);
|
||||
|
||||
@@ -22,9 +22,9 @@ export const getApprovalWorkflowsByEntities = async (collection: string, ids: st
|
||||
.toArray();
|
||||
};
|
||||
|
||||
export const getApprovalWorkflowByFormIntaker = async (entityId: string, formIntakerId: string) => {
|
||||
export const getApprovalWorkflowByFormIntaker = async (/* entityId: string, */ formIntakerId: string) => {
|
||||
return await db.collection<ApprovalWorkflow>("configured-workflows").findOne({
|
||||
entityId,
|
||||
/* entityId, */
|
||||
steps: {
|
||||
$elemMatch: {
|
||||
stepNumber: 1,
|
||||
|
||||
Reference in New Issue
Block a user