Merged in feature/IO-3499-React-19 (pull request #2900)

Feature/IO-3499 React 19
This commit is contained in:
Dave Richer
2026-01-28 00:27:51 +00:00
12 changed files with 53 additions and 23 deletions

View File

@@ -108,9 +108,12 @@ export function ChatPopupComponent({ chatVisible, selectedConversation, toggleCh
hasLoadedConversationsOnceRef.current = true;
getConversations({ variables: { offset: 0 } }).catch((err) => {
console.error(`Error fetching conversations: ${err?.message || ""}`, err);
// Ignore abort errors (they're expected when component unmounts)
if (err?.name !== "AbortError") {
console.error(`Error fetching conversations: ${err?.message || ""}`, err);
}
});
}, [getConversations]);
}, []);
const handleManualRefresh = async () => {
try {

View File

@@ -143,7 +143,7 @@ export function JobsDetailHeader({ job, bodyshop, disabled, insertAuditTrail, is
label={t("jobs.fields.comment")}
styles={{ value: { overflow: "hidden", textOverflow: "ellipsis" } }}
>
<ProductionListColumnComment record={job} />
<ProductionListColumnComment record={job} usePortal={true} />
</DataLabel>
{!isPartsEntry && <DataLabel label={t("jobs.fields.ins_co_nm_short")}>{job.ins_co_nm}</DataLabel>}
<DataLabel label={t("jobs.fields.clm_no")}>{job.clm_no}</DataLabel>
@@ -176,7 +176,7 @@ export function JobsDetailHeader({ job, bodyshop, disabled, insertAuditTrail, is
</DataLabel>
)}
<DataLabel label={t("jobs.fields.production_vars.note")}>
<ProductionListColumnProductionNote record={job} />
<ProductionListColumnProductionNote record={job} usePortal={true} />
</DataLabel>
<DataLabel label={t("jobs.fields.estimate_sent_approval")}>
<Space>

View File

@@ -63,10 +63,10 @@ const ProductionListColumnAlert = ({ id, productionVars, refetch, insertAuditTra
okText={t("general.labels.yes")}
cancelText={t("general.labels.no")}
>
<Button className="production-alert" icon={<ExclamationCircleFilled />} />
<Button className="production-alert" icon={<ExclamationCircleFilled />} style={{ cursor: "pointer" }} />
</Popconfirm>
) : (
<Button className="muted-button" icon={<PlusCircleFilled />} onClick={handleAlertToggle} />
<Button className="muted-button" icon={<PlusCircleFilled />} onClick={handleAlertToggle} style={{ cursor: "pointer" }} />
);
};

View File

@@ -48,7 +48,7 @@ export default function ProductionListColumnBodyPriority({ record }) {
return (
<Dropdown menu={menu} trigger={["click"]}>
<div style={{ width: "100%", height: "19px" }}>{record.production_vars?.bodypriority}</div>
<div style={{ width: "100%", height: "19px", cursor: "pointer" }}>{record.production_vars?.bodypriority}</div>
</Dropdown>
);
}

View File

@@ -7,7 +7,7 @@ import { FaRegStickyNote } from "react-icons/fa";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
import { logImEXEvent } from "../../firebase/firebase.utils";
export default function ProductionListColumnComment({ record }) {
export default function ProductionListColumnComment({ record, usePortal = false }) {
const { t } = useTranslation();
const [note, setNote] = useState(record.comment || "");
@@ -43,16 +43,20 @@ export default function ProductionListColumnComment({ record }) {
};
const content = (
<div style={{ width: "30em" }} onMouseDown={(e) => e.stopPropagation()} onClick={(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
allowClear
style={{ marginBottom: "1em" }}
onMouseDown={(e) => e.stopPropagation()}
onClick={(e) => e.stopPropagation()}
/>
<div>
<Button onClick={handleSaveNote} type="primary">
@@ -63,7 +67,15 @@ export default function ProductionListColumnComment({ record }) {
);
return (
<Popover onOpenChange={handleOpenChange} open={open} content={content} trigger="click" fresh>
<Popover
onOpenChange={handleOpenChange}
open={open}
content={content}
trigger="click"
destroyOnHidden
styles={{ body: { padding: '12px' } }}
{...(usePortal ? { getPopupContainer: (trigger) => trigger.parentElement || document.body } : {})}
>
<div
style={{
width: "100%",

View File

@@ -64,6 +64,7 @@ const productionListColumnsData = ({ technician, state, activeStatuses, data, bo
ellipsis: true,
render: (text, record) => (
<div
style={{ cursor: "pointer" }}
onClick={() => {
store.dispatch(
setModalContext({

View File

@@ -86,7 +86,8 @@ export default function ProductionListDate({ record, field, time, pastIndicator
<div
onClick={() => setOpen(true)}
style={{
height: "19px"
height: "19px",
cursor: "pointer"
}}
className={className}
>

View File

@@ -48,7 +48,7 @@ export default function ProductionListColumnDetailPriority({ record }) {
return (
<Dropdown menu={menu} trigger={["click"]}>
<div style={{ width: "100%", height: "19px" }}>{record.production_vars?.detailpriority}</div>
<div style={{ width: "100%", height: "19px", cursor: "pointer" }}>{record.production_vars?.detailpriority}</div>
</Dropdown>
);
}

View File

@@ -144,13 +144,13 @@ export function ProductionListEmpAssignment({ insertAuditTrail, bodyshop, record
<Popover destroyOnHidden content={popContent} open={visibility}>
<Spin spinning={loading}>
{record[type] ? (
<div>
<div style={{ cursor: "pointer" }}>
<span>{`${theEmployee?.first_name || ""} ${theEmployee?.last_name || ""}`}</span>
<DeleteFilled style={iconStyle} onClick={() => handleRemove(type)} />
</div>
) : (
<PlusCircleFilled
style={iconStyle}
style={{ ...iconStyle, cursor: "pointer" }}
className="muted-button"
onClick={() => {
setAssignment({ operation: type });

View File

@@ -124,7 +124,8 @@ export function ProductionLastContacted({ currentUser, record }) {
<div
onClick={() => setOpen(true)}
style={{
height: "19px"
height: "19px",
cursor: "pointer"
}}
>
<DateFormatter bordered={false}>{record.date_last_contacted}</DateFormatter>

View File

@@ -48,7 +48,7 @@ export default function ProductionListColumnPaintPriority({ record }) {
return (
<Dropdown menu={menu} trigger={["click"]}>
<div style={{ width: "100%", height: "19px" }}>{record.production_vars?.paintpriority}</div>
<div style={{ width: "100%", height: "19px", cursor: "pointer" }}>{record.production_vars?.paintpriority}</div>
</Dropdown>
);
}

View File

@@ -16,7 +16,7 @@ const mapDispatchToProps = (dispatch) => ({
setNoteUpsertContext: (context) => dispatch(setModalContext({ context: context, modal: "noteUpsert" }))
});
function ProductionListColumnProductionNote({ record, setNoteUpsertContext }) {
function ProductionListColumnProductionNote({ record, setNoteUpsertContext, usePortal = false }) {
const { t } = useTranslation();
const [note, setNote] = useState(record.production_vars?.note || "");
const [open, setOpen] = useState(false);
@@ -59,16 +59,20 @@ function ProductionListColumnProductionNote({ record, setNoteUpsertContext }) {
);
const content = (
<div style={{ width: "30em" }} onMouseDown={(e) => e.stopPropagation()} onClick={(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
allowClear
style={{ marginBottom: "1em" }}
onMouseDown={(e) => e.stopPropagation()}
onClick={(e) => e.stopPropagation()}
/>
<Space>
<Button onClick={handleSaveNote} type="primary">
@@ -92,7 +96,15 @@ function ProductionListColumnProductionNote({ record, setNoteUpsertContext }) {
);
return (
<Popover onOpenChange={handleOpenChange} open={open} content={content} trigger="click" fresh>
<Popover
onOpenChange={handleOpenChange}
open={open}
content={content}
trigger="click"
destroyOnHidden
styles={{ body: { padding: '12px' } }}
{...(usePortal ? { getPopupContainer: (trigger) => trigger.parentElement || document.body } : {})}
>
<div
style={{
width: "100%",