Compare commits
15 Commits
release/20
...
feature/IO
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d00fc29d1 | ||
|
|
a873a2573a | ||
|
|
8980d3716b | ||
|
|
764ec5f8f9 | ||
|
|
a7a7551dae | ||
|
|
571536a7ec | ||
|
|
20e56fff6a | ||
|
|
8f132ca14d | ||
|
|
99c002dac1 | ||
|
|
0cd30ccdec | ||
|
|
acd69276a5 | ||
|
|
faf5878bdf | ||
|
|
5a55798d2d | ||
|
|
c9e41ba72a | ||
|
|
522f2b9e26 |
@@ -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
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
* @returns {number|null}
|
||||
*/
|
||||
const parseVendorStatusCode = (err) => {
|
||||
// Prefer explicit numeric props when available
|
||||
// Prefer explicit numeric props when available.
|
||||
const codeProp = err?.code ?? err?.statusCode ?? err?.meta?.status?.StatusCode ?? err?.status?.StatusCode;
|
||||
const num = Number(codeProp);
|
||||
if (!Number.isNaN(num) && num > 0) return num;
|
||||
|
||||
@@ -12,7 +12,7 @@ const { createRRCustomer } = require("./rr-customers");
|
||||
const { ensureRRServiceVehicle } = require("./rr-service-vehicles");
|
||||
const { classifyRRVendorError } = require("./rr-errors");
|
||||
const { markRRExportSuccess, insertRRFailedExportLog } = require("./rr-export-logs");
|
||||
const { withRRRequestXml } = require("./rr-log-xml");
|
||||
const { withRRRequestXml, extractRRXmlPair } = require("./rr-log-xml");
|
||||
const {
|
||||
makeVehicleSearchPayloadFromJob,
|
||||
ownersFromVinBlocks,
|
||||
@@ -49,6 +49,21 @@ const resolveJobId = (explicit, payload, job) => explicit || payload?.jobId || j
|
||||
*/
|
||||
const resolveVin = ({ tx, job }) => tx?.jobData?.vin || job?.v_vin || null;
|
||||
|
||||
/**
|
||||
* Add request/response XML to socket event payloads when available.
|
||||
* @param rrObj
|
||||
* @param payload
|
||||
* @returns {*}
|
||||
*/
|
||||
const withRRXmlSocketPayload = (rrObj, payload = {}) => {
|
||||
const { requestXml, responseXml } = extractRRXmlPair(rrObj);
|
||||
return {
|
||||
...payload,
|
||||
...(requestXml ? { requestXml } : {}),
|
||||
...(responseXml ? { responseXml } : {})
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Sort vehicle owners first in the list, preserving original order otherwise.
|
||||
* @param list
|
||||
@@ -474,7 +489,14 @@ const registerRREvents = ({ socket, redisHelpers }) => {
|
||||
);
|
||||
|
||||
try {
|
||||
socket.emit("export-failed", { vendor: "rr", jobId: rid, error: error.message });
|
||||
socket.emit(
|
||||
"export-failed",
|
||||
withRRXmlSocketPayload(error, {
|
||||
vendor: "rr",
|
||||
jobId: rid,
|
||||
error: error.message
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
@@ -870,9 +892,11 @@ const registerRREvents = ({ socket, redisHelpers }) => {
|
||||
});
|
||||
|
||||
socket.emit("export-failed", {
|
||||
vendor: "rr",
|
||||
jobId: rid,
|
||||
error: cls?.friendlyMessage || result?.error || "RR early RO creation failed",
|
||||
...withRRXmlSocketPayload(result, {
|
||||
vendor: "rr",
|
||||
jobId: rid,
|
||||
error: cls?.friendlyMessage || result?.error || "RR early RO creation failed"
|
||||
}),
|
||||
...cls
|
||||
});
|
||||
|
||||
@@ -923,9 +947,11 @@ const registerRREvents = ({ socket, redisHelpers }) => {
|
||||
|
||||
try {
|
||||
socket.emit("export-failed", {
|
||||
vendor: "rr",
|
||||
jobId: rid,
|
||||
error: error.message,
|
||||
...withRRXmlSocketPayload(error, {
|
||||
vendor: "rr",
|
||||
jobId: rid,
|
||||
error: error.message
|
||||
}),
|
||||
...cls
|
||||
});
|
||||
socket.emit("rr-user-notice", { jobId: rid, ...cls });
|
||||
@@ -1173,7 +1199,14 @@ const registerRREvents = ({ socket, redisHelpers }) => {
|
||||
);
|
||||
|
||||
try {
|
||||
socket.emit("export-failed", { vendor: "rr", jobId: rid, error: error.message });
|
||||
socket.emit(
|
||||
"export-failed",
|
||||
withRRXmlSocketPayload(error, {
|
||||
vendor: "rr",
|
||||
jobId: rid,
|
||||
error: error.message
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
@@ -1538,9 +1571,11 @@ const registerRREvents = ({ socket, redisHelpers }) => {
|
||||
});
|
||||
|
||||
socket.emit("export-failed", {
|
||||
vendor: "rr",
|
||||
jobId: rid,
|
||||
error: cls?.friendlyMessage || result?.error || "RR export failed",
|
||||
...withRRXmlSocketPayload(result, {
|
||||
vendor: "rr",
|
||||
jobId: rid,
|
||||
error: cls?.friendlyMessage || result?.error || "RR export failed"
|
||||
}),
|
||||
...cls
|
||||
});
|
||||
|
||||
@@ -1591,9 +1626,11 @@ const registerRREvents = ({ socket, redisHelpers }) => {
|
||||
|
||||
try {
|
||||
socket.emit("export-failed", {
|
||||
vendor: "rr",
|
||||
jobId: rid,
|
||||
error: error.message,
|
||||
...withRRXmlSocketPayload(error, {
|
||||
vendor: "rr",
|
||||
jobId: rid,
|
||||
error: error.message
|
||||
}),
|
||||
...cls
|
||||
});
|
||||
socket.emit("rr-user-notice", { jobId: rid, ...cls });
|
||||
@@ -1725,9 +1762,11 @@ const registerRREvents = ({ socket, redisHelpers }) => {
|
||||
});
|
||||
|
||||
socket.emit("export-failed", {
|
||||
vendor: "rr",
|
||||
jobId: rid,
|
||||
error: cls?.friendlyMessage || finalizeResult?.error || "RR finalize failed",
|
||||
...withRRXmlSocketPayload(finalizeResult, {
|
||||
vendor: "rr",
|
||||
jobId: rid,
|
||||
error: cls?.friendlyMessage || finalizeResult?.error || "RR finalize failed"
|
||||
}),
|
||||
...cls
|
||||
});
|
||||
ack?.({ ok: false, error: cls.friendlyMessage || "RR finalize failed", classification: cls });
|
||||
@@ -1770,7 +1809,17 @@ const registerRREvents = ({ socket, redisHelpers }) => {
|
||||
});
|
||||
|
||||
try {
|
||||
socket.emit("export-failed", { vendor: "rr", jobId: rid, error: error.message, ...cls });
|
||||
socket.emit(
|
||||
"export-failed",
|
||||
{
|
||||
...withRRXmlSocketPayload(error, {
|
||||
vendor: "rr",
|
||||
jobId: rid,
|
||||
error: error.message
|
||||
}),
|
||||
...cls
|
||||
}
|
||||
);
|
||||
} catch {
|
||||
//
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user