@seedtactics/insight-client 17.0.1-beta.1 → 17.0.1-beta.10

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 (44) hide show
  1. package/dist/assets/ProgramHighlight-C6zSEXCX.js +3 -0
  2. package/dist/assets/index-BaeSfExJ.js +388 -0
  3. package/dist/cell-status/inspections.js +0 -20
  4. package/dist/cell-status/material-details.js +7 -1
  5. package/dist/cell-status/material-summary.js +1 -87
  6. package/dist/cell-status/station-cycles.d.ts +1 -0
  7. package/dist/cell-status/station-cycles.js +11 -14
  8. package/dist/components/LogEntry.js +0 -71
  9. package/dist/components/log-entry-container-name.d.ts +2 -2
  10. package/dist/components/log-entry-container-name.js +1 -7
  11. package/dist/components/operations/AllMaterial.js +2 -4
  12. package/dist/components/operations/CompletedParts.js +10 -10
  13. package/dist/components/operations/Programs.js +24 -17
  14. package/dist/components/operations/Rebookings.js +1 -1
  15. package/dist/components/quality/RecentFailedInspections.js +1 -1
  16. package/dist/components/routes.js +1 -2
  17. package/dist/components/station-monitor/BasketLoadStationWork.js +66 -16
  18. package/dist/components/station-monitor/BasketMovementArrival.d.ts +4 -2
  19. package/dist/components/station-monitor/BasketMovementArrival.js +23 -33
  20. package/dist/components/station-monitor/BulkRawMaterial.js +25 -14
  21. package/dist/components/station-monitor/CancelLoadButton.js +3 -1
  22. package/dist/components/station-monitor/InvalidateCycle.d.ts +1 -17
  23. package/dist/components/station-monitor/InvalidateCycle.js +2 -92
  24. package/dist/components/station-monitor/LoadStation.js +36 -18
  25. package/dist/components/station-monitor/Material.js +33 -31
  26. package/dist/components/station-monitor/PrintedLabel.js +2 -2
  27. package/dist/components/station-monitor/QuarantineButton.js +4 -4
  28. package/dist/components/station-monitor/SystemOverview.js +33 -31
  29. package/dist/data/all-material-bins.js +15 -11
  30. package/dist/data/current-cycles.js +6 -3
  31. package/dist/data/inspection-sankey.js +1 -1
  32. package/dist/data/results.completed-parts.js +1 -1
  33. package/dist/data/results.cycles.js +1 -1
  34. package/dist/data/results.schedules.js +1 -1
  35. package/dist/index.html +1 -1
  36. package/dist/network/api.d.ts +31 -50
  37. package/dist/network/api.js +55 -141
  38. package/dist/network/backend-mock.js +0 -3
  39. package/dist/network/backend.d.ts +0 -1
  40. package/docs/mazak.md +13 -0
  41. package/docs/operator-procedures.md +6 -6
  42. package/package.json +20 -20
  43. package/dist/assets/ProgramHighlight-DPTeZ8Si.js +0 -3
  44. package/dist/assets/index-C4HZdhRu.js +0 -388
@@ -185,26 +185,6 @@ export const updateLast30Inspections = atom(null, (_, set, { evt, now, expire })
185
185
  return parts.union(LazySeq.of(log).toLookupMap((e) => e.key, (e) => e.entry.cntr, (e) => e.entry), (e1, e2) => e1.union(e2));
186
186
  });
187
187
  }
188
- else if (evt.editMaterialInLog) {
189
- const changedByCntr = evt.editMaterialInLog.editedEvents;
190
- set(last30InspectionsRW, (parts) => parts.collectValues((entries) => {
191
- for (const changed of changedByCntr) {
192
- // inspection logs have only a single material
193
- const mat = changed?.material[0];
194
- const old = entries.get(changed.counter);
195
- if (old !== undefined && mat) {
196
- const newEntry = {
197
- ...old,
198
- materialID: mat.id,
199
- serial: mat.serial,
200
- workorder: mat.workorder,
201
- };
202
- entries = entries.set(changed.counter, newEntry);
203
- }
204
- }
205
- return entries;
206
- }));
207
- }
208
188
  });
209
189
  export const setSpecificMonthInspections = atom(null, (_, set, log) => {
210
190
  set(specificMonthInspectionsRW, LazySeq.of(log)
@@ -122,7 +122,13 @@ export const inProcessMaterialInDialog = atom(async (get) => {
122
122
  if (toShow === null)
123
123
  return null;
124
124
  if (toShow.type === "InProcMat") {
125
- return status.material.find((m) => m.materialID === toShow.inproc.materialID) ?? null;
125
+ return (status.material.find((m) => m.materialID === toShow.inproc.materialID &&
126
+ (m.materialID >= 0 ||
127
+ (m.action.loadCancellationId === toShow.inproc.action.loadCancellationId &&
128
+ m.action.workId === toShow.inproc.action.workId &&
129
+ m.action.loadToBasketSlot === toShow.inproc.action.loadToBasketSlot &&
130
+ m.action.loadToBasketId === toShow.inproc.action.loadToBasketId &&
131
+ m.jobUnique === toShow.inproc.jobUnique))) ?? null);
126
132
  }
127
133
  const matId = (await get(materialInDialogInfo))?.materialID ?? null;
128
134
  return matId !== null && matId >= 0
@@ -30,7 +30,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
30
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
31
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
32
  */
33
- import { LogType, } from "../network/api.js";
33
+ import { LogType } from "../network/api.js";
34
34
  import { addDays } from "date-fns";
35
35
  import { HashMap, LazySeq, HashSet } from "@seedtactics/immutable-collections";
36
36
  import { atom } from "jotai";
@@ -203,88 +203,6 @@ function filter_old(expire, { matIdsForJob, matsById }) {
203
203
  matsById = matsById.filter((e) => e.last_event >= expire);
204
204
  return { matIdsForJob, matsById };
205
205
  }
206
- function process_swap(swap, st) {
207
- let jobs = st.matIdsForJob;
208
- const oldMatFromState = st.matsById.get(swap.oldMaterialID) ?? null;
209
- const newMatFromState = st.matsById.get(swap.newMaterialID) ?? null;
210
- if (oldMatFromState === null)
211
- return st;
212
- let oldMat = oldMatFromState;
213
- let newMat;
214
- if (newMatFromState === null) {
215
- newMat = {
216
- materialID: swap.newMaterialID,
217
- jobUnique: oldMat.jobUnique,
218
- partName: oldMat.partName,
219
- last_event: oldMat.last_event,
220
- numProcesses: oldMat.numProcesses,
221
- startedProcess1: true,
222
- unloaded_processes: {},
223
- signaledInspections: [],
224
- quarantineAfterUnload: null,
225
- completedInspections: {},
226
- };
227
- }
228
- else {
229
- newMat = newMatFromState;
230
- }
231
- if (oldMat.jobUnique &&
232
- oldMat.jobUnique !== "" &&
233
- (!newMat.jobUnique || newMat.jobUnique === "")) {
234
- // Swap newMat from raw material
235
- const forJob = jobs.get(oldMat.jobUnique);
236
- if (forJob !== undefined) {
237
- jobs = jobs.set(oldMat.jobUnique, forJob.delete(oldMat.materialID).add(newMat.materialID));
238
- }
239
- newMat = { ...newMat, jobUnique: oldMat.jobUnique };
240
- oldMat = { ...oldMat, jobUnique: "" };
241
- }
242
- const oldMatUnloads = oldMat.unloaded_processes;
243
- oldMat = { ...oldMat, unloaded_processes: newMat.unloaded_processes };
244
- newMat = { ...newMat, unloaded_processes: oldMatUnloads };
245
- for (const evt of swap.editedEvents) {
246
- const newMatFromEvt = evt.material.find((m) => m.id === swap.newMaterialID);
247
- if (newMatFromEvt) {
248
- newMat = {
249
- ...newMat,
250
- serial: newMatFromEvt.serial ?? newMat.serial,
251
- workorderId: newMatFromEvt.workorder ?? newMat.workorderId,
252
- };
253
- }
254
- switch (evt.type) {
255
- case LogType.Inspection:
256
- case LogType.InspectionForce: {
257
- const inspType = evt.program;
258
- let inspect;
259
- if (evt.result.toLowerCase() === "true" || evt.result === "1") {
260
- inspect = true;
261
- }
262
- else {
263
- inspect = false;
264
- }
265
- if (inspect) {
266
- // remove from oldMat, add to newMat
267
- oldMat = {
268
- ...oldMat,
269
- signaledInspections: LazySeq.of(oldMat.signaledInspections)
270
- .filter((i) => i !== inspType)
271
- .toRArray(),
272
- };
273
- newMat = {
274
- ...newMat,
275
- signaledInspections: LazySeq.of([...newMat.signaledInspections, inspType])
276
- .distinct()
277
- .toSortedArray((x) => x),
278
- };
279
- }
280
- }
281
- }
282
- }
283
- return {
284
- matsById: st.matsById.set(oldMat.materialID, oldMat).set(newMat.materialID, newMat),
285
- matIdsForJob: jobs,
286
- };
287
- }
288
206
  export const setLast30MatSummary = atom(null, (_, set, log) => {
289
207
  set(last30MaterialSummaryRW, (st) => log.reduce(process_event, st));
290
208
  });
@@ -301,10 +219,6 @@ export const updateLast30MatSummary = atom(null, (_, set, { evt, now, expire })
301
219
  }
302
220
  });
303
221
  }
304
- else if (evt.editMaterialInLog) {
305
- const edit = evt.editMaterialInLog;
306
- set(last30MaterialSummaryRW, (st) => process_swap(edit, st));
307
- }
308
222
  });
309
223
  export const setSpecificMonthMatSummary = atom(null, (_, set, log) => {
310
224
  set(specificMonthMaterialSummaryRW, log.reduce(process_event, {
@@ -43,6 +43,7 @@ export declare function loadStationDisplayName(stationNumber: number, loadStatio
43
43
  export declare function displayStationName(stationGroup: string, stationNumber: number, loadStationNames: {
44
44
  [key: string]: string;
45
45
  } | undefined): string;
46
+ export declare function basketSlotLabel(slot: number): string;
46
47
  export declare function basketDisplayName(basketName: string | null | undefined): string;
47
48
  export declare function carrierLabel(cycle: Readonly<PartCycleData>, basketName?: string): string;
48
49
  export declare function carrierSortKey(cycle: Readonly<PartCycleData>): number;
@@ -72,6 +72,17 @@ export function displayStationName(stationGroup, stationNumber, loadStationNames
72
72
  ? loadStationDisplayName(stationNumber, loadStationNames)
73
73
  : stat_name_and_num(stationGroup, stationNumber);
74
74
  }
75
+ // Basket slots retain one-based numeric identities in the API and persistence. The operator UI
76
+ // displays them alphabetically: 1=A, 2=B, ..., 26=Z, 27=AA.
77
+ export function basketSlotLabel(slot) {
78
+ if (!Number.isSafeInteger(slot) || slot <= 0)
79
+ return String(slot);
80
+ let label = "";
81
+ for (let remaining = slot; remaining > 0; remaining = Math.floor((remaining - 1) / 26)) {
82
+ label = String.fromCharCode(65 + ((remaining - 1) % 26)) + label;
83
+ }
84
+ return label;
85
+ }
75
86
  export function basketDisplayName(basketName) {
76
87
  return basketName && basketName.trim().length > 0 ? basketName : "Basket";
77
88
  }
@@ -151,16 +162,6 @@ function convertOldLogsToCycles(estimateCycleTimes, log, loadStationNames) {
151
162
  .collect((c) => convertLogToCycle(estimateCycleTimes, c.cycle, c.elapsedForSingleMaterialMinutes, loadStationNames))
152
163
  .buildHashMap((c) => c.cntr);
153
164
  }
154
- function process_swap(swap, partCycles) {
155
- for (const changed of swap.editedEvents) {
156
- const c = partCycles.get(changed.counter);
157
- if (c !== undefined) {
158
- const newC = { ...c, material: changed.material };
159
- partCycles = partCycles.set(changed.counter, newC);
160
- }
161
- }
162
- return partCycles;
163
- }
164
165
  export const setLast30StationCycles = atom(null, (get, set, log) => {
165
166
  const estimatedCycleTimes = get(last30EstimatedCycleTimes);
166
167
  const loadStationNames = get(fmsInformation)?.loadStationNames;
@@ -204,10 +205,6 @@ export const updateLast30StationCycles = atom(null, (get, set, { evt, now, expir
204
205
  return cycles;
205
206
  });
206
207
  }
207
- else if (evt.editMaterialInLog) {
208
- const edit = evt.editMaterialInLog;
209
- set(last30StationCyclesRW, (oldCycles) => process_swap(edit, oldCycles));
210
- }
211
208
  });
212
209
  export const setSpecificMonthStationCycles = atom(null, (get, set, log) => {
213
210
  const estimatedCycleTimes = get(specificMonthEstimatedCycleTimes);
@@ -86,25 +86,6 @@ function logType(entry, fmsInfo) {
86
86
  }
87
87
  case api.LogType.BasketCycle:
88
88
  return `${basketName} Cycle`;
89
- case api.LogType.BasketInLocation:
90
- if (entry.startofcycle) {
91
- return "Arrive";
92
- }
93
- else {
94
- return "Depart";
95
- }
96
- case api.LogType.BasketObservation:
97
- return `${basketName} Observation`;
98
- case api.LogType.BasketObservationCorrection:
99
- return `${basketName} Observation Correction`;
100
- case api.LogType.BasketContentSnapshot:
101
- return `${basketName} Content Snapshot`;
102
- case api.LogType.BasketRegionSurvey:
103
- return `${basketName} Region Survey`;
104
- case api.LogType.BasketMisload:
105
- return `${basketName} Misload`;
106
- case api.LogType.BasketMisloadResolution:
107
- return `${basketName} Misload Resolution`;
108
89
  case api.LogType.MachineCycle:
109
90
  if (entry.startofcycle) {
110
91
  return "Start Cycle";
@@ -149,12 +130,6 @@ function logType(entry, fmsInfo) {
149
130
  return "Message";
150
131
  }
151
132
  }
152
- function evidencePosition(entry) {
153
- const title = entry.details?.locationTitle ?? entry.details?.location ?? entry.loc;
154
- const locationNumber = entry.locnum > 0 ? ` ${entry.locnum}` : "";
155
- const zone = entry.details?.zone === undefined ? "" : ` zone ${entry.details.zone}`;
156
- return `${title}${locationNumber}${zone}`;
157
- }
158
133
  export function isLogEntryInvalidated(e) {
159
134
  return e.details?.["PalletCycleInvalidated"] === "1";
160
135
  }
@@ -207,52 +182,6 @@ function display(props, fmsInfo) {
207
182
  const basketName = basketDisplayName(fmsInfo.basketName);
208
183
  return _jsx("span", { children: basketCycleDescription(entry, basketName) });
209
184
  }
210
- case api.LogType.BasketInLocation: {
211
- const basketName = basketDisplayName(fmsInfo.basketName);
212
- if (entry.startofcycle) {
213
- return (_jsxs("span", { children: [basketContainerName(entry, basketName), " arrived at ", entry.loc, entry.locnum > 0 ? ` position ${entry.locnum}` : ""] }));
214
- }
215
- else {
216
- return (_jsxs("span", { children: [basketContainerName(entry, basketName), " departed from ", entry.loc, entry.locnum > 0 ? ` position ${entry.locnum}` : ""] }));
217
- }
218
- }
219
- case api.LogType.BasketObservation: {
220
- const basketName = basketDisplayName(fmsInfo.basketName);
221
- const episodeCount = entry.details?.episodeCount;
222
- const source = entry.details?.sourceName;
223
- const note = entry.details?.note;
224
- return (_jsxs("span", { children: [source ?? "Source", " observed ", basketName, " ", entry.pal, " at ", evidencePosition(entry), episodeCount === undefined || episodeCount === "0"
225
- ? ""
226
- : ` with direct continuity to ${episodeCount} tracked content episode${episodeCount === "1" ? "" : "s"}`, note === undefined ? "" : `: ${note}`] }));
227
- }
228
- case api.LogType.BasketObservationCorrection: {
229
- const basketName = basketDisplayName(fmsInfo.basketName);
230
- return (_jsxs("span", { children: ["Observation of ", basketName, " ", entry.pal, " corrected"] }));
231
- }
232
- case api.LogType.BasketContentSnapshot: {
233
- const basketName = basketDisplayName(fmsInfo.basketName);
234
- return (_jsxs("span", { children: [basketContainerName(entry, basketName), " contained ", displayMat(entry.material)] }));
235
- }
236
- case api.LogType.BasketRegionSurvey: {
237
- const basketName = basketDisplayName(fmsInfo.basketName);
238
- const source = entry.details?.sourceName;
239
- const observed = entry.details?.observedBasketCount;
240
- const unidentified = entry.details?.unidentifiedBasketCount;
241
- return (_jsxs("span", { children: [source === undefined ? "Operator" : source, " recorded a ", entry.result.toLowerCase(), " ", basketName.toLowerCase(), " survey at ", evidencePosition(entry), observed === undefined ? "" : ` (${observed} identified`, unidentified === undefined ? "" : `, ${unidentified} unidentified`, observed === undefined && unidentified === undefined ? "" : ")"] }));
242
- }
243
- case api.LogType.BasketMisload: {
244
- const basketName = basketDisplayName(fmsInfo.basketName);
245
- const source = entry.details?.sourceName;
246
- const reason = entry.details?.reason;
247
- const subject = entry.pal > 0 ? `${basketName} ${entry.pal}` : `Unnumbered ${basketName.toLowerCase()}`;
248
- return (_jsxs("span", { children: [source === undefined ? subject : `${source} reported ${subject}`, " requires inspection at", " ", evidencePosition(entry), reason === undefined ? "" : `: ${reason}`] }));
249
- }
250
- case api.LogType.BasketMisloadResolution: {
251
- const basketName = basketDisplayName(fmsInfo.basketName);
252
- const source = entry.details?.sourceName;
253
- const subject = entry.pal > 0 ? `${basketName} ${entry.pal}` : `Unnumbered ${basketName.toLowerCase()}`;
254
- return (_jsxs("span", { children: [source === undefined ? "Inspection hold" : `${source} resolved inspection hold`, " for", " ", subject, " at ", evidencePosition(entry), ": ", entry.result] }));
255
- }
256
185
  case api.LogType.MachineCycle:
257
186
  return (_jsxs("span", { children: [displayMat(entry.material), " on", " ", _jsxs(ColoredSpan, { $type: "pallet", children: ["pallet ", entry.pal] }), " at", " ", _jsxs(ColoredSpan, { $type: "machine", children: [entry.loc, " ", entry.locnum.toString()] }), entry.program && entry.program !== "" ? (_jsxs("span", { children: [" with program ", entry.program] })) : undefined] }));
258
187
  case api.LogType.PartMark:
@@ -1,6 +1,6 @@
1
1
  import * as api from "../network/api.js";
2
- type BasketNameEntry = Readonly<Pick<api.ILogEntry, "pal" | "basketContentEpisodeId">>;
3
- type BasketCycleEntry = BasketNameEntry & Readonly<Pick<api.ILogEntry, "startofcycle" | "basketCycleEndContentEpisodeIds">>;
2
+ type BasketNameEntry = Readonly<Pick<api.ILogEntry, "pal">>;
3
+ type BasketCycleEntry = BasketNameEntry & Readonly<Pick<api.ILogEntry, "startofcycle">>;
4
4
  export declare function basketContainerName(entry: BasketNameEntry, basketName: string): string;
5
5
  export declare function basketCycleDescription(entry: BasketCycleEntry, basketName: string): string;
6
6
  export {};
@@ -1,6 +1,4 @@
1
1
  export function basketContainerName(entry, basketName) {
2
- if (entry.basketContentEpisodeId)
3
- return `${basketName} fragment ${entry.basketContentEpisodeId.slice(0, 8)}`;
4
2
  if (entry.pal > 0)
5
3
  return `${basketName} ${entry.pal}`;
6
4
  return basketName;
@@ -9,9 +7,5 @@ export function basketCycleDescription(entry, basketName) {
9
7
  const container = basketContainerName(entry, basketName);
10
8
  if (entry.startofcycle)
11
9
  return `${container} started cycle`;
12
- const fragmentCount = entry.basketCycleEndContentEpisodeIds?.length ?? 0;
13
- const fragments = fragmentCount > 0
14
- ? ` from ${fragmentCount} UUID fragment${fragmentCount === 1 ? "" : "s"}`
15
- : "";
16
- return `${container} completed cycle${fragments}`;
10
+ return `${container} completed cycle`;
17
11
  }
@@ -39,7 +39,7 @@ import { Box } from "@mui/material";
39
39
  import { Typography } from "@mui/material";
40
40
  import { LazySeq } from "@seedtactics/immutable-collections";
41
41
  import { DragOverlayInProcMaterial, InProcMaterial, MaterialDialog, SortableInProcMaterial, } from "../station-monitor/Material.js";
42
- import { InvalidateCycleDialogButton, InvalidateCycleDialogContent, SwapMaterialButtons, SwapMaterialDialogContent, } from "../station-monitor/InvalidateCycle.js";
42
+ import { InvalidateCycleDialogButton, InvalidateCycleDialogContent, } from "../station-monitor/InvalidateCycle.js";
43
43
  import { horizontalListSortingStrategy, SortableContext, useSortable, verticalListSortingStrategy, } from "@dnd-kit/sortable";
44
44
  import { closestCenter, DndContext, DragOverlay, getFirstCollision, MeasuringStrategy, pointerWithin, rectIntersection, } from "@dnd-kit/core";
45
45
  import { QuarantineMatButton } from "../station-monitor/QuarantineButton.js";
@@ -147,13 +147,11 @@ function MaterialBinColumn({ matBin, isDragOverlay, }) {
147
147
  }
148
148
  }
149
149
  const AllMatDialog = memo(function AllMatDialog() {
150
- const [swapSt, setSwapSt] = useState(null);
151
150
  const [invalidateSt, setInvalidateSt] = useState(null);
152
151
  function onClose() {
153
- setSwapSt(null);
154
152
  setInvalidateSt(null);
155
153
  }
156
- 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] }), buttons: _jsxs(_Fragment, { children: [_jsx(QuarantineMatButton, { onClose: onClose, ignoreOperator: true }), _jsx(CancelLoadButton, { onClose: onClose, ignoreOperator: true }), _jsx(SwapMaterialButtons, { st: swapSt, setState: setSwapSt, onClose: onClose, ignoreOperator: true }), _jsx(InvalidateCycleDialogButton, { st: invalidateSt, setState: setInvalidateSt, onClose: onClose, ignoreOperator: true })] }) }));
154
+ return (_jsx(MaterialDialog, { onClose: onClose, allowNote: true, highlightProcsGreaterOrEqualTo: invalidateSt?.process ?? undefined, extraDialogElements: _jsx(_Fragment, { children: invalidateSt !== null ? (_jsx(InvalidateCycleDialogContent, { st: invalidateSt, setState: setInvalidateSt })) : null }), buttons: _jsxs(_Fragment, { children: [_jsx(QuarantineMatButton, { onClose: onClose, ignoreOperator: true }), _jsx(CancelLoadButton, { onClose: onClose, ignoreOperator: true }), _jsx(InvalidateCycleDialogButton, { st: invalidateSt, setState: setInvalidateSt, onClose: onClose, ignoreOperator: true })] }) }));
157
155
  });
158
156
  function useCollisionDetection(allBins) {
159
157
  return useCallback((args) => {
@@ -64,20 +64,20 @@ function sortPartSummary(parts, col, order) {
64
64
  case "Elapsed":
65
65
  sortCol = (j) => j.stationMins
66
66
  .toAscLazySeq()
67
- .filter(([_, stat]) => !stat.isLoadUnload)
67
+ .filter(([, stat]) => !stat.isLoadUnload)
68
68
  .sumBy(([, t]) => t.elapsed);
69
69
  break;
70
70
  case "Active":
71
71
  sortCol = (j) => j.stationMins
72
72
  .toAscLazySeq()
73
- .filter(([_, stat]) => !stat.isLoadUnload)
74
- .sumBy(([_, t]) => t.active);
73
+ .filter(([, stat]) => !stat.isLoadUnload)
74
+ .sumBy(([, t]) => t.active);
75
75
  break;
76
76
  case "Median":
77
77
  sortCol = (j) => j.stationMins
78
78
  .toAscLazySeq()
79
- .filter(([_, stat]) => !stat.isLoadUnload)
80
- .sumBy(([_, t]) => t.medianElapsed);
79
+ .filter(([, stat]) => !stat.isLoadUnload)
80
+ .sumBy(([, t]) => t.medianElapsed);
81
81
  break;
82
82
  }
83
83
  const sorted = [...parts];
@@ -183,13 +183,13 @@ const PartRow = memo(function PartRow({ part }) {
183
183
  display: "block",
184
184
  }, children: part.part }) })] }) }), _jsx(TableCell, { align: "right", children: part.completedQty }), _jsx(TableCell, { align: "right", children: part.abnormalQty }), _jsx(TableCell, { align: "right", children: numFormat.format(part.stationMins
185
185
  .toAscLazySeq()
186
- .filter(([_, stat]) => !stat.isLoadUnload)
187
- .sumBy(([_, t]) => t.active) / 60) }), _jsx(TableCell, { align: "right", children: numFormat.format(part.stationMins
186
+ .filter(([, stat]) => !stat.isLoadUnload)
187
+ .sumBy(([, t]) => t.active) / 60) }), _jsx(TableCell, { align: "right", children: numFormat.format(part.stationMins
188
188
  .toAscLazySeq()
189
- .filter(([_, stat]) => !stat.isLoadUnload)
189
+ .filter(([, stat]) => !stat.isLoadUnload)
190
190
  .sumBy(([, t]) => t.elapsed) / 60) }), _jsx(TableCell, { align: "right", children: numFormat.format(part.stationMins
191
191
  .toAscLazySeq()
192
- .filter(([_, stat]) => !stat.isLoadUnload)
192
+ .filter(([, stat]) => !stat.isLoadUnload)
193
193
  .sumBy(([, t]) => t.medianElapsed) / 60) }), _jsx(TableCell, { align: "left", children: part.workorders.size <= 1 ? (_jsx(WorkorderLink, { workorderId: part.workorders.lookupMin() ?? null })) : part.workorders.size === 2 ? (_jsxs("span", { children: [_jsx(WorkorderLink, { workorderId: part.workorders.lookupMin() }), " &", " ", _jsx(WorkorderLink, { workorderId: part.workorders.lookupMax() })] })) : (`${part.workorders.size} workorders`) }), _jsx(TableCell, { children: _jsx(Tooltip, { title: "Show Details", children: _jsx(IconButton, { size: "small", onClick: () => setOpen(!open), children: open ? _jsx(KeyboardArrowUpIcon, {}) : _jsx(KeyboardArrowDownIcon, {}) }) }) })] }), _jsx(TableRow, { children: _jsx(TableCell, { sx: { pb: "0", pt: "0" }, colSpan: partColCount + 1, children: _jsx(Collapse, { in: open, timeout: "auto", unmountOnExit: true, children: _jsx(PartDetails, { part: part }) }) }) })] }));
194
194
  });
195
195
  function CopyToClipboardBtn({ partsAtom }) {
@@ -275,7 +275,7 @@ function copyPartsToClipboard(parts) {
275
275
  for (const lul of [false, true]) {
276
276
  const stats = p.stationMins
277
277
  .toAscLazySeq()
278
- .filter(([_, stat]) => stat.isLoadUnload === lul)
278
+ .filter(([, stat]) => stat.isLoadUnload === lul)
279
279
  .toRArray();
280
280
  if (stats.length === 0) {
281
281
  table += `<td>0</td><td>0</td><td>0</td>`;
@@ -297,23 +297,30 @@ export function ProgramHistoryDialog() {
297
297
  const [loading, setLoading] = useState(false);
298
298
  const [error, setError] = useState(null);
299
299
  useEffect(() => {
300
- if (program === null) {
301
- setRevisions(null);
302
- setPage(0);
303
- setLastLoadedPage({ page: 0, hasMore: false });
304
- }
305
- else if (program !== null && revisions === null) {
306
- // load initial
307
- setLoading(true);
308
- setError(null);
309
- MachineBackend.getProgramRevisionsInDescendingOrderOfRevision(program.programName, revisionsPerPage, undefined)
310
- .then((revs) => {
311
- setRevisions(revs);
312
- setLastLoadedPage({ page: 0, hasMore: revs.length === revisionsPerPage });
313
- })
314
- .catch(setError)
315
- .finally(() => setLoading(false));
316
- }
300
+ const loadProgramDetails = async () => {
301
+ if (program === null) {
302
+ setRevisions(null);
303
+ setPage(0);
304
+ setLastLoadedPage({ page: 0, hasMore: false });
305
+ }
306
+ else if (program !== null && revisions === null) {
307
+ // load initial
308
+ setLoading(true);
309
+ setError(null);
310
+ try {
311
+ const revs = await MachineBackend.getProgramRevisionsInDescendingOrderOfRevision(program.programName, revisionsPerPage, undefined);
312
+ setRevisions(revs);
313
+ setLastLoadedPage({ page: 0, hasMore: revs.length === revisionsPerPage });
314
+ }
315
+ catch (err) {
316
+ setError(err instanceof Error ? err : String(err));
317
+ }
318
+ finally {
319
+ setLoading(false);
320
+ }
321
+ }
322
+ };
323
+ loadProgramDetails().catch(console.error);
317
324
  }, [program, revisions]);
318
325
  function advancePage() {
319
326
  if (page < lastLoadedPage.page) {
@@ -169,7 +169,7 @@ const RebookingDialog = memo(function RebookingDialog({ rebooking, close, }) {
169
169
  return (_jsxs(Dialog, { open: rebooking !== undefined, onClose: () => close(undefined), children: [_jsx(DialogTitle, { children: rebooking?.canceled ? (_jsx(Typography, { sx: { textDecoration: "line-through" }, children: rebooking?.bookingId })) : (rebooking?.bookingId) }), _jsx(DialogContent, { children: _jsxs(Stack, { direction: "column", spacing: 1, children: [rebooking?.canceled && (_jsxs(Typography, { variant: "h5", children: ["Canceled at ", longDateFormat.format(rebooking.canceled)] })), _jsxs(Stack, { direction: "row", spacing: 1, children: [_jsx("span", { children: "Part:" }), rebooking?.partName && _jsx(PartIdenticon, { part: rebooking?.partName, size: 25 }), _jsx("span", { children: rebooking?.partName })] }), _jsxs(Typography, { children: ["Quantity: ", rebooking?.quantity] }), _jsxs(Typography, { children: ["Request Time: ", longDateFormat.format(rebooking?.timeUTC)] }), _jsxs(Typography, { children: ["Priority: ", rebooking?.priority] }), rebooking?.workorder && _jsxs(Typography, { children: ["Workorder: ", rebooking?.workorder] }), _jsxs(Typography, { children: ["Note: ", rebooking?.notes] }), rebooking?.job && (_jsxs(_Fragment, { children: [_jsx(Divider, {}), _jsxs(Typography, { children: ["Scheduled Job: ", rebooking?.job] }), _jsxs(Typography, { children: ["Scheduled Time: ", rebooking?.schTime?.toLocaleString()] })] }))] }) }), _jsxs(DialogActions, { children: [!rebooking?.canceled && !rebooking?.job && (_jsxs(Button, { onClick: cancel, color: "secondary", disabled: canceling, children: [canceling ? _jsx(CircularProgress, { size: 24 }) : undefined, "Cancel Rebooking Request"] })), _jsx(Button, { onClick: () => close(undefined), children: "Close" })] })] }));
170
170
  });
171
171
  const partNamesAtom = atom((get) => LazySeq.ofObject(get(currentStatus).jobs)
172
- .map(([_, j]) => j.partName)
172
+ .map(([, j]) => j.partName)
173
173
  .concat(get(last30Jobs)
174
174
  .valuesToLazySeq()
175
175
  .map((j) => j.partName))
@@ -111,7 +111,7 @@ export function RecentFailedInspectionsTable() {
111
111
  const inspections = useAtomValue(last30Inspections);
112
112
  const failed = useMemo(() => {
113
113
  const today = startOfToday();
114
- const allEvts = LazySeq.of(inspections).flatMap(([_, evts]) => evts.valuesToLazySeq());
114
+ const allEvts = LazySeq.of(inspections).flatMap(([, evts]) => evts.valuesToLazySeq());
115
115
  return extractFailedInspections(allEvts, addDays(today, -4), addDays(today, 1));
116
116
  }, [inspections]);
117
117
  return (_jsxs("div", { children: [_jsxs(Box, { component: "nav", sx: {
@@ -231,10 +231,9 @@ export function useIsDemo() {
231
231
  return useAtomValue(isDemoAtom);
232
232
  }
233
233
  export function useSetTitle(title) {
234
- const demo = useIsDemo();
235
234
  useEffect(() => {
236
235
  document.title = title + " - FMS Insight";
237
- }, [demo, title]);
236
+ }, [title]);
238
237
  }
239
238
  export function helpUrl(r) {
240
239
  switch (r.route) {