diff --git a/client/src/components/task-list/task-list.component.jsx b/client/src/components/task-list/task-list.component.jsx index 7ea01aca0..8a63a8ede 100644 --- a/client/src/components/task-list/task-list.component.jsx +++ b/client/src/components/task-list/task-list.component.jsx @@ -84,10 +84,13 @@ function TaskListComponent({ loading, tasks, total, + titleTranslation, refetch, toggleCompletedStatus, setTaskUpsertContext, - toggleDeletedStatus + toggleDeletedStatus, + relationshipType, + relationshipId }) { const {t} = useTranslation(); @@ -186,7 +189,9 @@ function TaskListComponent({ const handleCreateTask = () => { setTaskUpsertContext({ actions: {}, - context: {}, + context: { + [relationshipType]: relationshipId, + }, }); }; @@ -241,7 +246,7 @@ function TaskListComponent({ return ( ); } diff --git a/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx b/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx index 3f60b1d41..b84d15579 100644 --- a/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx +++ b/client/src/components/task-upsert-modal/task-upsert-modal.component.jsx @@ -42,7 +42,7 @@ export function TaskUpsertModalComponent({ {label: t('tasks.date_presets.three_weeks'), value: dayjs().add(3, 'weeks')}, {label: t('tasks.date_presets.one_month'), value: dayjs().add(1, 'month')}, ]; - + const clearRelations = () => { form.setFieldsValue({ billid: null, @@ -61,8 +61,8 @@ export function TaskUpsertModalComponent({ clearRelations(); }; - - if (!data || loading || error) return ; + + if (loading || error) return ; return ( <> @@ -115,7 +115,7 @@ export function TaskUpsertModalComponent({ { - if (jobId || existingTask?.id) { - setSelectedJobId(jobId || existingTask.jobid); + if (jobid || existingTask?.id) { + 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 @@ -65,9 +65,11 @@ export function TaskUpsertModalContainer({ form.setFieldsValue(existingTask); } else if (!existingTask && open) { 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 @@ -125,10 +127,10 @@ export function TaskUpsertModalContainer({ fields: { tasks(existingTasks) { return [{ - ...values, + ...values, created_by: currentUser.email, bodyshopid: bodyshop.id - }, ...existingTasks] + }, ...existingTasks] }, }, }); diff --git a/client/src/graphql/tasks.queries.js b/client/src/graphql/tasks.queries.js index d19b70315..525cc4ae0 100644 --- a/client/src/graphql/tasks.queries.js +++ b/client/src/graphql/tasks.queries.js @@ -42,12 +42,214 @@ export const QUERY_ALL_TASKS_PAGINATED = gql` } `; -/** - * My tasks paginated query - * @type {DocumentNode} - */ +const PARTIAL_TASK_FIELDS = gql` + fragment TaskFields on tasks { + 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` - query QUERY_TASKS_PAGINATED( + ${PARTIAL_TASK_FIELDS} + query QUERY_MY_TASKS_PAGINATED( $offset: Int $limit: Int $user: String! @@ -67,46 +269,7 @@ export const QUERY_MY_TASKS_PAGINATED = gql` completed: {_eq: $completed} } ) { - 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 + ...TaskFields } tasks_aggregate( where: { diff --git a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx index 1027001f4..a6b684e88 100644 --- a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx +++ b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx @@ -16,7 +16,7 @@ import dayjs from "../../utils/day"; import queryString from "query-string"; import React, {useEffect, useState} from "react"; 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 {useLocation, useNavigate} from "react-router-dom"; import {createStructuredSelector} from "reselect"; @@ -54,6 +54,8 @@ import JobProfileDataWarning from "../../components/job-profile-data-warning/job import {DateTimeFormat} from "../../utils/DateFormatter"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; 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({ bodyshop: selectBodyshop, @@ -376,6 +378,12 @@ export function JobsDetailPage({ label: t("jobs.labels.audit"), children: , }, + { + key: 'tasks', + icon: , + label: t("menus.jobsdetail.tasks"), + children: + }, ]} /> diff --git a/client/src/pages/tasks/tasks.page.component.jsx b/client/src/pages/tasks/tasks.page.component.jsx index 253bc9c4c..34cff9fc3 100644 --- a/client/src/pages/tasks/tasks.page.component.jsx +++ b/client/src/pages/tasks/tasks.page.component.jsx @@ -1,11 +1,13 @@ import React from "react"; 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}) { return (
- +
); } diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index e8c6ea50b..aedcbdc52 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -2120,6 +2120,8 @@ "edit": "Edit Task" }, "titles": { + "job_tasks": "Job Tasks", + "my_tasks": "My Tasks", "completed": "Completed Tasks", "deleted": "Deleted Tasks" },