- additional cleanup and validation / fixes
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -163,7 +163,7 @@ function TaskListComponent({
|
|||||||
width: "8%",
|
width: "8%",
|
||||||
render: (text, record) =>
|
render: (text, record) =>
|
||||||
record.job ? (
|
record.job ? (
|
||||||
<Link to={`/manage/jobs/${record.job.id}`}>{record.job.ro_number || t("general.labels.na")}</Link>
|
<Link to={`/manage/jobs/${record.job.id}?tab=tasks`}>{record.job.ro_number || t("general.labels.na")}</Link>
|
||||||
) : (
|
) : (
|
||||||
t("general.labels.na")
|
t("general.labels.na")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -27,12 +27,13 @@ export function TaskUpsertModalComponent({
|
|||||||
selectedJobId,
|
selectedJobId,
|
||||||
setSelectedJobId,
|
setSelectedJobId,
|
||||||
selectedJobDetails,
|
selectedJobDetails,
|
||||||
|
existingTask,
|
||||||
loading,
|
loading,
|
||||||
error
|
error
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const datePickerPresets = [
|
const datePickerPresets = [
|
||||||
{ label: t("tasks.date_presets.today"), value: dayjs() },
|
{ label: t("tasks.date_presets.today"), value: dayjs().add(1, "hour") },
|
||||||
{ label: t("tasks.date_presets.tomorrow"), value: dayjs().add(1, "day") },
|
{ label: t("tasks.date_presets.tomorrow"), value: dayjs().add(1, "day") },
|
||||||
{ label: t("tasks.date_presets.next_week"), value: dayjs().add(1, "week") },
|
{ label: t("tasks.date_presets.next_week"), value: dayjs().add(1, "week") },
|
||||||
{ label: t("tasks.date_presets.two_weeks"), value: dayjs().add(2, "weeks") },
|
{ label: t("tasks.date_presets.two_weeks"), value: dayjs().add(2, "weeks") },
|
||||||
@@ -195,11 +196,38 @@ export function TaskUpsertModalComponent({
|
|||||||
</Col>
|
</Col>
|
||||||
<Col span={8}>
|
<Col span={8}>
|
||||||
<Form.Item label={t("tasks.fields.due_date")} name="due_date">
|
<Form.Item label={t("tasks.fields.due_date")} name="due_date">
|
||||||
<FormDatePicker onlyFuture format="MM/DD/YYYY" presets={datePickerPresets} />
|
<FormDatePicker
|
||||||
|
onlyFuture
|
||||||
|
format="MM/DD/YYYY"
|
||||||
|
presets={datePickerPresets}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
validator: (_, value) => {
|
||||||
|
if (!value || existingTask?.due_date === value || dayjs(value).isAfter(dayjs())) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(t("tasks.validation.due_at_error_message")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={8}>
|
<Col span={8}>
|
||||||
<Form.Item label={t("tasks.fields.remind_at")} name="remind_at">
|
<Form.Item
|
||||||
|
label={t("tasks.fields.remind_at")}
|
||||||
|
name="remind_at"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
validator: (_, value) => {
|
||||||
|
if (!value || existingTask?.remind_at === value || dayjs(value).isAfter(dayjs().add(30, "minute"))) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(t("tasks.validation.remind_at_error_message")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
>
|
||||||
<FormDateTimePickerEnhanced onlyFuture showTime minuteStep={15} presets={datePickerPresets} />
|
<FormDateTimePickerEnhanced onlyFuture showTime minuteStep={15} presets={datePickerPresets} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import axios from "axios";
|
|||||||
import dayjs from "../../utils/day";
|
import dayjs from "../../utils/day";
|
||||||
import { insertAuditTrail } from "../../redux/application/application.actions.js";
|
import { insertAuditTrail } from "../../redux/application/application.actions.js";
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings.js";
|
import AuditTrailMapping from "../../utils/AuditTrailMappings.js";
|
||||||
|
import { isEqual } from "lodash";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
currentUser: selectCurrentUser,
|
currentUser: selectCurrentUser,
|
||||||
@@ -33,13 +34,13 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to
|
|||||||
const history = useNavigate();
|
const history = useNavigate();
|
||||||
const [insertTask] = useMutation(MUTATION_INSERT_NEW_TASK);
|
const [insertTask] = useMutation(MUTATION_INSERT_NEW_TASK);
|
||||||
const [updateTask] = useMutation(MUTATION_UPDATE_TASK);
|
const [updateTask] = useMutation(MUTATION_UPDATE_TASK);
|
||||||
const { open, context, actions } = taskUpsert;
|
const { open, context } = taskUpsert;
|
||||||
const { jobid, joblineid, billid, partsorderid, taskId, existingTask, query } = context;
|
const { jobid, joblineid, billid, partsorderid, taskId, existingTask, query } = context;
|
||||||
const { refetch } = actions;
|
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [selectedJobId, setSelectedJobId] = useState(null);
|
const [selectedJobId, setSelectedJobId] = useState(null);
|
||||||
const [selectedJobDetails, setSelectedJobDetails] = useState(null);
|
const [selectedJobDetails, setSelectedJobDetails] = useState(null);
|
||||||
const [jobIdState, setJobIdState] = useState(null);
|
const [jobIdState, setJobIdState] = useState(null);
|
||||||
|
const [isTouched, setIsTouched] = useState(false);
|
||||||
|
|
||||||
const { loading, error, data } = useQuery(QUERY_GET_TASKS_JOB_DETAILS_BY_ID, {
|
const { loading, error, data } = useQuery(QUERY_GET_TASKS_JOB_DETAILS_BY_ID, {
|
||||||
variables: { id: jobIdState },
|
variables: { id: jobIdState },
|
||||||
@@ -91,6 +92,7 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to
|
|||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
setSelectedJobId(null);
|
setSelectedJobId(null);
|
||||||
|
setIsTouched(false);
|
||||||
};
|
};
|
||||||
}, [jobid, existingTask, form, open, joblineid, billid, partsorderid]);
|
}, [jobid, existingTask, form, open, joblineid, billid, partsorderid]);
|
||||||
|
|
||||||
@@ -164,8 +166,6 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to
|
|||||||
message: t("tasks.successes.updated")
|
message: t("tasks.successes.updated")
|
||||||
});
|
});
|
||||||
|
|
||||||
if (refetch) await refetch();
|
|
||||||
|
|
||||||
toggleModalVisible();
|
toggleModalVisible();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -181,19 +181,6 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
refetchQueries: ["GET_JOB_BY_PK"]
|
refetchQueries: ["GET_JOB_BY_PK"]
|
||||||
// update(cache, { data }) {
|
|
||||||
// cache.modify({
|
|
||||||
// fields: {
|
|
||||||
// tasks(cached) {
|
|
||||||
// const newTasks = data?.insert_tasks?.returning.map(task => cache.writeFragment({
|
|
||||||
// data: task,
|
|
||||||
// fragment: PARTIAL_TASK_FIELDS_WRAPPER
|
|
||||||
// }));
|
|
||||||
// return [...cached, ...newTasks];
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (query && Object.keys(query).length) {
|
if (query && Object.keys(query).length) {
|
||||||
@@ -213,8 +200,6 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refetch) await refetch();
|
|
||||||
|
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
toggleModalVisible();
|
toggleModalVisible();
|
||||||
|
|
||||||
@@ -253,12 +238,16 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to
|
|||||||
* @returns {Promise<[{jobid, bodyshopid, created_by},...*]>}
|
* @returns {Promise<[{jobid, bodyshopid, created_by},...*]>}
|
||||||
*/
|
*/
|
||||||
const handleFinish = async (formValues) => {
|
const handleFinish = async (formValues) => {
|
||||||
const { ...values } = formValues;
|
|
||||||
|
|
||||||
if (existingTask) {
|
if (existingTask) {
|
||||||
await handleExistingTask(values);
|
const dirtyValues = Object.keys(formValues).reduce((acc, key) => {
|
||||||
|
if (!isEqual(formValues[key], existingTask[key])) {
|
||||||
|
acc[key] = formValues[key];
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
await handleExistingTask(dirtyValues);
|
||||||
} else {
|
} else {
|
||||||
await handleNewTask(values);
|
await handleNewTask(formValues);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -276,14 +265,23 @@ export function TaskUpsertModalContainer({ bodyshop, currentUser, taskUpsert, to
|
|||||||
removeTaskIdFromUrl();
|
removeTaskIdFromUrl();
|
||||||
toggleModalVisible();
|
toggleModalVisible();
|
||||||
}}
|
}}
|
||||||
|
okButtonProps={{ disabled: !isTouched }}
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
>
|
>
|
||||||
<Form form={form} onFinish={handleFinish} layout="vertical">
|
<Form
|
||||||
|
form={form}
|
||||||
|
onFinish={handleFinish}
|
||||||
|
layout="vertical"
|
||||||
|
onFieldsChange={() => {
|
||||||
|
setIsTouched(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<TaskUpsertModalComponent
|
<TaskUpsertModalComponent
|
||||||
form={form}
|
form={form}
|
||||||
loading={loading || (taskId && taskLoading)}
|
loading={loading || (taskId && taskLoading)}
|
||||||
error={error}
|
error={error}
|
||||||
data={data}
|
data={data}
|
||||||
|
existingTask={existingTask}
|
||||||
selectedJobId={selectedJobId}
|
selectedJobId={selectedJobId}
|
||||||
setSelectedJobId={setSelectedJobId}
|
setSelectedJobId={setSelectedJobId}
|
||||||
selectedJobDetails={selectedJobDetails}
|
selectedJobDetails={selectedJobDetails}
|
||||||
|
|||||||
@@ -2224,6 +2224,10 @@
|
|||||||
"job": {
|
"job": {
|
||||||
"ro_number": "RO #"
|
"ro_number": "RO #"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"validation": {
|
||||||
|
"due_at_error_message": "The due date must be in the future!",
|
||||||
|
"remind_at_error_message": "The reminder date and time must be at least 30 minutes in the future!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"menus": {
|
"menus": {
|
||||||
|
|||||||
@@ -2223,6 +2223,10 @@
|
|||||||
"job": {
|
"job": {
|
||||||
"ro_number": ""
|
"ro_number": ""
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"validation": {
|
||||||
|
"due_at_error_message": "",
|
||||||
|
"remind_at_error_message": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"menus": {
|
"menus": {
|
||||||
|
|||||||
@@ -2223,6 +2223,10 @@
|
|||||||
"job": {
|
"job": {
|
||||||
"ro_number": ""
|
"ro_number": ""
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"validation": {
|
||||||
|
"due_at_error_message": "",
|
||||||
|
"remind_at_error_message": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"menus": {
|
"menus": {
|
||||||
|
|||||||
Reference in New Issue
Block a user