major change on how workflow builder works. It now fetches in edit mode all the currently configured workflows
This commit is contained in:
@@ -22,9 +22,9 @@ import { useEffect, useState } from "react";
|
||||
import { BsChevronLeft } from "react-icons/bs";
|
||||
import { GrClearOption } from "react-icons/gr";
|
||||
import { toast, ToastContainer } from "react-toastify";
|
||||
import { getApprovalWorkflow } from "@/utils/approval.workflows.be";
|
||||
import { useRouter } from "next/router";
|
||||
import axios from "axios";
|
||||
import { getConfiguredWorkflow } from "@/utils/approval.workflows.be";
|
||||
|
||||
export const getServerSideProps = withIronSessionSsr(async ({ req, res, params }) => {
|
||||
const user = await requestUser(req, res);
|
||||
@@ -35,7 +35,7 @@ export const getServerSideProps = withIronSessionSsr(async ({ req, res, params }
|
||||
|
||||
const { id } = params as { id: string };
|
||||
|
||||
const workflow: ApprovalWorkflow | null = await getApprovalWorkflow(id);
|
||||
const workflow: ApprovalWorkflow | null = await getConfiguredWorkflow(id);
|
||||
|
||||
if (!workflow)
|
||||
return redirect("/approval-workflows")
|
||||
@@ -91,6 +91,7 @@ export default function Home({ user, workflow, userEntitiesWithLabel, userEntiti
|
||||
key: step.stepNumber + 999, // just making sure they are unique because new steps that users add will have key=3 key=4 etc
|
||||
stepType: step.stepType,
|
||||
stepNumber: step.stepNumber,
|
||||
completed: false,
|
||||
assignees: step.assignees.map(id => id),
|
||||
firstStep: step.firstStep || false,
|
||||
finalStep: step.finalStep || false,
|
||||
@@ -179,8 +180,8 @@ export default function Home({ user, workflow, userEntitiesWithLabel, userEntiti
|
||||
startDate: Date.now(),
|
||||
status: "pending",
|
||||
steps: [
|
||||
{ key: 9998, stepType: "form-intake", stepNumber: 1, firstStep: true, finalStep: false, assignees: [null] },
|
||||
{ key: 9999, stepType: "approval-by", stepNumber: 2, firstStep: false, finalStep: true, assignees: [null] },
|
||||
{ key: 9998, stepType: "form-intake", stepNumber: 1, completed: false, firstStep: true, finalStep: false, assignees: [null] },
|
||||
{ key: 9999, stepType: "approval-by", stepNumber: 2, completed: false, firstStep: false, finalStep: true, assignees: [null] },
|
||||
],
|
||||
};
|
||||
setCloneWorkflow(newWorkflow);
|
||||
|
||||
@@ -8,18 +8,18 @@ import { CorporateUser, DeveloperUser, MasterCorporateUser, TeacherUser, User }
|
||||
import { sessionOptions } from "@/lib/session";
|
||||
import { redirect, serialize } from "@/utils";
|
||||
import { requestUser } from "@/utils/api";
|
||||
import { getConfiguredWorkflow } from "@/utils/approval.workflows.be";
|
||||
import { shouldRedirectHome } from "@/utils/navigation.disabled";
|
||||
import { getEntityUsers } from "@/utils/users.be";
|
||||
import axios from "axios";
|
||||
import { motion } from "framer-motion";
|
||||
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 { BsChevronLeft } from "react-icons/bs";
|
||||
import { toast, ToastContainer } from "react-toastify";
|
||||
import axios from "axios";
|
||||
import { getApprovalWorkflow } from "@/utils/approval.workflows.be";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
export const getServerSideProps = withIronSessionSsr(async ({ req, res, params }) => {
|
||||
const user = await requestUser(req, res);
|
||||
@@ -30,7 +30,7 @@ export const getServerSideProps = withIronSessionSsr(async ({ req, res, params }
|
||||
|
||||
const { id } = params as { id: string };
|
||||
|
||||
const workflow: ApprovalWorkflow | null = await getApprovalWorkflow(id);
|
||||
const workflow: ApprovalWorkflow | null = await getConfiguredWorkflow(id);
|
||||
|
||||
if (!workflow)
|
||||
return redirect("/approval-workflows")
|
||||
@@ -62,6 +62,9 @@ export default function Home({ user, workflow, workflowEntityApprovers }: Props)
|
||||
key: step.stepNumber + 999, // just making sure they are unique because new steps that users add will have key=3 key=4 etc
|
||||
stepType: step.stepType,
|
||||
stepNumber: step.stepNumber,
|
||||
completed: step.completed,
|
||||
completedBy: step.completedBy || undefined,
|
||||
completedDate: step.completedDate || undefined,
|
||||
assignees: step.assignees.map(id => id),
|
||||
firstStep: step.firstStep || false,
|
||||
finalStep: step.finalStep || false,
|
||||
|
||||
@@ -11,7 +11,7 @@ import { User } from "@/interfaces/user";
|
||||
import { sessionOptions } from "@/lib/session";
|
||||
import { redirect, serialize } from "@/utils";
|
||||
import { requestUser } from "@/utils/api";
|
||||
import { getApprovalWorkflow } from "@/utils/approval.workflows.be";
|
||||
import { getConfiguredWorkflow } from "@/utils/approval.workflows.be";
|
||||
import { shouldRedirectHome } from "@/utils/navigation.disabled";
|
||||
import { getSpecificUsers, getUser } from "@/utils/users.be";
|
||||
import axios from "axios";
|
||||
@@ -23,12 +23,14 @@ import { useRouter } from "next/router";
|
||||
import { useState } from "react";
|
||||
import { BsChevronLeft } from "react-icons/bs";
|
||||
import { FaSpinner, FaWpforms } from "react-icons/fa6";
|
||||
import { FiSave } from "react-icons/fi";
|
||||
import { IoMdCheckmarkCircleOutline } from "react-icons/io";
|
||||
import { IoDocumentTextOutline } from "react-icons/io5";
|
||||
import { MdOutlineDoubleArrow } from "react-icons/md";
|
||||
import { RiThumbUpLine } from "react-icons/ri";
|
||||
import { toast, ToastContainer } from "react-toastify";
|
||||
import { IoMdCheckmarkCircleOutline } from "react-icons/io";
|
||||
import { FiSave } from "react-icons/fi";
|
||||
import { RxCrossCircled } from "react-icons/rx";
|
||||
import { TiEdit } from "react-icons/ti";
|
||||
import { toast, ToastContainer } from "react-toastify";
|
||||
|
||||
export const getServerSideProps = withIronSessionSsr(async ({ req, res, params }) => {
|
||||
const user = await requestUser(req, res);
|
||||
@@ -39,7 +41,7 @@ export const getServerSideProps = withIronSessionSsr(async ({ req, res, params }
|
||||
|
||||
const { id } = params as { id: string };
|
||||
|
||||
const workflow: ApprovalWorkflow | null = await getApprovalWorkflow(id);
|
||||
const workflow: ApprovalWorkflow | null = await getConfiguredWorkflow(id);
|
||||
|
||||
if (!workflow)
|
||||
return redirect("/approval-workflows")
|
||||
@@ -132,6 +134,7 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
|
||||
|
||||
const updatedWorkflow: ApprovalWorkflow = {
|
||||
...workflow,
|
||||
status: selectedStepIndex === workflow.steps.length - 1 ? "approved" : "pending",
|
||||
steps: workflow.steps.map((step, index) =>
|
||||
index === selectedStepIndex ?
|
||||
{
|
||||
@@ -206,6 +209,14 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
|
||||
})
|
||||
};
|
||||
|
||||
const handleViewExam = () => {
|
||||
|
||||
}
|
||||
|
||||
const handleEditExam = () => {
|
||||
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
@@ -244,6 +255,29 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
|
||||
status={workflow.status}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-row gap-3">
|
||||
<Button
|
||||
color="purple"
|
||||
variant="solid"
|
||||
onClick={handleViewExam}
|
||||
padding="px-6 py-2"
|
||||
className="w-[240px] text-lg flex items-center justify-center gap-2 text-left"
|
||||
>
|
||||
<IoDocumentTextOutline />
|
||||
View Exam
|
||||
</Button>
|
||||
<Button
|
||||
color="purple"
|
||||
variant="solid"
|
||||
onClick={handleEditExam}
|
||||
padding="px-6 py-2"
|
||||
className="w-[240px] text-lg flex items-center justify-center gap-2 text-left"
|
||||
>
|
||||
<TiEdit size={20} />
|
||||
Edit Exam
|
||||
</Button>
|
||||
|
||||
</div>
|
||||
{steps.find((step) => !step.completed) === undefined &&
|
||||
<Tip text="All steps in this instance have been completed." />
|
||||
}
|
||||
@@ -271,7 +305,7 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
|
||||
{/* Side panel */}
|
||||
<AnimatePresence mode="wait">
|
||||
<LayoutGroup key="sidePanel">
|
||||
<section className={`absolute inset-y-0 right-0 h-full bg-mti-purple-ultralight bg-opacity-50 shadow-xl shadow-mti-purple transition-all duration-300 overflow-hidden ${isPanelOpen ? 'w-2/5' : 'w-0'}`}>
|
||||
<section className={`absolute inset-y-0 right-0 h-full bg-mti-purple-ultralight bg-opacity-50 shadow-xl shadow-mti-purple transition-all duration-300 overflow-hidden ${isPanelOpen ? 'w-[500px]' : 'w-0'}`}>
|
||||
{isPanelOpen && selectedStep && (
|
||||
<motion.div
|
||||
className="p-6"
|
||||
@@ -412,7 +446,7 @@ export default function Home({ user, workflow, workflowAssignees, workflowReques
|
||||
) : (
|
||||
<>
|
||||
<RxCrossCircled size={20} />
|
||||
Reject Step
|
||||
Reject
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
@@ -10,6 +10,7 @@ import { CorporateUser, DeveloperUser, MasterCorporateUser, TeacherUser, User }
|
||||
import { sessionOptions } from "@/lib/session";
|
||||
import { redirect, serialize } from "@/utils";
|
||||
import { requestUser } from "@/utils/api";
|
||||
import { getConfiguredWorkflowsByEntities } from "@/utils/approval.workflows.be";
|
||||
import { getEntities } from "@/utils/entities.be";
|
||||
import { shouldRedirectHome } from "@/utils/navigation.disabled";
|
||||
import { getEntitiesUsers } from "@/utils/users.be";
|
||||
@@ -33,10 +34,13 @@ export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
|
||||
return redirect("/")
|
||||
|
||||
const userEntitiesWithLabel = await getEntities(user.entities.map(entity => entity.id));
|
||||
|
||||
const allConfiguredWorkflows = await getConfiguredWorkflowsByEntities(userEntitiesWithLabel.map(entity => entity.id));
|
||||
|
||||
return {
|
||||
props: serialize({
|
||||
user,
|
||||
allConfiguredWorkflows,
|
||||
userEntitiesWithLabel,
|
||||
userEntitiesApprovers: await getEntitiesUsers(userEntitiesWithLabel.map(entity => entity.id), { type: { $in: ["teacher", "corporate", "mastercorporate", "developer"] } }) as (TeacherUser | CorporateUser | MasterCorporateUser | DeveloperUser)[],
|
||||
}),
|
||||
@@ -45,12 +49,13 @@ export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
|
||||
|
||||
interface Props {
|
||||
user: User,
|
||||
allConfiguredWorkflows: EditableApprovalWorkflow[],
|
||||
userEntitiesWithLabel: Entity[],
|
||||
userEntitiesApprovers: (TeacherUser | CorporateUser | MasterCorporateUser | DeveloperUser)[],
|
||||
}
|
||||
|
||||
export default function Home({ user, userEntitiesWithLabel, userEntitiesApprovers }: Props) {
|
||||
const [workflows, setWorkflows] = useState<EditableApprovalWorkflow[]>([]);
|
||||
export default function Home({ user, allConfiguredWorkflows, userEntitiesWithLabel, userEntitiesApprovers }: Props) {
|
||||
const [workflows, setWorkflows] = useState<EditableApprovalWorkflow[]>(allConfiguredWorkflows);
|
||||
const [selectedWorkflowId, setSelectedWorkflowId] = useState<string | undefined>(undefined);
|
||||
const [entityId, setEntityId] = useState<string | null | undefined>(null);
|
||||
const [entityApprovers, setEntityApprovers] = useState<(TeacherUser | CorporateUser | MasterCorporateUser | DeveloperUser)[]>([]);
|
||||
@@ -93,13 +98,14 @@ export default function Home({ user, userEntitiesWithLabel, userEntitiesApprover
|
||||
...workflow,
|
||||
steps: workflow.steps.map(step => ({
|
||||
...step,
|
||||
completed: false,
|
||||
assignees: step.assignees.filter((assignee): assignee is string => assignee !== null && assignee !== undefined)
|
||||
}))
|
||||
}));
|
||||
|
||||
const requestData = {filteredWorkflows, userEntitiesWithLabel};
|
||||
|
||||
axios
|
||||
.post(`/api/approval-workflows/create`, filteredWorkflows)
|
||||
.post(`/api/approval-workflows/create`, requestData)
|
||||
.then(() => {
|
||||
toast.success("Approval Workflows created successfully.");
|
||||
setIsRedirecting(true);
|
||||
@@ -135,8 +141,8 @@ export default function Home({ user, userEntitiesWithLabel, userEntitiesApprover
|
||||
startDate: Date.now(),
|
||||
status: "pending",
|
||||
steps: [
|
||||
{ key: 9998, stepType: "form-intake", stepNumber: 1, firstStep: true, finalStep: false, assignees: [null] },
|
||||
{ key: 9999, stepType: "approval-by", stepNumber: 2, firstStep: false, finalStep: true, assignees: [null] },
|
||||
{ key: 9998, stepType: "form-intake", stepNumber: 1, completed: false, firstStep: true, finalStep: false, assignees: [null] },
|
||||
{ key: 9999, stepType: "approval-by", stepNumber: 2, completed: false, firstStep: false, finalStep: true, assignees: [null] },
|
||||
],
|
||||
};
|
||||
setWorkflows((prev) => [...prev, newWorkflow]);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Layout from "@/components/High/Layout";
|
||||
import Button from "@/components/Low/Button";
|
||||
import Input from "@/components/Low/Input";
|
||||
import Select from "@/components/Low/Select";
|
||||
import { Module, ModuleTypeLabels } from "@/interfaces";
|
||||
import { ApprovalWorkflow, ApprovalWorkflowStatus, ApprovalWorkflowStatusLabel, StepTypeLabel } from "@/interfaces/approval.workflow";
|
||||
@@ -8,6 +9,7 @@ import { User } from "@/interfaces/user";
|
||||
import { sessionOptions } from "@/lib/session";
|
||||
import { redirect, serialize } from "@/utils";
|
||||
import { requestUser } from "@/utils/api";
|
||||
import { getConfiguredWorkflows } from "@/utils/approval.workflows.be";
|
||||
import { getEntities } from "@/utils/entities.be";
|
||||
import { shouldRedirectHome } from "@/utils/navigation.disabled";
|
||||
import { getSpecificUsers } from "@/utils/users.be";
|
||||
@@ -17,18 +19,14 @@ 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";
|
||||
import { FaRegClone } from "react-icons/fa6";
|
||||
import { IoIosAddCircleOutline } from "react-icons/io";
|
||||
import { toast, ToastContainer } from "react-toastify";
|
||||
|
||||
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<ApprovalWorkflow>();
|
||||
|
||||
export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
|
||||
@@ -38,7 +36,7 @@ export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
|
||||
if (shouldRedirectHome(user) || !["admin", "developer", "teacher", "corporate", "mastercorporate"].includes(user.type))
|
||||
return redirect("/")
|
||||
|
||||
const workflows = await getApprovalWorkflows();
|
||||
const workflows = await getConfiguredWorkflows();
|
||||
|
||||
const allAssigneeIds: string[] = [
|
||||
...new Set(
|
||||
@@ -331,7 +329,7 @@ export default function ApprovalWorkflows({ user, workflows, workflowsAssignees,
|
||||
className="min-w-fit text-lg font-medium flex items-center gap-2 text-left"
|
||||
>
|
||||
<IoIosAddCircleOutline className="size-6" />
|
||||
Configure New Workflows
|
||||
Configure Workflows
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user