@seedtactics/insight-client 16.8.4-beta.8 → 17.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +21 -0
  2. package/dist/assets/index-BkKYqUM0.js +388 -0
  3. package/dist/cell-status/material-details.d.ts +19 -5
  4. package/dist/cell-status/material-details.js +71 -37
  5. package/dist/components/LogEntry.js +2 -9
  6. package/dist/components/log-entry-container-name.d.ts +2 -0
  7. package/dist/components/log-entry-container-name.js +10 -0
  8. package/dist/components/operations/AllMaterial.js +4 -3
  9. package/dist/components/station-monitor/BasketLoadStationWork.js +12 -8
  10. package/dist/components/station-monitor/BulkRawMaterial.js +4 -4
  11. package/dist/components/station-monitor/CancelLoadButton.d.ts +4 -0
  12. package/dist/components/station-monitor/CancelLoadButton.js +60 -0
  13. package/dist/components/station-monitor/Closeout.js +2 -1
  14. package/dist/components/station-monitor/Inspection.js +2 -1
  15. package/dist/components/station-monitor/InvalidateCycle.d.ts +4 -1
  16. package/dist/components/station-monitor/InvalidateCycle.js +104 -38
  17. package/dist/components/station-monitor/LoadStation.js +25 -15
  18. package/dist/components/station-monitor/Material.js +14 -1
  19. package/dist/components/station-monitor/QuarantineButton.js +160 -90
  20. package/dist/components/station-monitor/Queues.js +2 -1
  21. package/dist/components/station-monitor/QueuesAddMaterial.js +65 -57
  22. package/dist/components/station-monitor/SystemOverview.js +2 -1
  23. package/dist/components/station-monitor/Whiteboard.js +2 -2
  24. package/dist/data/material-operation-policy.d.ts +21 -0
  25. package/dist/data/material-operation-policy.js +89 -0
  26. package/dist/extension.d.ts +11 -0
  27. package/dist/extension.js +21 -0
  28. package/dist/index.html +1 -2
  29. package/dist/index.js +1 -1
  30. package/dist/network/api.d.ts +20 -4
  31. package/dist/network/api.js +163 -2
  32. package/dist/network/backend-mock.js +6 -0
  33. package/dist/network/backend.d.ts +2 -0
  34. package/dist/network/backend.js +2 -1
  35. package/package.json +12 -11
  36. package/dist/assets/index-DHusyIyb.js +0 -388
  37. package/dist/assets/manifest-BzJli0lx.webmanifest +0 -15
  38. package/dist/bootstrap.d.ts +0 -5
  39. package/dist/bootstrap.js +0 -56
  40. package/dist/components/station-monitor/Material.test.d.ts +0 -1
  41. package/dist/components/station-monitor/Material.test.js +0 -199
@@ -34,17 +34,42 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
34
  import { Box, Button, ListItemIcon, ListItemText, ListSubheader, Stack } from "@mui/material";
35
35
  import { MenuItem } from "@mui/material";
36
36
  import { TextField } from "@mui/material";
37
- import { ActionType, LocType } from "../../network/api.js";
37
+ import { LocType, LogType } from "../../network/api.js";
38
38
  import { JobsBackend } from "../../network/backend.js";
39
- import { LazySeq } from "@seedtactics/immutable-collections";
39
+ import { HashMap, LazySeq } from "@seedtactics/immutable-collections";
40
40
  import { currentStatus } from "../../cell-status/current-status.js";
41
- import { barcodePotentialNewMaterial, inProcessMaterialInDialog, materialDialogOpen, materialInDialogInfo, materialInDialogLargestUsedProcess, } from "../../cell-status/material-details.js";
41
+ import { barcodePotentialNewMaterial, inProcessMaterialInDialog, materialDialogOpen, materialInDialogInfo, materialInDialogLargestUsedProcess, materialInDialogLocalEvents, } from "../../cell-status/material-details.js";
42
42
  import { currentOperator } from "../../data/operators.js";
43
43
  import { fmsInformation } from "../../network/server-settings.js";
44
44
  import { useAtomValue, useSetAtom } from "jotai";
45
45
  import { useEffect, useRef } from "react";
46
46
  import { last30Jobs } from "../../cell-status/scheduled-jobs.js";
47
47
  import { PartIdenticon } from "./Material.js";
48
+ import { isLogEntryInvalidated } from "../LogEntry.js";
49
+ import { ApiException } from "../../network/api.js";
50
+ import { canInvalidateMaterial, isActiveLoadStationOperation, } from "../../data/material-operation-policy.js";
51
+ const invalidatableEventTypes = LazySeq.of([
52
+ LogType.AddToQueue,
53
+ LogType.RemoveFromQueue,
54
+ LogType.LoadUnloadCycle,
55
+ LogType.MachineCycle,
56
+ LogType.BasketLoadUnload,
57
+ LogType.BasketCycle,
58
+ ]).toRSet((eventType) => eventType);
59
+ export function affectedMaterialForInvalidation(events, materialId, process) {
60
+ let affected = HashMap.empty();
61
+ for (const event of events) {
62
+ if (!invalidatableEventTypes.has(event.type) ||
63
+ isLogEntryInvalidated(event) ||
64
+ !event.material.some((material) => material.id === materialId && (process === null || material.proc >= process))) {
65
+ continue;
66
+ }
67
+ for (const material of event.material) {
68
+ affected = affected.set(material.id, material.serial ?? null);
69
+ }
70
+ }
71
+ return affected;
72
+ }
48
73
  function InvalidateSelect(props) {
49
74
  const lastMat = useAtomValue(materialInDialogLargestUsedProcess);
50
75
  const possible = useAtomValue(barcodePotentialNewMaterial);
@@ -60,50 +85,64 @@ function InvalidateSelect(props) {
60
85
  }));
61
86
  const hasProc = lastMat !== null && lastMat.process >= 1;
62
87
  const hasChangeMat = castings.length > 0 || jobs.length > 0;
88
+ const selectedCasting = props.st?.changeRawMat !== null &&
89
+ props.st?.changeRawMat !== undefined &&
90
+ castings.includes(props.st.changeRawMat);
91
+ const selectedJob = props.st?.changeJobUnique !== null &&
92
+ props.st?.changeJobUnique !== undefined &&
93
+ jobs.some((job) => job.jobUnique === props.st?.changeJobUnique);
63
94
  function change(e) {
64
95
  props.setState({
65
96
  updating: false,
66
- process: e.startsWith("proc") ? parseInt(e.substring(4)) : null,
97
+ error: null,
98
+ process: e.startsWith("proc") ? parseInt(e.substring(4)) : 1,
67
99
  changeRawMat: e.startsWith("rawMat") ? e.substring(6) : null,
68
100
  changeJobUnique: e.startsWith("job") ? e.substring(3) : null,
69
101
  });
70
102
  }
71
- return (_jsx(TextField, { value: props.st?.process
72
- ? "proc" + props.st.process.toString()
73
- : props.st?.changeRawMat
74
- ? "rawMat" + props.st.changeRawMat
75
- : props.st?.changeJobUnique
76
- ? "job" + props.st.changeJobUnique
77
- : "", select: true, onChange: (e) => change(e.target.value), variant: "outlined", label: props.st?.process || !hasChangeMat
78
- ? "Invalidate Process"
79
- : props.st?.changeRawMat
80
- ? "Change Raw Material"
81
- : props.st?.changeJobUnique
82
- ? "Change Assigned Job"
103
+ return (_jsx(TextField, { value: selectedCasting
104
+ ? "rawMat" + props.st.changeRawMat
105
+ : selectedJob
106
+ ? "job" + props.st.changeJobUnique
107
+ : props.st?.process && hasProc
108
+ ? "proc" + props.st.process.toString()
109
+ : "", select: true, onChange: (e) => change(e.target.value), variant: "outlined", label: props.st?.changeRawMat
110
+ ? "Change Raw Material"
111
+ : props.st?.changeJobUnique
112
+ ? "Change Assigned Job"
113
+ : props.st?.process || !hasChangeMat
114
+ ? "Invalidate Process"
83
115
  : !hasProc
84
116
  ? "Change Assignment"
85
117
  : "", children: [
86
118
  hasProc && hasChangeMat
87
119
  ? [_jsx(ListSubheader, { children: "Invalidate Selected Process" }, "procheader")]
88
120
  : [],
89
- lastMat
90
- ? LazySeq.ofRange(1, lastMat.process + 1)
91
- .map((p) => (_jsxs(MenuItem, { value: "proc" + p.toString(), children: ["Invalidate Process ", p] }, p)))
92
- .toRArray()
121
+ hasProc
122
+ ? [
123
+ _jsxs(MenuItem, { value: "proc" + lastMat.process.toString(), children: ["Invalidate Process ", lastMat.process] }, lastMat.process),
124
+ ...(lastMat.process > 1
125
+ ? [
126
+ _jsx(MenuItem, { value: "proc1", children: "Invalidate All Processes" }, "all"),
127
+ ]
128
+ : []),
129
+ ]
93
130
  : [],
94
131
  hasProc && hasChangeMat
95
132
  ? [_jsx(ListSubheader, { children: "Change Material Type" }, "matheader")]
96
133
  : [],
97
134
  hasChangeMat
98
135
  ? [
99
- ...castings.map((c) => (_jsxs(MenuItem, { value: "rawMat" + c, children: ["Invalidate Everything And Change to ", c] }, "rawMat" + c))),
100
- ...jobs.map(({ jobUnique, job }) => (_jsxs(MenuItem, { value: "job" + jobUnique, children: [job ? (_jsx(ListItemIcon, { children: _jsx(PartIdenticon, { part: job.partName }) })) : undefined, _jsx(ListItemText, { primary: "Invalidate Everything And Change To Job " + jobUnique, secondary: job?.partName })] }, "job" + jobUnique))),
136
+ ...castings.map((c) => (_jsxs(MenuItem, { value: "rawMat" + c, children: ["Invalidate Everything and Change to ", c] }, "rawMat" + c))),
137
+ ...jobs.map(({ jobUnique, job }) => (_jsxs(MenuItem, { value: "job" + jobUnique, children: [job ? (_jsx(ListItemIcon, { children: _jsx(PartIdenticon, { part: job.partName }) })) : undefined, _jsx(ListItemText, { primary: "Invalidate Everything and Change to Job " + jobUnique, secondary: job?.partName })] }, "job" + jobUnique))),
101
138
  ]
102
139
  : [],
103
140
  ] }));
104
141
  }
105
142
  export function InvalidateCycleDialogContent(props) {
106
143
  const curMat = useAtomValue(materialInDialogInfo);
144
+ const events = useAtomValue(materialInDialogLocalEvents);
145
+ const status = useAtomValue(currentStatus);
107
146
  const show = props.st !== null && curMat !== null;
108
147
  const boxRef = useRef(null);
109
148
  useEffect(() => {
@@ -114,7 +153,20 @@ export function InvalidateCycleDialogContent(props) {
114
153
  }, [boxRef, show]);
115
154
  if (!show)
116
155
  return _jsx("div", {});
117
- return (_jsx(Box, { ref: boxRef, sx: { display: "flex", flexDirection: "column", alignItems: "center", marginTop: "1em" }, children: _jsxs(Stack, { spacing: 2, children: [_jsx("p", { style: { maxWidth: "35em" }, children: "An invalidated cycle remains in the event log, but is not considered when determining the next process to be machined on a piece of material." }), _jsx(InvalidateSelect, { st: props.st, setState: props.setState })] }) }));
156
+ const hasSelection = props.st.process !== null ||
157
+ props.st.changeRawMat !== null ||
158
+ props.st.changeJobUnique !== null;
159
+ const previewProcess = props.st.changeRawMat !== null || props.st.changeJobUnique !== null ? null : props.st.process;
160
+ const affected = hasSelection
161
+ ? affectedMaterialForInvalidation(events, curMat.materialID, previewProcess)
162
+ : HashMap.empty();
163
+ const affectedLabels = [...affected].map(([materialId, serial]) => ({
164
+ materialId,
165
+ serial,
166
+ queued: status.material.find((material) => material.materialID === materialId)?.location.type ===
167
+ LocType.InQueue,
168
+ }));
169
+ return (_jsx(Box, { ref: boxRef, sx: { display: "flex", flexDirection: "column", alignItems: "center", marginTop: "1em" }, children: _jsxs(Stack, { spacing: 2, children: [_jsx("p", { style: { maxWidth: "35em" }, children: "Invalidating removes whole recorded cycle events from active material reconstruction while retaining them in the event log." }), _jsx(InvalidateSelect, { st: props.st, setState: props.setState }), affectedLabels.length > 0 ? (_jsxs(_Fragment, { children: [_jsx("p", { children: "All material recorded on these events will be affected:" }), _jsx("ul", { children: affectedLabels.map((material) => (_jsxs("li", { children: [material.serial || `Material ID ${material.materialId}`, material.queued ? " (currently in a queue)" : ""] }, material.materialId))) })] })) : null, props.st.error ? _jsx("p", { role: "alert", children: props.st.error }) : null] }) }));
118
170
  }
119
171
  export function InvalidateCycleDialogButton(props) {
120
172
  const fmsInfo = useAtomValue(fmsInformation);
@@ -130,7 +182,7 @@ export function InvalidateCycleDialogButton(props) {
130
182
  return null;
131
183
  if (curMat === null)
132
184
  return null;
133
- if (inProcMat && inProcMat.location.type === LocType.OnPallet)
185
+ if (!canInvalidateMaterial(inProcMat))
134
186
  return null;
135
187
  const allowChange = possibleNew !== null &&
136
188
  (!LazySeq.ofObject(possibleNew.possibleCastingsByQueue ?? {}).isEmpty() ||
@@ -140,7 +192,13 @@ export function InvalidateCycleDialogButton(props) {
140
192
  if (props.ignoreOperator)
141
193
  operator = null;
142
194
  function showInvalidate() {
143
- props.setState({ process: null, updating: false, changeRawMat: null, changeJobUnique: null });
195
+ props.setState({
196
+ process: null,
197
+ updating: false,
198
+ error: null,
199
+ changeRawMat: null,
200
+ changeJobUnique: null,
201
+ });
144
202
  }
145
203
  function invalidateCycle() {
146
204
  if (curMat && (props.st?.process || props.st?.changeRawMat || props.st?.changeJobUnique)) {
@@ -152,7 +210,7 @@ export function InvalidateCycleDialogButton(props) {
152
210
  type: "MatDetails",
153
211
  details: mat,
154
212
  });
155
- props.onClose();
213
+ props.setState(null);
156
214
  }
157
215
  else {
158
216
  setMatToShow(null);
@@ -160,21 +218,31 @@ export function InvalidateCycleDialogButton(props) {
160
218
  }
161
219
  })
162
220
  .catch((e) => {
163
- console.log(e);
164
- setMatToShow(null);
165
- props.onClose();
221
+ props.setState({
222
+ ...props.st,
223
+ updating: false,
224
+ error: ApiException.isApiException(e)
225
+ ? e.response
226
+ : e instanceof Error
227
+ ? e.message
228
+ : String(e),
229
+ });
166
230
  });
167
231
  }
168
232
  }
169
233
  return (_jsxs(_Fragment, { children: [props.st === null ? (_jsx(Button, { color: "primary", onClick: showInvalidate, children: "Invalidate Cycle" })) : undefined, props.st !== null ? (_jsx(Button, { color: "primary", onClick: invalidateCycle, disabled: props.st.updating ||
170
234
  (props.st.process === null &&
171
235
  props.st.changeRawMat === null &&
172
- props.st.changeJobUnique === null), children: props.st.process !== null
173
- ? "Invalidate Process " + props.st.process.toString()
174
- : props.st.changeJobUnique !== null
175
- ? "Invalidate And Change To Job " + props.st.changeJobUnique
176
- : props.st.changeRawMat !== null
177
- ? "Invalidate And Change To " + props.st.changeRawMat
236
+ props.st.changeJobUnique === null), children: props.st.changeJobUnique !== null
237
+ ? "Invalidate Everything and Change to Job " + props.st.changeJobUnique
238
+ : props.st.changeRawMat !== null
239
+ ? "Invalidate Everything and Change to " + props.st.changeRawMat
240
+ : props.st.process !== null
241
+ ? props.st.process === 1
242
+ ? lastMat && lastMat.process > 1
243
+ ? "Invalidate All Processes"
244
+ : "Invalidate Process 1"
245
+ : "Invalidate Process " + props.st.process.toString()
178
246
  : "Invalidate Cycle" })) : undefined] }));
179
247
  }
180
248
  function isNullOrEmpty(s) {
@@ -241,9 +309,7 @@ export function SwapMaterialButtons(props) {
241
309
  operator = null;
242
310
  if (!curMat ||
243
311
  curMat.location.type !== LocType.OnPallet ||
244
- curMat.action.type === ActionType.Loading ||
245
- curMat.action.type === ActionType.UnloadToCompletedMaterial ||
246
- curMat.action.type === ActionType.UnloadToInProcess) {
312
+ isActiveLoadStationOperation(curMat)) {
247
313
  return null;
248
314
  }
249
315
  function swapMats() {
@@ -51,6 +51,7 @@ import { fmsInformation } from "../../network/server-settings.js";
51
51
  import { currentStatus, secondsSinceEpochAtom } from "../../cell-status/current-status.js";
52
52
  import { useIsDemo, useSetTitle } from "../routes.js";
53
53
  import { QuarantineMatButton } from "./QuarantineButton.js";
54
+ import { CancelLoadButton } from "./CancelLoadButton.js";
54
55
  import { durationToSeconds } from "../../util/parseISODuration.js";
55
56
  import { formatSeconds } from "./SystemOverview.js";
56
57
  import { InvalidateCycleDialogButton, InvalidateCycleDialogContent, SwapMaterialButtons, SwapMaterialDialogContent, } from "./InvalidateCycle.js";
@@ -61,6 +62,7 @@ import { useAtomValue, useSetAtom } from "jotai";
61
62
  import { PrintLabelButton } from "./PrintedLabel.js";
62
63
  import { hideNonLoadingMaterialOnLoadStation } from "../../data/queue-material.js";
63
64
  import { basketDisplayName, loadStationDisplayName } from "../../cell-status/station-cycles.js";
65
+ import { canAddOrMoveMaterialToQueue } from "../../data/material-operation-policy.js";
64
66
  import { BasketLoadStationWorkflow, } from "./BasketLoadStationWork.js";
65
67
  function encodeLoadStationRegionIdPart(value) {
66
68
  return encodeURIComponent(value.toString());
@@ -540,10 +542,8 @@ function AddMatButton({ queues, onClose, toQueue, showAddToQueue, setShowAddToQu
540
542
  const inProcMat = useAtomValue(matDetails.inProcessMaterialInDialog);
541
543
  const operator = useAtomValue(currentOperator);
542
544
  const [addExistingMat, addingExistingMat] = matDetails.useAddExistingMaterialToQueue();
543
- if (!existingMat ||
544
- inProcMat?.location.type === api.LocType.OnPallet ||
545
- inProcMat?.action.type === api.ActionType.Loading ||
546
- inProcMat?.action.type === api.ActionType.LoadingToBasket) {
545
+ const [addError, setAddError] = useState(null);
546
+ if (!existingMat || !canAddOrMoveMaterialToQueue(inProcMat)) {
547
547
  return null;
548
548
  }
549
549
  if (queues.length === 0)
@@ -557,16 +557,26 @@ function AddMatButton({ queues, onClose, toQueue, showAddToQueue, setShowAddToQu
557
557
  return (_jsx(Button, { color: "primary", onClick: () => setShowAddToQueue(true), children: "Add To Queue" }));
558
558
  }
559
559
  else {
560
- return (_jsxs(Button, { color: "primary", disabled: toQueue === null || addingExistingMat, onClick: () => {
561
- addExistingMat({
562
- materialId: existingMat.materialID,
563
- queue: toQueue ?? "",
564
- queuePosition: -1,
565
- operator: operator,
566
- });
567
- setMatToShow(null);
568
- onClose();
569
- }, children: ["Add To ", toQueue ?? "Queue", " ", lastProcMat ? ` To Run Process ${lastProcMat.process + 1}` : ""] }));
560
+ return (_jsxs(_Fragment, { children: [_jsxs(Button, { color: "primary", disabled: toQueue === null || addingExistingMat, onClick: async () => {
561
+ setAddError(null);
562
+ try {
563
+ await addExistingMat({
564
+ materialId: existingMat.materialID,
565
+ queue: toQueue ?? "",
566
+ queuePosition: -1,
567
+ operator: operator,
568
+ });
569
+ setMatToShow(null);
570
+ onClose();
571
+ }
572
+ catch (e) {
573
+ setAddError(api.ApiException.isApiException(e)
574
+ ? e.response
575
+ : e instanceof Error
576
+ ? e.message
577
+ : String(e));
578
+ }
579
+ }, children: ["Add To ", toQueue ?? "Queue", " ", lastProcMat ? ` To Run Process ${lastProcMat.process + 1}` : ""] }), addError ? _jsx(Typography, { role: "alert", children: addError }) : null] }));
570
580
  }
571
581
  }
572
582
  function AssignWorkorderButton() {
@@ -593,7 +603,7 @@ const LoadMatDialog = memo(function LoadMatDialog(props) {
593
603
  setShowAddMaterial(false);
594
604
  setSelectedQueue(null);
595
605
  }, [setSwapSt, setInvalidateSt]);
596
- return (_jsx(MaterialDialog, { onClose: onClose, allowNote: true, highlightProcsGreaterOrEqualTo: invalidateSt?.process ?? undefined, extraDialogElements: _jsxs(_Fragment, { children: [_jsx(SwapMaterialDialogContent, { st: swapSt, setState: setSwapSt }), invalidateSt !== null ? (_jsx(InvalidateCycleDialogContent, { st: invalidateSt, setState: setInvalidateSt })) : null, showAddMaterial ? (_jsx(PromptForQueue, { selectedQueue: selectedQueue, setSelectedQueue: setSelectedQueue, queueNames: props.queues })) : undefined] }), buttons: _jsxs(_Fragment, { children: [_jsx(InstructionButton, { pallet: props.pallet }), _jsx(PrintLabelButton, {}), _jsx(QuarantineMatButton, {}), _jsx(SignalInspectionButton, {}), _jsx(AddMatButton, { toQueue: selectedQueue, queues: props.queues, onClose: onClose, showAddToQueue: showAddMaterial, setShowAddToQueue: setShowAddMaterial }), _jsx(SwapMaterialButtons, { st: swapSt, setState: setSwapSt, onClose: onClose }), _jsx(InvalidateCycleDialogButton, { st: invalidateSt, setState: setInvalidateSt, onClose: onClose, loadStation: true }), _jsx(AssignWorkorderButton, {})] }) }));
606
+ return (_jsx(MaterialDialog, { onClose: onClose, allowNote: true, highlightProcsGreaterOrEqualTo: invalidateSt?.process ?? undefined, extraDialogElements: _jsxs(_Fragment, { children: [_jsx(SwapMaterialDialogContent, { st: swapSt, setState: setSwapSt }), invalidateSt !== null ? (_jsx(InvalidateCycleDialogContent, { st: invalidateSt, setState: setInvalidateSt })) : null, showAddMaterial ? (_jsx(PromptForQueue, { selectedQueue: selectedQueue, setSelectedQueue: setSelectedQueue, queueNames: props.queues })) : undefined] }), buttons: _jsxs(_Fragment, { children: [_jsx(InstructionButton, { pallet: props.pallet }), _jsx(PrintLabelButton, {}), _jsx(QuarantineMatButton, {}), _jsx(CancelLoadButton, { onClose: onClose }), _jsx(SignalInspectionButton, {}), _jsx(AddMatButton, { toQueue: selectedQueue, queues: props.queues, onClose: onClose, showAddToQueue: showAddMaterial, setShowAddToQueue: setShowAddMaterial }), _jsx(SwapMaterialButtons, { st: swapSt, setState: setSwapSt, onClose: onClose }), _jsx(InvalidateCycleDialogButton, { st: invalidateSt, setState: setInvalidateSt, onClose: onClose, loadStation: true }), _jsx(AssignWorkorderButton, {})] }) }));
597
607
  });
598
608
  function useGridLayout({ numMatCols, maxNumFaces, horizontal, showMatInCompleted, }) {
599
609
  let rows = "";
@@ -49,6 +49,7 @@ import { useAtom, useAtomValue, useSetAtom } from "jotai";
49
49
  import { last30Rebookings } from "../../cell-status/rebookings.js";
50
50
  import { fmsInformation } from "../../network/server-settings.js";
51
51
  import { basketDisplayName } from "../../cell-status/station-cycles.js";
52
+ import { materialOperationState } from "../../data/material-operation-policy.js";
52
53
  export class PartIdenticon extends PureComponent {
53
54
  render() {
54
55
  const iconSize = this.props.size || 50;
@@ -537,6 +538,18 @@ function RebookingNote() {
537
538
  }
538
539
  return null;
539
540
  }
541
+ function MaterialOperationNotice() {
542
+ const material = useAtomValue(matDetails.inProcessMaterialInDialog);
543
+ if (material === null)
544
+ return null;
545
+ if (material.quarantineAfterUnload) {
546
+ return (_jsx(Typography, { variant: "caption", component: "p", children: "Quarantine requested" }));
547
+ }
548
+ const state = materialOperationState(material);
549
+ if (state.kind !== "ActiveLoadStationOperation" || state.cancellationId !== null)
550
+ return null;
551
+ return (_jsx(Typography, { variant: "caption", component: "p", children: "This material is part of the current load/unload operation. Complete the operation or cancel it at the machine control before making other changes." }));
552
+ }
540
553
  export const MaterialDetailContent = memo(function MaterialDetailContent({ highlightProcsGreaterOrEqualTo, }) {
541
554
  const toShow = useAtomValue(matDetails.materialDialogOpen);
542
555
  const mat = useAtomValue(matDetails.materialInDialogInfo);
@@ -559,7 +572,7 @@ export const MaterialDetailContent = memo(function MaterialDetailContent({ highl
559
572
  return _jsx("div", { style: { marginLeft: "1em" }, children: "Material not found." });
560
573
  }
561
574
  }
562
- return (_jsxs(_Fragment, { children: [_jsxs("div", { style: { marginLeft: "1em" }, children: [_jsx("div", { children: _jsxs("small", { children: ["Workorder: ", mat?.workorderId ?? "none"] }) }), _jsx("div", { children: _jsx(DisplayLoadingAndError, { fallback: _jsxs("small", { children: ["Inspections: ", _jsx(CircularProgress, { size: "10" })] }), children: _jsx(MaterialInspections, {}) }) }), _jsx("div", { children: _jsx(DisplayLoadingAndError, { fallback: _jsx("div", {}), children: _jsx(RebookingNote, {}) }) })] }), _jsx(DisplayLoadingAndError, { fallback: _jsx(CircularProgress, {}), children: _jsx(MaterialEvents, { highlightProcsGreaterOrEqualTo: highlightProcsGreaterOrEqualTo }) })] }));
575
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { style: { marginLeft: "1em" }, children: [_jsx(MaterialOperationNotice, {}), _jsx("div", { children: _jsxs("small", { children: ["Workorder: ", mat?.workorderId ?? "none"] }) }), _jsx("div", { children: _jsx(DisplayLoadingAndError, { fallback: _jsxs("small", { children: ["Inspections: ", _jsx(CircularProgress, { size: "10" })] }), children: _jsx(MaterialInspections, {}) }) }), _jsx("div", { children: _jsx(DisplayLoadingAndError, { fallback: _jsx("div", {}), children: _jsx(RebookingNote, {}) }) })] }), _jsx(DisplayLoadingAndError, { fallback: _jsx(CircularProgress, {}), children: _jsx(MaterialEvents, { highlightProcsGreaterOrEqualTo: highlightProcsGreaterOrEqualTo }) })] }));
563
576
  });
564
577
  function NotesDialogBody(props) {
565
578
  const [curNote, setCurNote] = useState("");