@@ -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 (
|
||||
<Card
|
||||
title={t("menus.header.my_tasks")}
|
||||
title={titleTranslation}
|
||||
extra={tasksExtra()}
|
||||
>
|
||||
<Table
|
||||
|
||||
@@ -4,7 +4,6 @@ import {useMutation, useQuery} from "@apollo/client";
|
||||
import {
|
||||
MUTATION_TOGGLE_TASK_COMPLETED,
|
||||
MUTATION_TOGGLE_TASK_DELETED,
|
||||
QUERY_MY_TASKS_PAGINATED
|
||||
} from "../../graphql/tasks.queries.js";
|
||||
import {pageLimit} from "../../utils/config.js";
|
||||
import AlertComponent from "../alert/alert.component.jsx";
|
||||
@@ -13,18 +12,18 @@ import TaskListComponent from "./task-list.component.jsx";
|
||||
import {notification} from "antd";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
export default function TaskListContainer({bodyshop, currentUser}) {
|
||||
export default function TaskListContainer({bodyshop, titleTranslation ,query, relationshipType, relationshipId}) {
|
||||
const {t} = useTranslation();
|
||||
const searchParams = queryString.parse(useLocation().search);
|
||||
const {page, sortcolumn, sortorder, deleted, completed} = searchParams;
|
||||
const {loading, error, data, refetch} = useQuery(
|
||||
QUERY_MY_TASKS_PAGINATED,
|
||||
query,
|
||||
{
|
||||
fetchPolicy: "network-only",
|
||||
nextFetchPolicy: "network-only",
|
||||
variables: {
|
||||
bodyshop: bodyshop.id,
|
||||
user: currentUser.email,
|
||||
[relationshipType]: relationshipId,
|
||||
deleted: deleted === 'true',
|
||||
completed: completed === "true",
|
||||
offset: page ? (page - 1) * pageLimit : 0,
|
||||
@@ -129,9 +128,12 @@ export default function TaskListContainer({bodyshop, currentUser}) {
|
||||
loading={loading}
|
||||
tasks={data ? data.tasks : null}
|
||||
total={data ? data.tasks_aggregate.aggregate.count : 0}
|
||||
titleTranslation={t(titleTranslation || "tasks.title")}
|
||||
refetch={refetch}
|
||||
toggleCompletedStatus={toggleCompletedStatus}
|
||||
toggleDeletedStatus={toggleDeletedStatus}
|
||||
relationshipType={relationshipType}
|
||||
relationshipId={relationshipId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 <LoadingSkeleton active/>;
|
||||
|
||||
if (loading || error) return <LoadingSkeleton active/>;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -115,7 +115,7 @@ export function TaskUpsertModalComponent({
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
name="jobid"
|
||||
// initialValue={selectedJobId}
|
||||
initialValue={selectedJobId}
|
||||
label={t("tasks.fields.jobid")}
|
||||
rules={[
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ export function TaskUpsertModalContainer({
|
||||
const [updateTask] = useMutation(MUTATION_UPDATE_TASK);
|
||||
|
||||
const {open, context, actions} = taskUpsert;
|
||||
const {jobId, existingTask} = context;
|
||||
const {jobid, existingTask, joblineid, billid, partsorderid} = context;
|
||||
const {refetch} = actions;
|
||||
const [form] = Form.useForm();
|
||||
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
|
||||
*/
|
||||
useEffect(() => {
|
||||
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]
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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: <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>
|
||||
|
||||
@@ -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 (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2120,6 +2120,8 @@
|
||||
"edit": "Edit Task"
|
||||
},
|
||||
"titles": {
|
||||
"job_tasks": "Job Tasks",
|
||||
"my_tasks": "My Tasks",
|
||||
"completed": "Completed Tasks",
|
||||
"deleted": "Deleted Tasks"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user