diff --git a/src/pages/api/approval-workflows/[id]/edit.ts b/src/pages/api/approval-workflows/[id]/edit.ts
index 2d517f0e..c61e200a 100644
--- a/src/pages/api/approval-workflows/[id]/edit.ts
+++ b/src/pages/api/approval-workflows/[id]/edit.ts
@@ -2,7 +2,7 @@
import { ApprovalWorkflow } from "@/interfaces/approval.workflow";
import { sessionOptions } from "@/lib/session";
import { requestUser } from "@/utils/api";
-import { createApprovalWorkflows, updateApprovalWorkflow } from "@/utils/approval.workflows.be";
+import { updateApprovalWorkflow } from "@/utils/approval.workflows.be";
import { withIronSessionApiRoute } from "iron-session/next";
import type { NextApiRequest, NextApiResponse } from "next";
@@ -23,6 +23,8 @@ async function put(req: NextApiRequest, res: NextApiResponse) {
const { id } = req.query as { id?: string };
const approvalWorkflow: ApprovalWorkflow = req.body;
- if (id && approvalWorkflow)
- return res.status(204).json(await updateApprovalWorkflow(id, approvalWorkflow));
+ if (id && approvalWorkflow) {
+ await updateApprovalWorkflow(id, approvalWorkflow);
+ return res.status(204).end();
+ }
}
diff --git a/src/pages/api/approval-workflows/[id]/index.ts b/src/pages/api/approval-workflows/[id]/index.ts
index 16efab91..e8de49a8 100644
--- a/src/pages/api/approval-workflows/[id]/index.ts
+++ b/src/pages/api/approval-workflows/[id]/index.ts
@@ -2,7 +2,7 @@
import { ApprovalWorkflow } from "@/interfaces/approval.workflow";
import { sessionOptions } from "@/lib/session";
import { requestUser } from "@/utils/api";
-import { createApprovalWorkflows, deleteApprovalWorkflow, updateApprovalWorkflow } from "@/utils/approval.workflows.be";
+import { deleteApprovalWorkflow, updateApprovalWorkflow } from "@/utils/approval.workflows.be";
import { withIronSessionApiRoute } from "iron-session/next";
import type { NextApiRequest, NextApiResponse } from "next";
@@ -10,6 +10,7 @@ export default withIronSessionApiRoute(handler, sessionOptions);
async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === "DELETE") return await del(req, res);
+ if (req.method === "PUT") return await put(req, res);
}
async function del(req: NextApiRequest, res: NextApiResponse) {
@@ -22,6 +23,22 @@ async function del(req: NextApiRequest, res: NextApiResponse) {
const { id } = req.query as { id?: string };
- if (id)
- return res.status(200).json(await deleteApprovalWorkflow(id));
+ if (id) return res.status(200).json(await deleteApprovalWorkflow(id));
+}
+
+async function put(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 { id } = req.query as { id?: string };
+ const workflow = req.body;
+
+ if (id && workflow) {
+ await updateApprovalWorkflow(id, workflow);
+ return res.status(204).end();
+ }
}
diff --git a/src/pages/approval-workflows/[id]/clone.tsx b/src/pages/approval-workflows/[id]/clone.tsx
index 7246b695..f91a83da 100644
--- a/src/pages/approval-workflows/[id]/clone.tsx
+++ b/src/pages/approval-workflows/[id]/clone.tsx
@@ -124,7 +124,6 @@ export default function Home({ user, workflow, userEntitiesWithLabel, userEntiti
...cloneWorkflow,
steps: cloneWorkflow.steps.map(step => ({
...step,
- currentStep: step.stepNumber === 1 ? true : false,
completed: false,
assignees: step.assignees.filter((assignee): assignee is string => assignee !== null && assignee !== undefined)
}))
@@ -137,23 +136,21 @@ export default function Home({ user, workflow, userEntitiesWithLabel, userEntiti
setIsRedirecting(true);
setTimeout(() => {
router.push("/approval-workflows");
- }, 2000);
+ }, 1000);
})
.catch((reason) => {
if (reason.response.status === 401) {
toast.error("Not logged in!");
- return router.push("/login");
- }
- if (reason.response.status === 403) {
+ } else if (reason.response.status === 403) {
toast.error("You do not have permission to clone Approval Workflows!");
- return router.push("/approval-workflows");
+ } else {
+ toast.error("Something went wrong, please try again later.");
}
- toast.error("Something went wrong, please try again later.");
setIsLoading(false);
+ console.log("Submitted Values:", filteredWorkflow);
return;
})
- console.log("Form submitted! Filtered Values:", filteredWorkflow);
};
const onWorkflowChange = (wf: EditableApprovalWorkflow) => {
diff --git a/src/pages/approval-workflows/[id]/edit.tsx b/src/pages/approval-workflows/[id]/edit.tsx
index 8bad8e91..7c9a1d83 100644
--- a/src/pages/approval-workflows/[id]/edit.tsx
+++ b/src/pages/approval-workflows/[id]/edit.tsx
@@ -95,12 +95,11 @@ export default function Home({ user, workflow, workflowEntityApprovers }: Props)
...updatedWorkflow,
steps: updatedWorkflow.steps.map(step => ({
...step,
- currentStep: step.stepNumber === 1 ? true : false,
completed: false,
assignees: step.assignees.filter((assignee): assignee is string => assignee !== null && assignee !== undefined)
}))
};
-
+
axios
.put(`/api/approval-workflows/${updatedWorkflow.id}/edit`, filteredWorkflow)
.then(() => {
@@ -108,23 +107,20 @@ export default function Home({ user, workflow, workflowEntityApprovers }: Props)
setIsRedirecting(true);
setTimeout(() => {
router.push("/approval-workflows");
- }, 2000);
+ }, 1000);
})
.catch((reason) => {
if (reason.response.status === 401) {
toast.error("Not logged in!");
- return router.push("/login");
- }
- if (reason.response.status === 403) {
+ } else if (reason.response.status === 403) {
toast.error("You do not have permission to edit Approval Workflows!");
- return router.push("/approval-workflows");
+ } else {
+ toast.error("Something went wrong, please try again later.");
}
- toast.error("Something went wrong, please try again later.");
setIsLoading(false);
+ console.log("Submitted Values:", filteredWorkflow);
return;
})
-
- console.log("Form submitted! Filtered Values:", filteredWorkflow);
};
const onWorkflowChange = (updatedWorkflow: EditableApprovalWorkflow) => {
@@ -159,7 +155,7 @@ export default function Home({ user, workflow, workflowEntityApprovers }: Props)
{
const user = await requestUser(req, res);
@@ -75,6 +79,9 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
const [selectedStep, setSelectedStep] = useState(steps[selectedStepIndex]);
const [isPanelOpen, setIsPanelOpen] = useState(true);
const [comments, setComments] = useState(selectedStep.comments || "");
+ const [isLoading, setIsLoading] = useState(false);
+ const [isRedirecting, setIsRedirecting] = useState(false);
+ const router = useRouter();
const handleStepClick = (index: number, stepInfo: WorkflowStep) => {
setSelectedStep(stepInfo);
@@ -84,11 +91,82 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
};
const handleSaveComments = () => {
+ setIsLoading(true);
+ const updatedWorkflow: ApprovalWorkflow = {
+ ...workflow,
+ steps: workflow.steps.map((step, index) =>
+ index === selectedStepIndex ?
+ {
+ ...step,
+ comments: comments,
+ }
+ : step
+ )
+ };
+
+ axios
+ .put(`/api/approval-workflows/${workflow._id}`, updatedWorkflow)
+ .then(() => {
+ toast.success("Comments saved successfully.");
+ setIsRedirecting(true);
+ setTimeout(() => {
+ router.reload();
+ }, 1000);
+ })
+ .catch((reason) => {
+ if (reason.response.status === 401) {
+ toast.error("Not logged in!");
+ } else if (reason.response.status === 403) {
+ toast.error("You do not have permission to approve this step!");
+ } else {
+ toast.error("Something went wrong, please try again later.");
+ }
+ setIsLoading(false);
+ console.log("Submitted Values:", updatedWorkflow);
+ return;
+ })
};
const handleApproveStep = () => {
-
+ if (!confirm(`Are you sure you want to approve this step?`)) return;
+ setIsLoading(true);
+
+ const updatedWorkflow: ApprovalWorkflow = {
+ ...workflow,
+ steps: workflow.steps.map((step, index) =>
+ index === selectedStepIndex ?
+ {
+ ...step,
+ completed: true,
+ completedBy: user.id,
+ completedDate: Date.now(),
+ }
+ : step
+ )
+ };
+
+ axios
+ .put(`/api/approval-workflows/${workflow._id}`, updatedWorkflow)
+ .then(() => {
+ toast.success("Step approved successfully.");
+ setIsRedirecting(true);
+ setTimeout(() => {
+ router.reload();
+ }, 1000);
+ })
+ .catch((reason) => {
+ if (reason.response.status === 401) {
+ toast.error("Not logged in!");
+ } else if (reason.response.status === 403) {
+ toast.error("You do not have permission to approve this step!");
+ } else {
+ toast.error("Something went wrong, please try again later.");
+ }
+ setIsLoading(false);
+ console.log("Submitted Values:", updatedWorkflow);
+ return;
+ })
};
return (
@@ -120,7 +198,7 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
)}
-
- {selectedStepIndex === currentStep &&
+
+ {selectedStepIndex === currentStep && !selectedStep.completed &&
}
@@ -267,14 +361,32 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
placeholder="Input comments here"
className="w-full h-64 p-2 border-2 rounded-xl shadow-lg focus:border-mti-purple focus:outline-none mt-3 resize-none"
/>
+
diff --git a/src/pages/approval-workflows/create.tsx b/src/pages/approval-workflows/create.tsx
index d2299c4a..73d5a4c0 100644
--- a/src/pages/approval-workflows/create.tsx
+++ b/src/pages/approval-workflows/create.tsx
@@ -86,13 +86,13 @@ export default function Home({ user, userEntitiesWithLabel, userEntitiesApprover
if (workflows.length === 0) {
setIsLoading(false);
+ return;
}
const filteredWorkflows: ApprovalWorkflow[] = workflows.map(workflow => ({
...workflow,
steps: workflow.steps.map(step => ({
...step,
- currentStep: step.stepNumber === 1 ? true : false,
completed: false,
assignees: step.assignees.filter((assignee): assignee is string => assignee !== null && assignee !== undefined)
}))
@@ -105,23 +105,22 @@ export default function Home({ user, userEntitiesWithLabel, userEntitiesApprover
setIsRedirecting(true);
setTimeout(() => {
router.push("/approval-workflows");
- }, 2000);
+ }, 1000);
})
.catch((reason) => {
if (reason.response.status === 401) {
toast.error("Not logged in!");
- return router.push("/login");
}
- if (reason.response.status === 403) {
+ else if (reason.response.status === 403) {
toast.error("You do not have permission to create Approval Workflows!");
- return router.push("/approval-workflows");
}
- toast.error("Something went wrong, please try again later.");
+ else {
+ toast.error("Something went wrong, please try again later.");
+ }
setIsLoading(false);
+ console.log("Submitted Values:", filteredWorkflows);
return;
})
-
- console.log("Form submitted! Filtered Values:", filteredWorkflows);
};
const handleAddNewWorkflow = () => {
diff --git a/src/pages/approval-workflows/index.tsx b/src/pages/approval-workflows/index.tsx
index c7c71731..a8b59b26 100644
--- a/src/pages/approval-workflows/index.tsx
+++ b/src/pages/approval-workflows/index.tsx
@@ -27,6 +27,7 @@ import Input from "@/components/Low/Input";
import { FaRegClone } from "react-icons/fa6";
import useApprovalWorkflows from "@/hooks/useApprovalWorkflows";
import { getApprovalWorkflows } from "@/utils/approval.workflows.be";
+import { useRouter } from "next/router";
const columnHelper = createColumnHelper();
@@ -110,6 +111,7 @@ export default function ApprovalWorkflows({ user, workflows, workflowsAssignees,
const [statusFilter, setStatusFilter] = useState(undefined);
const [entityFilter, setEntityFilter] = useState(undefined);
const [nameFilter, setNameFilter] = useState("");
+ const router = useRouter();
useEffect(() => {
const filters: Array<(workflow: ApprovalWorkflow) => boolean> = [];
@@ -154,21 +156,18 @@ export default function ApprovalWorkflows({ user, workflows, workflowsAssignees,
.then(() => {
toast.success(`Successfully deleted ${name} Approval Workflow.`);
setTimeout(() => {
- window.location.reload();
- }, 2000);
+ router.reload();
+ }, 1000);
})
.catch((reason) => {
if (reason.response.status === 404) {
toast.error("Approval Workflow not found!");
- return;
- }
-
- if (reason.response.status === 403) {
+ } else if (reason.response.status === 403) {
toast.error("You do not have permission to delete an Approval Workflow!");
- return;
+ } else {
+ toast.error("Something went wrong, please try again later.");
}
-
- toast.error("Something went wrong, please try again later.");
+ return;
})
};
diff --git a/src/utils/approval.workflows.be.ts b/src/utils/approval.workflows.be.ts
index e876a279..f82056dd 100644
--- a/src/utils/approval.workflows.be.ts
+++ b/src/utils/approval.workflows.be.ts
@@ -15,17 +15,20 @@ export const getApprovalWorkflow = async (id: string) => {
return await db.collection("approval-workflows").findOne({ _id: new ObjectId(id) });
};
-export const createApprovalWorkflow = async (workflow: Omit) => {
- return await db.collection("approval-workflows").insertOne(workflow);
+export const createApprovalWorkflow = async (workflow: ApprovalWorkflow) => {
+ const { _id, ...workflowWithoutId } = workflow as ApprovalWorkflow;
+ return await db.collection("approval-workflows").insertOne(workflowWithoutId);
};
-export const createApprovalWorkflows = async (workflows: Omit[]) => {
+export const createApprovalWorkflows = async (workflows: ApprovalWorkflow[]) => {
if (workflows.length === 0) return;
- return await db.collection("approval-workflows").insertMany(workflows);
+ const workflowsWithoutIds: ApprovalWorkflow[] = workflows.map(({_id, ...wfs}) => wfs)
+ return await db.collection("approval-workflows").insertMany(workflowsWithoutIds);
};
-export const updateApprovalWorkflow = async (id: string, workflow: Omit) => {
- return await db.collection("approval-workflows").replaceOne({ _id: new ObjectId(id) }, workflow);
+export const updateApprovalWorkflow = async (id: string, workflow: ApprovalWorkflow) => {
+ const { _id, ...workflowWithoutId } = workflow as ApprovalWorkflow;
+ return await db.collection("approval-workflows").replaceOne({ _id: new ObjectId(id) }, workflowWithoutId);
};
export const deleteApprovalWorkflow = async (id: string) => {