- Progress commit

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-03-28 12:30:14 -04:00
parent ae9e9f4b72
commit dc22b96bed
8 changed files with 250 additions and 66 deletions

View File

@@ -84,10 +84,13 @@ function TaskListComponent({
loading, loading,
tasks, tasks,
total, total,
titleTranslation,
refetch, refetch,
toggleCompletedStatus, toggleCompletedStatus,
setTaskUpsertContext, setTaskUpsertContext,
toggleDeletedStatus toggleDeletedStatus,
relationshipType,
relationshipId
}) { }) {
const {t} = useTranslation(); const {t} = useTranslation();
@@ -186,7 +189,9 @@ function TaskListComponent({
const handleCreateTask = () => { const handleCreateTask = () => {
setTaskUpsertContext({ setTaskUpsertContext({
actions: {}, actions: {},
context: {}, context: {
[relationshipType]: relationshipId,
},
}); });
}; };
@@ -241,7 +246,7 @@ function TaskListComponent({
return ( return (
<Card <Card
title={t("menus.header.my_tasks")} title={titleTranslation}
extra={tasksExtra()} extra={tasksExtra()}
> >
<Table <Table

View File

@@ -4,7 +4,6 @@ import {useMutation, useQuery} from "@apollo/client";
import { import {
MUTATION_TOGGLE_TASK_COMPLETED, MUTATION_TOGGLE_TASK_COMPLETED,
MUTATION_TOGGLE_TASK_DELETED, MUTATION_TOGGLE_TASK_DELETED,
QUERY_MY_TASKS_PAGINATED
} from "../../graphql/tasks.queries.js"; } from "../../graphql/tasks.queries.js";
import {pageLimit} from "../../utils/config.js"; import {pageLimit} from "../../utils/config.js";
import AlertComponent from "../alert/alert.component.jsx"; import AlertComponent from "../alert/alert.component.jsx";
@@ -13,18 +12,18 @@ import TaskListComponent from "./task-list.component.jsx";
import {notification} from "antd"; import {notification} from "antd";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
export default function TaskListContainer({bodyshop, currentUser}) { export default function TaskListContainer({bodyshop, titleTranslation ,query, relationshipType, relationshipId}) {
const {t} = useTranslation(); const {t} = useTranslation();
const searchParams = queryString.parse(useLocation().search); const searchParams = queryString.parse(useLocation().search);
const {page, sortcolumn, sortorder, deleted, completed} = searchParams; const {page, sortcolumn, sortorder, deleted, completed} = searchParams;
const {loading, error, data, refetch} = useQuery( const {loading, error, data, refetch} = useQuery(
QUERY_MY_TASKS_PAGINATED, query,
{ {
fetchPolicy: "network-only", fetchPolicy: "network-only",
nextFetchPolicy: "network-only", nextFetchPolicy: "network-only",
variables: { variables: {
bodyshop: bodyshop.id, bodyshop: bodyshop.id,
user: currentUser.email, [relationshipType]: relationshipId,
deleted: deleted === 'true', deleted: deleted === 'true',
completed: completed === "true", completed: completed === "true",
offset: page ? (page - 1) * pageLimit : 0, offset: page ? (page - 1) * pageLimit : 0,
@@ -129,9 +128,12 @@ export default function TaskListContainer({bodyshop, currentUser}) {
loading={loading} loading={loading}
tasks={data ? data.tasks : null} tasks={data ? data.tasks : null}
total={data ? data.tasks_aggregate.aggregate.count : 0} total={data ? data.tasks_aggregate.aggregate.count : 0}
titleTranslation={t(titleTranslation || "tasks.title")}
refetch={refetch} refetch={refetch}
toggleCompletedStatus={toggleCompletedStatus} toggleCompletedStatus={toggleCompletedStatus}
toggleDeletedStatus={toggleDeletedStatus} toggleDeletedStatus={toggleDeletedStatus}
relationshipType={relationshipType}
relationshipId={relationshipId}
/> />
); );
} }

View File

@@ -62,7 +62,7 @@ export function TaskUpsertModalComponent({
}; };
if (!data || loading || error) return <LoadingSkeleton active/>; if (loading || error) return <LoadingSkeleton active/>;
return ( return (
<> <>
@@ -115,7 +115,7 @@ export function TaskUpsertModalComponent({
<Col span={24}> <Col span={24}>
<Form.Item <Form.Item
name="jobid" name="jobid"
// initialValue={selectedJobId} initialValue={selectedJobId}
label={t("tasks.fields.jobid")} label={t("tasks.fields.jobid")}
rules={[ rules={[
{ {

View File

@@ -32,7 +32,7 @@ export function TaskUpsertModalContainer({
const [updateTask] = useMutation(MUTATION_UPDATE_TASK); const [updateTask] = useMutation(MUTATION_UPDATE_TASK);
const {open, context, actions} = taskUpsert; const {open, context, actions} = taskUpsert;
const {jobId, existingTask} = context; const {jobid, existingTask, joblineid, billid, partsorderid} = context;
const {refetch} = actions; const {refetch} = actions;
const [form] = Form.useForm(); const [form] = Form.useForm();
const [selectedJobId, setSelectedJobId] = useState(null); const [selectedJobId, setSelectedJobId] = useState(null);
@@ -52,10 +52,10 @@ export function TaskUpsertModalContainer({
* Set the selected job id when the modal is opened and jobId is passed as a prop or when an existing task is passed as a prop * Set the selected job id when the modal is opened and jobId is passed as a prop or when an existing task is passed as a prop
*/ */
useEffect(() => { useEffect(() => {
if (jobId || existingTask?.id) { if (jobid || existingTask?.id) {
setSelectedJobId(jobId || existingTask.jobid); setSelectedJobId(jobid || existingTask.jobid);
} }
}, [jobId, existingTask]); }, [jobid, existingTask]);
/** /**
* Set the form values when the modal is opened and an existing task is passed as a prop * Set the form values when the modal is opened and an existing task is passed as a prop
@@ -65,9 +65,11 @@ export function TaskUpsertModalContainer({
form.setFieldsValue(existingTask); form.setFieldsValue(existingTask);
} else if (!existingTask && open) { } else if (!existingTask && open) {
form.resetFields(); form.resetFields();
if (joblineid) form.setFieldsValue({joblineid});
if (billid) form.setFieldsValue({billid});
if (partsorderid) form.setFieldsValue({partsorderid});
} }
}, [existingTask, form, open]); }, [existingTask, form, open, joblineid, billid, partsorderid]);
/** /**
* Set the job id state when the selected job id changes * Set the job id state when the selected job id changes
@@ -128,7 +130,7 @@ export function TaskUpsertModalContainer({
...values, ...values,
created_by: currentUser.email, created_by: currentUser.email,
bodyshopid: bodyshop.id bodyshopid: bodyshop.id
}, ...existingTasks] }, ...existingTasks]
}, },
}, },
}); });

View File

@@ -42,12 +42,214 @@ export const QUERY_ALL_TASKS_PAGINATED = gql`
} }
`; `;
/** const PARTIAL_TASK_FIELDS = gql`
* My tasks paginated query fragment TaskFields on tasks {
* @type {DocumentNode} id
*/ created_at
updated_at
title
description
deleted
deleted_at
due_date
created_by
assigned_to
completed
completed_at
remind_at
priority
job {
id
ro_number
joblines {
id
line_desc
}
bills {
id
vendor {
name
}
invoice_number
}
parts_orders {
id
vendor {
name
}
order_number
}
}
jobid
joblineid
partsorderid
billid
}
`;
// Query for joblineid
export const QUERY_JOBLINE_TASKS_PAGINATED = gql`
${PARTIAL_TASK_FIELDS}
query QUERY_JOBLINE_TASKS_PAGINATED(
$offset: Int
$limit: Int
$joblineid: uuid!
$bodyshop: uuid!
$deleted: Boolean
$completed: Boolean
$order: [tasks_order_by!]!
) {
tasks(
offset: $offset
limit: $limit
order_by: $order
where: {
joblineid: {_eq: $joblineid},
bodyshopid: {_eq: $bodyshop},
deleted: {_eq: $deleted},
completed: {_eq: $completed}
}
) {
...TaskFields
}
tasks_aggregate(
where: {
joblineid: {_eq: $joblineid},
bodyshopid: {_eq: $bodyshop},
deleted: {_eq: $deleted},
completed: {_eq: $completed}
}
) {
aggregate {
count
}
}
}
`;
// Query for partsorderid
export const QUERY_PARTSORDER_TASKS_PAGINATED = gql`
${PARTIAL_TASK_FIELDS}
query QUERY_PARTSORDER_TASKS_PAGINATED(
$offset: Int
$limit: Int
$partsorderid: uuid!
$bodyshop: uuid!
$deleted: Boolean
$completed: Boolean
$order: [tasks_order_by!]!
) {
tasks(
offset: $offset
limit: $limit
order_by: $order
where: {
partsorderid: {_eq: $partsorderid},
bodyshopid: {_eq: $bodyshop},
deleted: {_eq: $deleted},
completed: {_eq: $completed}
}
) {
...TaskFields
}
tasks_aggregate(
where: {
partsorderid: {_eq: $partsorderid},
bodyshopid: {_eq: $bodyshop},
deleted: {_eq: $deleted},
completed: {_eq: $completed}
}
) {
aggregate {
count
}
}
}
`;
// Query for billid
export const QUERY_BILL_TASKS_PAGINATED = gql`
${PARTIAL_TASK_FIELDS}
query QUERY_BILL_TASKS_PAGINATED(
$offset: Int
$limit: Int
$billid: uuid!
$bodyshop: uuid!
$deleted: Boolean
$completed: Boolean
$order: [tasks_order_by!]!
) {
tasks(
offset: $offset
limit: $limit
order_by: $order
where: {
billid: {_eq: $billid},
bodyshopid: {_eq: $bodyshop},
deleted: {_eq: $deleted},
completed: {_eq: $completed}
}
) {
...TaskFields
}
tasks_aggregate(
where: {
billid: {_eq: $billid},
bodyshopid: {_eq: $bodyshop},
deleted: {_eq: $deleted},
completed: {_eq: $completed}
}
) {
aggregate {
count
}
}
}
`;
// Use the fragment in your queries
export const QUERY_JOB_TASKS_PAGINATED = gql`
${PARTIAL_TASK_FIELDS}
query QUERY_JOB_TASKS_PAGINATED(
$offset: Int
$limit: Int
$jobid: uuid!
$bodyshop: uuid!
$deleted: Boolean
$completed: Boolean
$order: [tasks_order_by!]!
) {
tasks(
offset: $offset
limit: $limit
order_by: $order
where: {
jobid: {_eq: $jobid},
bodyshopid: {_eq: $bodyshop},
deleted: {_eq: $deleted},
completed: {_eq: $completed}
}
) {
...TaskFields
}
tasks_aggregate(
where: {
jobid: {_eq: $jobid},
bodyshopid: {_eq: $bodyshop},
deleted: {_eq: $deleted},
completed: {_eq: $completed}
}
) {
aggregate {
count
}
}
}
`;
export const QUERY_MY_TASKS_PAGINATED = gql` export const QUERY_MY_TASKS_PAGINATED = gql`
query QUERY_TASKS_PAGINATED( ${PARTIAL_TASK_FIELDS}
query QUERY_MY_TASKS_PAGINATED(
$offset: Int $offset: Int
$limit: Int $limit: Int
$user: String! $user: String!
@@ -67,46 +269,7 @@ export const QUERY_MY_TASKS_PAGINATED = gql`
completed: {_eq: $completed} completed: {_eq: $completed}
} }
) { ) {
id ...TaskFields
created_at
updated_at
title
description
deleted
deleted_at
due_date
created_by
assigned_to
completed
completed_at
remind_at
priority
job {
id
ro_number
joblines {
id
line_desc
}
bills {
id
vendor {
name
}
invoice_number
}
parts_orders {
id
vendor {
name
}
order_number
}
}
jobid
joblineid
partsorderid
billid
} }
tasks_aggregate( tasks_aggregate(
where: { where: {

View File

@@ -16,7 +16,7 @@ import dayjs from "../../utils/day";
import queryString from "query-string"; import queryString from "query-string";
import React, {useEffect, useState} from "react"; import React, {useEffect, useState} from "react";
import {useTranslation} from "react-i18next"; import {useTranslation} from "react-i18next";
import {FaHardHat, FaRegStickyNote, FaShieldAlt} from "react-icons/fa"; import {FaHardHat, FaRegStickyNote, FaShieldAlt, FaTasks} from "react-icons/fa";
import {connect} from "react-redux"; import {connect} from "react-redux";
import {useLocation, useNavigate} from "react-router-dom"; import {useLocation, useNavigate} from "react-router-dom";
import {createStructuredSelector} from "reselect"; import {createStructuredSelector} from "reselect";
@@ -54,6 +54,8 @@ import JobProfileDataWarning from "../../components/job-profile-data-warning/job
import {DateTimeFormat} from "../../utils/DateFormatter"; import {DateTimeFormat} from "../../utils/DateFormatter";
import InstanceRenderManager from "../../utils/instanceRenderMgr"; import InstanceRenderManager from "../../utils/instanceRenderMgr";
import { HasFeatureAccess } from "../../components/feature-wrapper/feature-wrapper.component"; import { HasFeatureAccess } from "../../components/feature-wrapper/feature-wrapper.component";
import TaskListContainer from "../../components/task-list/task-list.container.jsx";
import {QUERY_JOB_TASKS_PAGINATED} from "../../graphql/tasks.queries.js";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -376,6 +378,12 @@ export function JobsDetailPage({
label: t("jobs.labels.audit"), label: t("jobs.labels.audit"),
children: <JobAuditTrail jobId={job.id}/>, children: <JobAuditTrail jobId={job.id}/>,
}, },
{
key: 'tasks',
icon: <FaTasks/>,
label: t("menus.jobsdetail.tasks"),
children: <TaskListContainer bodyshop={bodyshop} relationshipType={'jobid'} relationshipId={job.id} query={QUERY_JOB_TASKS_PAGINATED} titleTranslation='tasks.titles.job_tasks'/>
},
]} ]}
/> />
</Form> </Form>

View File

@@ -1,11 +1,13 @@
import React from "react"; import React from "react";
import TaskListContainer from "../../components/task-list/task-list.container.jsx"; import TaskListContainer from "../../components/task-list/task-list.container.jsx";
import {QUERY_MY_TASKS_PAGINATED} from "../../graphql/tasks.queries.js";
export default function TasksPageComponent({bodyshop, currentUser}) { export default function TasksPageComponent({bodyshop, currentUser}) {
return ( return (
<div> <div>
<TaskListContainer bodyshop={bodyshop} currentUser={currentUser} /> <TaskListContainer relationshipId={currentUser.email} relationshipType={'user'} query={QUERY_MY_TASKS_PAGINATED} bodyshop={bodyshop} titleTranslation={'tasks.titles.my_tasks'}
currentUser={currentUser}/>
</div> </div>
); );
} }

View File

@@ -2120,6 +2120,8 @@
"edit": "Edit Task" "edit": "Edit Task"
}, },
"titles": { "titles": {
"job_tasks": "Job Tasks",
"my_tasks": "My Tasks",
"completed": "Completed Tasks", "completed": "Completed Tasks",
"deleted": "Deleted Tasks" "deleted": "Deleted Tasks"
}, },