@@ -145,7 +145,7 @@ function TaskListComponent({
|
||||
key: "priority",
|
||||
sorter: true,
|
||||
sortOrder: sortcolumn === "priority" && sortorder,
|
||||
width: '5%',
|
||||
width: '8%',
|
||||
render: (text, record) => <PriorityLabel priority={record.priority}
|
||||
/>
|
||||
},
|
||||
@@ -157,7 +157,6 @@ function TaskListComponent({
|
||||
<Space direction='horizontal'>
|
||||
<Button title={t('tasks.buttons.edit')} onClick={() => {
|
||||
setTaskUpsertContext({
|
||||
actions: {},
|
||||
context: {
|
||||
existingTask: record,
|
||||
},
|
||||
|
||||
@@ -2,15 +2,19 @@ import queryString from "query-string";
|
||||
import {useLocation} from "react-router-dom";
|
||||
import {useMutation, useQuery} from "@apollo/client";
|
||||
import {
|
||||
MUTATION_TOGGLE_TASK_COMPLETED, MUTATION_TOGGLE_TASK_DELETED,
|
||||
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";
|
||||
import React, {useEffect} from "react";
|
||||
import TaskListComponent from "./task-list.component.jsx";
|
||||
import {notification} from "antd";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
export default function TaskListContainer({bodyshop, currentUser}) {
|
||||
const {t} = useTranslation();
|
||||
const searchParams = queryString.parse(useLocation().search);
|
||||
const {page, sortcolumn, sortorder, deleted, completed} = searchParams;
|
||||
const {loading, error, data, refetch} = useQuery(
|
||||
@@ -45,7 +49,8 @@ export default function TaskListContainer({bodyshop, currentUser}) {
|
||||
const handleTaskUpdated = () => {
|
||||
refetch().catch((e) => {
|
||||
console.error(`Something went wrong fetching tasks: ${e.message || ''}`);
|
||||
}); };
|
||||
});
|
||||
};
|
||||
}, [refetch]);
|
||||
|
||||
/**
|
||||
@@ -61,16 +66,26 @@ export default function TaskListContainer({bodyshop, currentUser}) {
|
||||
*/
|
||||
const toggleCompletedStatus = async (id, currentStatus) => {
|
||||
const completed_at = !currentStatus ? new Date().toISOString() : null;
|
||||
await toggleTaskCompleted({
|
||||
variables: {
|
||||
id: id,
|
||||
completed: !currentStatus,
|
||||
completed_at: completed_at
|
||||
}
|
||||
});
|
||||
refetch().catch((e) => {
|
||||
console.error(`Something went wrong fetching tasks: ${e.message || ''}`);
|
||||
}); };
|
||||
try {
|
||||
await toggleTaskCompleted({
|
||||
variables: {
|
||||
id: id,
|
||||
completed: !currentStatus,
|
||||
completed_at: completed_at
|
||||
}
|
||||
});
|
||||
refetch().catch((e) => {
|
||||
console.error(`Something went wrong fetching tasks: ${e.message || ''}`);
|
||||
});
|
||||
notification["success"]({
|
||||
message: t("tasks.successes.completed"),
|
||||
});
|
||||
} catch (err) {
|
||||
notification["error"]({
|
||||
message: t("tasks.failures.completed"),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle task deleted mutation
|
||||
@@ -85,20 +100,30 @@ export default function TaskListContainer({bodyshop, currentUser}) {
|
||||
*/
|
||||
const toggleDeletedStatus = async (id, currentStatus) => {
|
||||
const deleted_at = !currentStatus ? new Date().toISOString() : null;
|
||||
await toggleTaskDeleted({
|
||||
variables: {
|
||||
id: id,
|
||||
deleted: !currentStatus,
|
||||
deleted_at: deleted_at
|
||||
}
|
||||
});
|
||||
refetch().catch((e) => {
|
||||
console.error(`Something went wrong fetching tasks: ${e.message || ''}`);
|
||||
});
|
||||
try {
|
||||
await toggleTaskDeleted({
|
||||
variables: {
|
||||
id: id,
|
||||
deleted: !currentStatus,
|
||||
deleted_at: deleted_at
|
||||
}
|
||||
});
|
||||
refetch().catch((e) => {
|
||||
console.error(`Something went wrong fetching tasks: ${e.message || ''}`);
|
||||
});
|
||||
notification["success"]({
|
||||
message: t("tasks.successes.deleted"),
|
||||
});
|
||||
} catch (err) {
|
||||
notification["error"]({
|
||||
message: t("tasks.failures.deleted"),
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if (error) return <AlertComponent message={error.message} type="error"/>;
|
||||
|
||||
|
||||
return (
|
||||
<TaskListComponent
|
||||
loading={loading}
|
||||
|
||||
@@ -8,6 +8,7 @@ import dayjs from '../../utils/day';
|
||||
|
||||
import {connect} from "react-redux";
|
||||
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component.jsx";
|
||||
import JobSearchSelectComponent from "../job-search-select/job-search-select.component.jsx";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -41,8 +42,27 @@ 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')},
|
||||
];
|
||||
|
||||
if (loading || error) return <LoadingSkeleton active/>;
|
||||
|
||||
const clearRelations = () => {
|
||||
form.setFieldsValue({
|
||||
billid: null,
|
||||
partsorderid: null,
|
||||
joblineid: null
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the selected job id
|
||||
* @param jobId
|
||||
*/
|
||||
const changeJobId = (jobId) => {
|
||||
setSelectedJobId(jobId || null);
|
||||
// Reset the form fields when selectedJobId changes
|
||||
clearRelations();
|
||||
};
|
||||
|
||||
|
||||
if (!data || loading || error) return <LoadingSkeleton active/>;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -80,20 +100,95 @@ export function TaskUpsertModalComponent({
|
||||
label={t("tasks.fields.completed")}
|
||||
name="completed"
|
||||
valuePropName="checked"
|
||||
initialValue={false}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Switch/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
name="jobid"
|
||||
// initialValue={selectedJobId}
|
||||
label={t("tasks.fields.jobid")}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<JobSearchSelectComponent placeholder={t('tasks.placeholders.jobid')}
|
||||
onSelect={changeJobId} onClear={changeJobId}/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
label={t("tasks.fields.joblineid")}
|
||||
name="joblineid"
|
||||
>
|
||||
<Select allowClear placeholder={t("tasks.placeholders.joblineid")}
|
||||
disabled={!selectedJobDetails || !selectedJobId}>
|
||||
{selectedJobDetails?.joblines?.map((jobline) => (
|
||||
<Select.Option key={jobline.id} value={jobline.id}>
|
||||
{jobline.line_desc}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
label={t("tasks.fields.partsorderid")}
|
||||
name="partsorderid"
|
||||
>
|
||||
<Select allowClear placeholder={t("tasks.placeholders.partsorderid")}
|
||||
disabled={!selectedJobDetails || !selectedJobId}>
|
||||
{selectedJobDetails?.parts_orders?.map((partsOrder) => (
|
||||
<Select.Option key={partsOrder.id} value={partsOrder.id}>
|
||||
{partsOrder.order_number} - {partsOrder.vendor.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
label={t("tasks.fields.billid")}
|
||||
name="billid"
|
||||
>
|
||||
<Select allowClear placeholder={t("tasks.placeholders.billid")}
|
||||
disabled={!selectedJobDetails || !selectedJobId}>
|
||||
{selectedJobDetails?.bills?.map((bill) => (
|
||||
<Select.Option key={bill.id} value={bill.id}>
|
||||
{bill.invoice_number} - {bill.vendor.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
label={t("tasks.fields.assigned_to")}
|
||||
name="assigned_to"
|
||||
initialValue={currentUser.email}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Select placeholder={t("tasks.labels.selectemployee")}>
|
||||
{bodyshop.employees.map((employee) => (
|
||||
{bodyshop.employees.filter(x => x.active).map((employee) => (
|
||||
<Select.Option key={employee.id} value={employee.user_email}>
|
||||
{employee.first_name} {employee.last_name}
|
||||
</Select.Option>
|
||||
@@ -131,71 +226,6 @@ export function TaskUpsertModalComponent({
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<Form.Item
|
||||
name="jobid"
|
||||
label={t("tasks.fields.jobid")}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},1
|
||||
]}
|
||||
>
|
||||
<Select placeholder={t('tasks.placeholders.jobid')} defaultValue={selectedJobId} onSelect={setSelectedJobId}>
|
||||
{data.jobs.map((job) => (
|
||||
<Select.Option key={job.id} value={job.id}>
|
||||
{job.ro_number}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
label={t("tasks.fields.joblineid")}
|
||||
name="joblineid"
|
||||
>
|
||||
<Select placeholder={t("tasks.placeholders.joblineid")} disabled={!selectedJobDetails}>
|
||||
{selectedJobDetails?.joblines?.map((jobline) => (
|
||||
<Select.Option key={jobline.id} value={jobline.id}>
|
||||
{jobline.line_desc}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
label={t("tasks.fields.partsorderid")}
|
||||
name="partsorderid"
|
||||
>
|
||||
<Select placeholder={t("tasks.placeholders.partsorderid")} disabled={!selectedJobDetails}>
|
||||
{selectedJobDetails?.parts_orders?.map((partsOrder) => (
|
||||
<Select.Option key={partsOrder.id} value={partsOrder.id}>
|
||||
{partsOrder.order_number} - {partsOrder.vendor.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
label={t("tasks.fields.billid")}
|
||||
name="billid"
|
||||
>
|
||||
<Select placeholder={t("tasks.placeholders.billid")} disabled={!selectedJobDetails}>
|
||||
{selectedJobDetails?.bills?.map((bill) => (
|
||||
<Select.Option key={bill.id} value={bill.id}>
|
||||
{bill.invoice_number} - {bill.vendor.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,14 +5,12 @@ import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {MUTATION_INSERT_NEW_TASK, MUTATION_UPDATE_TASK} from "../../graphql/tasks.queries";
|
||||
import {
|
||||
QUERY_GET_TASKS_JOB_DETAILS,
|
||||
QUERY_GET_TASKS_JOB_DETAILS_BY_ID
|
||||
} from "../../graphql/jobs.queries.js";
|
||||
import {QUERY_GET_TASKS_JOB_DETAILS_BY_ID} from "../../graphql/jobs.queries.js";
|
||||
import {toggleModalVisible} from "../../redux/modals/modals.actions";
|
||||
import {selectTaskUpsert} from "../../redux/modals/modals.selectors";
|
||||
import {selectBodyshop, selectCurrentUser} from "../../redux/user/user.selectors";
|
||||
import TaskUpsertModalComponent from "./task-upsert-modal.component";
|
||||
import {replaceUndefinedWithNull} from "../../utils/undefinedtonull.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
@@ -41,16 +39,14 @@ export function TaskUpsertModalContainer({
|
||||
const [selectedJobDetails, setSelectedJobDetails] = useState(null);
|
||||
const [jobIdState, setJobIdState] = useState(null);
|
||||
|
||||
|
||||
const {
|
||||
loading: jobDetailsLoading,
|
||||
error: jobDetailsError,
|
||||
data: jobDetailsData
|
||||
loading: loading,
|
||||
error: error,
|
||||
data: data
|
||||
} = useQuery(QUERY_GET_TASKS_JOB_DETAILS_BY_ID, {
|
||||
variables: {id: jobIdState},
|
||||
skip: !jobIdState, // Skip the query if jobIdState is null
|
||||
skip: !jobIdState,
|
||||
});
|
||||
const {loading, error, data} = useQuery(QUERY_GET_TASKS_JOB_DETAILS);
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -72,16 +68,6 @@ export function TaskUpsertModalContainer({
|
||||
}
|
||||
}, [existingTask, form, open]);
|
||||
|
||||
/**
|
||||
* Reset the form values when the selected job id changes
|
||||
*/
|
||||
useEffect(() => {
|
||||
form.setFieldsValue({
|
||||
joblineid: undefined,
|
||||
billid: undefined,
|
||||
partsorderid: undefined,
|
||||
});
|
||||
}, [selectedJobId, form]);
|
||||
|
||||
/**
|
||||
* Set the job id state when the selected job id changes
|
||||
@@ -97,10 +83,11 @@ export function TaskUpsertModalContainer({
|
||||
* Set the selected job details when the job details query is successful
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!jobDetailsLoading && !jobDetailsError && jobDetailsData) {
|
||||
setSelectedJobDetails(jobDetailsData.jobs_by_pk);
|
||||
if (!loading && !error && data) {
|
||||
setSelectedJobDetails(data.jobs_by_pk);
|
||||
}
|
||||
}, [jobDetailsLoading, jobDetailsError, jobDetailsData]);
|
||||
}, [loading, error, data]);
|
||||
|
||||
|
||||
/**
|
||||
* Handle the form submit
|
||||
@@ -109,13 +96,11 @@ export function TaskUpsertModalContainer({
|
||||
*/
|
||||
const handleFinish = async (formValues) => {
|
||||
const {...values} = formValues;
|
||||
|
||||
if (existingTask) {
|
||||
await updateTask({
|
||||
variables: {
|
||||
taskId: existingTask.id,
|
||||
task: values,
|
||||
jobid: selectedJobId,
|
||||
task: replaceUndefinedWithNull(values)
|
||||
},
|
||||
});
|
||||
|
||||
@@ -128,19 +113,19 @@ export function TaskUpsertModalContainer({
|
||||
await insertTask({
|
||||
variables: {
|
||||
taskInput: [
|
||||
{...values, jobid: selectedJobId, created_by: currentUser.email, bodyshopid: bodyshop.id},
|
||||
{
|
||||
...replaceUndefinedWithNull(values),
|
||||
created_by: currentUser.email,
|
||||
bodyshopid: bodyshop.id
|
||||
},
|
||||
],
|
||||
},
|
||||
updateQueries: {
|
||||
query: QUERY_GET_TASKS_JOB_DETAILS,
|
||||
},
|
||||
update(cache) {
|
||||
cache.modify({
|
||||
fields: {
|
||||
tasks(existingTasks) {
|
||||
return [{
|
||||
...values,
|
||||
jobid: selectedJobId,
|
||||
created_by: currentUser.email,
|
||||
bodyshopid: bodyshop.id
|
||||
}, ...existingTasks]
|
||||
@@ -154,7 +139,7 @@ export function TaskUpsertModalContainer({
|
||||
form.resetFields();
|
||||
toggleModalVisible();
|
||||
notification["success"]({
|
||||
message: t("tasks.successes.create"),
|
||||
message: t("tasks.successes.created"),
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -176,7 +161,7 @@ export function TaskUpsertModalContainer({
|
||||
>
|
||||
<Form form={form} onFinish={handleFinish} layout="vertical">
|
||||
<TaskUpsertModalComponent form={form} loading={loading} error={error} data={data}
|
||||
selectedJobId={setSelectedJobId}
|
||||
selectedJobId={selectedJobId}
|
||||
setSelectedJobId={setSelectedJobId}
|
||||
selectedJobDetails={selectedJobDetails}/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user