Add workflow table name filter
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -40,4 +40,6 @@ next-env.d.ts
|
|||||||
.env
|
.env
|
||||||
.yarn/*
|
.yarn/*
|
||||||
.history*
|
.history*
|
||||||
__ENV.js
|
__ENV.js
|
||||||
|
|
||||||
|
settings.json
|
||||||
@@ -17,7 +17,7 @@ import clsx from "clsx";
|
|||||||
import { withIronSessionSsr } from "iron-session/next";
|
import { withIronSessionSsr } from "iron-session/next";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useEffect, useState } from "react";
|
import { ChangeEvent, useEffect, useState } from "react";
|
||||||
import { BsTrash } from "react-icons/bs";
|
import { BsTrash } from "react-icons/bs";
|
||||||
import { FaRegEdit } from "react-icons/fa";
|
import { FaRegEdit } from "react-icons/fa";
|
||||||
import { IoIosAddCircleOutline } from "react-icons/io";
|
import { IoIosAddCircleOutline } from "react-icons/io";
|
||||||
@@ -25,6 +25,7 @@ import { toast, ToastContainer } from "react-toastify";
|
|||||||
|
|
||||||
import approvalWorkflowsData from '../../demo/approval_workflows.json'; // to test locally
|
import approvalWorkflowsData from '../../demo/approval_workflows.json'; // to test locally
|
||||||
import { FaRegClone } from "react-icons/fa6";
|
import { FaRegClone } from "react-icons/fa6";
|
||||||
|
import Input from "@/components/Low/Input";
|
||||||
|
|
||||||
const columnHelper = createColumnHelper<ApprovalWorkflow>();
|
const columnHelper = createColumnHelper<ApprovalWorkflow>();
|
||||||
|
|
||||||
@@ -64,15 +65,10 @@ const StatusClassNames: { [key in ApprovalWorkflowStatus]: string } = {
|
|||||||
rejected: "bg-red-100 text-red-800 border border-red-300 before:content-[''] before:w-2 before:h-2 before:bg-red-500 before:rounded-full before:inline-block before:mr-2",
|
rejected: "bg-red-100 text-red-800 border border-red-300 before:content-[''] before:w-2 before:h-2 before:bg-red-500 before:rounded-full before:inline-block before:mr-2",
|
||||||
};
|
};
|
||||||
|
|
||||||
type CustomStatus = ApprovalWorkflowStatus | "all";
|
type CustomStatus = ApprovalWorkflowStatus | undefined;
|
||||||
type CustomEntity = EntityWithRoles | "all";
|
type CustomEntity = EntityWithRoles["id"] | undefined;
|
||||||
|
|
||||||
const STATUS_OPTIONS = [
|
const STATUS_OPTIONS = [
|
||||||
{
|
|
||||||
label: "All",
|
|
||||||
value: "all",
|
|
||||||
filter: (x: ApprovalWorkflow) => true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
label: "Approved",
|
label: "Approved",
|
||||||
value: "approved",
|
value: "approved",
|
||||||
@@ -100,12 +96,6 @@ interface Props {
|
|||||||
export default function ApprovalWorkflows({ user, workflows, workflowsAssignees, userEntitiesWithLabel }: Props) {
|
export default function ApprovalWorkflows({ user, workflows, workflowsAssignees, userEntitiesWithLabel }: Props) {
|
||||||
|
|
||||||
const ENTITY_OPTIONS = [
|
const ENTITY_OPTIONS = [
|
||||||
{
|
|
||||||
label: "All",
|
|
||||||
value: "all",
|
|
||||||
filter: (x: ApprovalWorkflow) =>
|
|
||||||
userEntitiesWithLabel.some(entity => entity.id === x.entityId),
|
|
||||||
},
|
|
||||||
...userEntitiesWithLabel
|
...userEntitiesWithLabel
|
||||||
.map(entity => ({
|
.map(entity => ({
|
||||||
label: entity.label,
|
label: entity.label,
|
||||||
@@ -117,23 +107,43 @@ export default function ApprovalWorkflows({ user, workflows, workflowsAssignees,
|
|||||||
|
|
||||||
const [filteredWorkflows, setFilteredWorkflows] = useState<ApprovalWorkflow[]>([]);
|
const [filteredWorkflows, setFilteredWorkflows] = useState<ApprovalWorkflow[]>([]);
|
||||||
|
|
||||||
const [statusFilter, setStatusFilter] = useState<CustomStatus>("all");
|
const [statusFilter, setStatusFilter] = useState<CustomStatus>(undefined);
|
||||||
const [entityFilter, setEntityFilter] = useState<CustomEntity>("all");
|
const [entityFilter, setEntityFilter] = useState<CustomEntity>(undefined);
|
||||||
|
const [nameFilter, setNameFilter] = useState<string>("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const filters = [];
|
const filters: Array<(workflow: ApprovalWorkflow) => boolean> = [];
|
||||||
if (statusFilter) {
|
|
||||||
const filter = STATUS_OPTIONS.find((x) => x.value === statusFilter)?.filter;
|
if (statusFilter && statusFilter !== undefined) {
|
||||||
if (filter) filters.push(filter);
|
const statusOption = STATUS_OPTIONS.find((x) => x.value === statusFilter);
|
||||||
|
if (statusOption && statusOption.filter) {
|
||||||
|
filters.push(statusOption.filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (entityFilter) {
|
|
||||||
const filter = ENTITY_OPTIONS.find((x) => x.value === entityFilter)?.filter;
|
if (entityFilter && entityFilter !== undefined) {
|
||||||
if (filter) filters.push(filter);
|
const entityOption = ENTITY_OPTIONS.find((x) => x.value === entityFilter);
|
||||||
|
if (entityOption && entityOption.filter) {
|
||||||
|
filters.push(entityOption.filter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setFilteredWorkflows([...filters.reduce((d, f) => d.filter(f), workflows)]);
|
if (nameFilter.trim() !== "") {
|
||||||
|
const nameFilterFunction = (workflow: ApprovalWorkflow) =>
|
||||||
|
workflow.name.toLowerCase().includes(nameFilter.toLowerCase());
|
||||||
|
filters.push(nameFilterFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply all filters
|
||||||
|
const filtered = workflows.filter(workflow => filters.every(filterFn => filterFn(workflow)));
|
||||||
|
setFilteredWorkflows(filtered);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [workflows, statusFilter, entityFilter]);
|
}, [workflows, statusFilter, entityFilter, nameFilter]);
|
||||||
|
|
||||||
|
|
||||||
|
const handleNameFilterChange = (name: ApprovalWorkflow["name"]) => {
|
||||||
|
setNameFilter(name);
|
||||||
|
};
|
||||||
|
|
||||||
const deleteApprovalWorkflow = (id: string, name: string) => {
|
const deleteApprovalWorkflow = (id: string, name: string) => {
|
||||||
if (!confirm(`Are you sure you want to delete this Approval Workflow?`)) return;
|
if (!confirm(`Are you sure you want to delete this Approval Workflow?`)) return;
|
||||||
@@ -320,6 +330,16 @@ export default function ApprovalWorkflows({ user, workflows, workflowsAssignees,
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex w-full items-center gap-4">
|
<div className="flex w-full items-center gap-4">
|
||||||
|
<div className="flex w-full flex-col gap-3">
|
||||||
|
<label className="text-mti-gray-dim text-base font-normal">Name</label>
|
||||||
|
<Input
|
||||||
|
name="nameFilter"
|
||||||
|
type="text"
|
||||||
|
value={nameFilter}
|
||||||
|
onChange={handleNameFilterChange}
|
||||||
|
placeholder="Filter by name..."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className="flex w-full flex-col gap-3">
|
<div className="flex w-full flex-col gap-3">
|
||||||
<label className="text-mti-gray-dim text-base font-normal">Status</label>
|
<label className="text-mti-gray-dim text-base font-normal">Status</label>
|
||||||
<Select
|
<Select
|
||||||
@@ -327,7 +347,7 @@ export default function ApprovalWorkflows({ user, workflows, workflowsAssignees,
|
|||||||
value={STATUS_OPTIONS.find((x) => x.value === statusFilter)}
|
value={STATUS_OPTIONS.find((x) => x.value === statusFilter)}
|
||||||
onChange={(value) => setStatusFilter((value?.value as ApprovalWorkflowStatus) ?? undefined)}
|
onChange={(value) => setStatusFilter((value?.value as ApprovalWorkflowStatus) ?? undefined)}
|
||||||
isClearable
|
isClearable
|
||||||
placeholder="Status..."
|
placeholder="Filter by status..."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex w-full flex-col gap-3">
|
<div className="flex w-full flex-col gap-3">
|
||||||
@@ -337,7 +357,7 @@ export default function ApprovalWorkflows({ user, workflows, workflowsAssignees,
|
|||||||
value={ENTITY_OPTIONS.find((x) => x.value === entityFilter)}
|
value={ENTITY_OPTIONS.find((x) => x.value === entityFilter)}
|
||||||
onChange={(value) => setEntityFilter((value?.value as CustomEntity) ?? undefined)}
|
onChange={(value) => setEntityFilter((value?.value as CustomEntity) ?? undefined)}
|
||||||
isClearable
|
isClearable
|
||||||
placeholder="Entity..."
|
placeholder="Filter by entity..."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user