Compare commits
2 Commits
feature/IO
...
feature/IO
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d00fc29d1 | ||
|
|
a873a2573a |
@@ -33,7 +33,7 @@ import JobLinesBillRefernece from "../job-lines-bill-reference/job-lines-bill-re
|
||||
import { useTreatmentsWithConfig } from "@splitsoftware/splitio-react";
|
||||
import _ from "lodash";
|
||||
import { FaTasks } from "react-icons/fa";
|
||||
import { selectAuthLevel, selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import dayjs from "../../utils/day";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
|
||||
@@ -49,7 +49,6 @@ import JobLinesPartPriceChange from "./job-lines-part-price-change.component";
|
||||
import JobLinesExpanderSimple from "./jobs-lines-expander-simple.component";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import { HasRbacAccess } from "../rbac-wrapper/rbac-wrapper.component.jsx";
|
||||
|
||||
const UPDATE_JOB_LINES_LOCATION_BULK = gql`
|
||||
mutation UPDATE_JOB_LINES_LOCATION_BULK($ids: [uuid!]!, $location: String!) {
|
||||
@@ -67,8 +66,7 @@ const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
jobRO: selectJobReadOnly,
|
||||
technician: selectTechnician,
|
||||
isPartsEntry: selectIsPartsEntry,
|
||||
authLevel: selectAuthLevel
|
||||
isPartsEntry: selectIsPartsEntry
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
@@ -96,8 +94,7 @@ export function JobLinesComponent({
|
||||
setTaskUpsertContext,
|
||||
billsQuery,
|
||||
handlePartsOrderOnRowClick,
|
||||
isPartsEntry,
|
||||
authLevel
|
||||
isPartsEntry
|
||||
}) {
|
||||
const [deleteJobLine] = useMutation(DELETE_JOB_LINE_BY_PK);
|
||||
const [bulkUpdateLocations] = useMutation(UPDATE_JOB_LINES_LOCATION_BULK);
|
||||
@@ -389,20 +386,18 @@ export function JobLinesComponent({
|
||||
key: "actions",
|
||||
render: (text, record) => (
|
||||
<Space>
|
||||
{(record.manual_line || jobIsPrivate) &&
|
||||
!technician &&
|
||||
HasRbacAccess({ bodyshop, authLevel, action: "jobs:manual-line" }) && (
|
||||
<Button
|
||||
disabled={jobRO}
|
||||
onClick={() => {
|
||||
setJobLineEditContext({
|
||||
actions: { refetch: refetch, submit: form && form.submit },
|
||||
context: { ...record, jobid: job.id }
|
||||
});
|
||||
}}
|
||||
icon={<EditFilled />}
|
||||
/>
|
||||
)}
|
||||
{(record.manual_line || jobIsPrivate) && !technician && (
|
||||
<Button
|
||||
disabled={jobRO}
|
||||
onClick={() => {
|
||||
setJobLineEditContext({
|
||||
actions: { refetch: refetch, submit: form && form.submit },
|
||||
context: { ...record, jobid: job.id }
|
||||
});
|
||||
}}
|
||||
icon={<EditFilled />}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
title={t("tasks.buttons.create")}
|
||||
onClick={() => {
|
||||
@@ -415,30 +410,29 @@ export function JobLinesComponent({
|
||||
}}
|
||||
icon={<FaTasks />}
|
||||
/>
|
||||
{(record.manual_line || jobIsPrivate) &&
|
||||
!technician &&
|
||||
HasRbacAccess({ bodyshop, authLevel, action: "jobs:manual-line" }) && (
|
||||
<Button
|
||||
disabled={jobRO}
|
||||
onClick={async () => {
|
||||
await deleteJobLine({
|
||||
variables: { joblineId: record.id },
|
||||
update(cache) {
|
||||
cache.modify({
|
||||
fields: {
|
||||
joblines(existingJobLines, { readField }) {
|
||||
return existingJobLines.filter((jlRef) => record.id !== readField("id", jlRef));
|
||||
}
|
||||
|
||||
{(record.manual_line || jobIsPrivate) && !technician && (
|
||||
<Button
|
||||
disabled={jobRO}
|
||||
onClick={async () => {
|
||||
await deleteJobLine({
|
||||
variables: { joblineId: record.id },
|
||||
update(cache) {
|
||||
cache.modify({
|
||||
fields: {
|
||||
joblines(existingJobLines, { readField }) {
|
||||
return existingJobLines.filter((jlRef) => record.id !== readField("id", jlRef));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
await axios.post("/job/totalsssu", { id: job.id });
|
||||
if (refetch) refetch();
|
||||
}}
|
||||
icon={<DeleteFilled />}
|
||||
/>
|
||||
)}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
await axios.post("/job/totalsssu", { id: job.id });
|
||||
if (refetch) refetch();
|
||||
}}
|
||||
icon={<DeleteFilled />}
|
||||
/>
|
||||
)}
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
@@ -663,7 +657,7 @@ export function JobLinesComponent({
|
||||
<Button id="repair-data-mark-button">{t("jobs.actions.mark")}</Button>
|
||||
</Dropdown>
|
||||
|
||||
{!isPartsEntry && HasRbacAccess({ bodyshop, authLevel, action: "jobs:manual-line" }) && (
|
||||
{!isPartsEntry && (
|
||||
<Button
|
||||
disabled={jobRO || technician}
|
||||
onClick={() => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Icon from "@ant-design/icons";
|
||||
import { useMutation } from "@apollo/client/react";
|
||||
import { Button, Input, Popover, Tooltip } from "antd";
|
||||
import { useState } from "react";
|
||||
import { useState, useRef } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FaRegStickyNote } from "react-icons/fa";
|
||||
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||
@@ -9,10 +9,10 @@ import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
|
||||
export default function ProductionListColumnComment({ record, usePortal = false }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [note, setNote] = useState(record.comment || "");
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
const textAreaRef = useRef(null);
|
||||
const rafIdRef = useRef(null);
|
||||
|
||||
const [updateAlert] = useMutation(UPDATE_JOB);
|
||||
|
||||
@@ -38,23 +38,35 @@ export default function ProductionListColumnComment({ record, usePortal = false
|
||||
};
|
||||
|
||||
const handleOpenChange = (flag) => {
|
||||
if (rafIdRef.current) {
|
||||
cancelAnimationFrame(rafIdRef.current);
|
||||
rafIdRef.current = null;
|
||||
}
|
||||
setOpen(flag);
|
||||
if (flag) setNote(record.comment || "");
|
||||
if (flag) {
|
||||
setNote(record.comment || "");
|
||||
rafIdRef.current = requestAnimationFrame(() => {
|
||||
rafIdRef.current = null;
|
||||
if (textAreaRef.current?.focus) {
|
||||
try {
|
||||
textAreaRef.current.focus({ preventScroll: true });
|
||||
} catch {
|
||||
textAreaRef.current.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const content = (
|
||||
<div
|
||||
style={{ width: "30em" }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onPointerDown={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div style={{ width: "30em" }} onClick={(e) => e.stopPropagation()} onPointerDown={(e) => e.stopPropagation()}>
|
||||
<Input.TextArea
|
||||
id={`job-comment-${record.id}`}
|
||||
name="comment"
|
||||
rows={5}
|
||||
value={note}
|
||||
onChange={handleChange}
|
||||
autoFocus
|
||||
ref={textAreaRef}
|
||||
allowClear
|
||||
style={{ marginBottom: "1em" }}
|
||||
/>
|
||||
@@ -67,13 +79,13 @@ export default function ProductionListColumnComment({ record, usePortal = false
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover
|
||||
onOpenChange={handleOpenChange}
|
||||
open={open}
|
||||
content={content}
|
||||
trigger="click"
|
||||
<Popover
|
||||
onOpenChange={handleOpenChange}
|
||||
open={open}
|
||||
content={content}
|
||||
trigger="click"
|
||||
destroyOnHidden
|
||||
styles={{ body: { padding: '12px' } }}
|
||||
styles={{ body: { padding: "12px" } }}
|
||||
{...(usePortal ? { getPopupContainer: (trigger) => trigger.parentElement || document.body } : {})}
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Icon from "@ant-design/icons";
|
||||
import { useMutation } from "@apollo/client/react";
|
||||
import { Button, Input, Popover, Space } from "antd";
|
||||
import { useCallback, useState } from "react";
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FaRegStickyNote } from "react-icons/fa";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
@@ -20,6 +20,8 @@ function ProductionListColumnProductionNote({ record, setNoteUpsertContext, useP
|
||||
const { t } = useTranslation();
|
||||
const [note, setNote] = useState(record.production_vars?.note || "");
|
||||
const [open, setOpen] = useState(false);
|
||||
const textAreaRef = useRef(null);
|
||||
const rafIdRef = useRef(null);
|
||||
|
||||
const [updateAlert] = useMutation(UPDATE_JOB);
|
||||
|
||||
@@ -52,25 +54,37 @@ function ProductionListColumnProductionNote({ record, setNoteUpsertContext, useP
|
||||
|
||||
const handleOpenChange = useCallback(
|
||||
(flag) => {
|
||||
if (rafIdRef.current) {
|
||||
cancelAnimationFrame(rafIdRef.current);
|
||||
rafIdRef.current = null;
|
||||
}
|
||||
setOpen(flag);
|
||||
if (flag) setNote(record.production_vars?.note || "");
|
||||
if (flag) {
|
||||
setNote(record.production_vars?.note || "");
|
||||
rafIdRef.current = requestAnimationFrame(() => {
|
||||
rafIdRef.current = null;
|
||||
if (textAreaRef.current?.focus) {
|
||||
try {
|
||||
textAreaRef.current.focus({ preventScroll: true });
|
||||
} catch {
|
||||
textAreaRef.current.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
[record]
|
||||
);
|
||||
|
||||
const content = (
|
||||
<div
|
||||
style={{ width: "30em" }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onPointerDown={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div style={{ width: "30em" }} onClick={(e) => e.stopPropagation()} onPointerDown={(e) => e.stopPropagation()}>
|
||||
<Input.TextArea
|
||||
id={`job-production-note-${record.id}`}
|
||||
name="production_note"
|
||||
rows={5}
|
||||
value={note}
|
||||
onChange={handleChange}
|
||||
autoFocus
|
||||
ref={textAreaRef}
|
||||
allowClear
|
||||
style={{ marginBottom: "1em" }}
|
||||
/>
|
||||
@@ -96,13 +110,13 @@ function ProductionListColumnProductionNote({ record, setNoteUpsertContext, useP
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover
|
||||
onOpenChange={handleOpenChange}
|
||||
open={open}
|
||||
content={content}
|
||||
trigger="click"
|
||||
<Popover
|
||||
onOpenChange={handleOpenChange}
|
||||
open={open}
|
||||
content={content}
|
||||
trigger="click"
|
||||
destroyOnHidden
|
||||
styles={{ body: { padding: '12px' } }}
|
||||
styles={{ body: { padding: "12px" } }}
|
||||
{...(usePortal ? { getPopupContainer: (trigger) => trigger.parentElement || document.body } : {})}
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -26,7 +26,6 @@ const ret = {
|
||||
"jobs:partsqueue": 4,
|
||||
"jobs:checklist-view": 2,
|
||||
"jobs:list-ready": 1,
|
||||
"jobs:manual-line": 1,
|
||||
"jobs:void": 5,
|
||||
|
||||
"bills:enter": 2,
|
||||
|
||||
@@ -435,19 +435,6 @@ export function ShopInfoRbacComponent({ bodyshop }) {
|
||||
>
|
||||
<InputNumber />
|
||||
</Form.Item>,
|
||||
<Form.Item
|
||||
key="jobs:manual-line"
|
||||
label={t("bodyshop.fields.rbac.jobs.manual-line")}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
name={["md_rbac", "jobs:manual-line"]}
|
||||
>
|
||||
<InputNumber />
|
||||
</Form.Item>,
|
||||
<Form.Item
|
||||
key="jobs:partsqueue"
|
||||
label={t("bodyshop.fields.rbac.jobs.partsqueue")}
|
||||
|
||||
@@ -519,7 +519,6 @@
|
||||
"list-active": "Jobs -> List Active",
|
||||
"list-all": "Jobs -> List All",
|
||||
"list-ready": "Jobs -> List Ready",
|
||||
"manual-line": "Jobs -> Manual Line",
|
||||
"partsqueue": "Jobs -> Parts Queue",
|
||||
"void": "Jobs -> Void"
|
||||
},
|
||||
|
||||
@@ -519,7 +519,6 @@
|
||||
"list-active": "",
|
||||
"list-all": "",
|
||||
"list-ready": "",
|
||||
"manual-line": "",
|
||||
"partsqueue": "",
|
||||
"void": ""
|
||||
},
|
||||
|
||||
@@ -519,7 +519,6 @@
|
||||
"list-active": "",
|
||||
"list-all": "",
|
||||
"list-ready": "",
|
||||
"manual-line": "",
|
||||
"partsqueue": "",
|
||||
"void": ""
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user