@seedtactics/insight-client 17.0.1-beta.7 → 17.0.1-beta.8
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.
- package/dist/assets/index-MFZreX-b.js +388 -0
- package/dist/cell-status/inspections.js +0 -20
- package/dist/cell-status/material-summary.js +1 -87
- package/dist/cell-status/station-cycles.d.ts +1 -0
- package/dist/cell-status/station-cycles.js +11 -14
- package/dist/components/operations/AllMaterial.js +2 -4
- package/dist/components/station-monitor/BasketLoadStationWork.js +7 -4
- package/dist/components/station-monitor/InvalidateCycle.d.ts +1 -17
- package/dist/components/station-monitor/InvalidateCycle.js +1 -91
- package/dist/components/station-monitor/LoadStation.js +3 -5
- package/dist/components/station-monitor/Material.js +5 -3
- package/dist/components/station-monitor/SystemOverview.js +2 -4
- package/dist/index.html +1 -1
- package/dist/network/api.d.ts +2 -32
- package/dist/network/api.js +2 -116
- package/dist/network/backend-mock.js +0 -3
- package/dist/network/backend.d.ts +0 -1
- package/docs/operator-procedures.md +6 -6
- package/package.json +1 -1
- package/dist/assets/index-CNJT3DX_.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)
|
|
@@ -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
|
|
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);
|
|
@@ -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,
|
|
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:
|
|
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) => {
|
|
@@ -31,6 +31,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
31
31
|
import { useMemo, useState } from "react";
|
|
32
32
|
import { Alert, Box, Button, Stack, Typography } from "@mui/material";
|
|
33
33
|
import { LazySeq } from "@seedtactics/immutable-collections";
|
|
34
|
+
import { basketSlotLabel } from "../../cell-status/station-cycles.js";
|
|
34
35
|
import * as api from "../../network/api.js";
|
|
35
36
|
import { InProcMaterial } from "./Material.js";
|
|
36
37
|
import { MoveMaterialArrowNode } from "./MoveMaterialArrows.js";
|
|
@@ -140,6 +141,7 @@ function SlotMaterial({ material, fsize, }) {
|
|
|
140
141
|
export function BasketLoadStationWorkflow({ stationNumber, basket, material, fsize, submitCommand, }) {
|
|
141
142
|
const [submission, setSubmission] = useState();
|
|
142
143
|
const workState = useMemo(() => stationWork(material, basket), [basket, material]);
|
|
144
|
+
const blockedReason = basket.loadStationWork?.confirmationBlockedReason?.trim();
|
|
143
145
|
const work = workState.type === "active" ? workState.work : undefined;
|
|
144
146
|
const submissionState = submission !== undefined &&
|
|
145
147
|
submission.workId === work?.workId &&
|
|
@@ -197,8 +199,9 @@ export function BasketLoadStationWorkflow({ stationNumber, basket, material, fsi
|
|
|
197
199
|
type: MoveMaterialNodeKindType.BasketSlotZone,
|
|
198
200
|
basketId: basket.basketId,
|
|
199
201
|
slot,
|
|
200
|
-
}, children: _jsxs(Box, { component: "section", "data-testid": `basket-load-station-slot-${slot}`, sx: { border: "1px solid", borderColor: "text.primary", p: 2 }, children: [_jsxs(Typography, { variant: "h6", children: ["Slot ", slot] }), slotMaterial.length > 0 ? (_jsx(SlotMaterial, { material: slotMaterial, fsize: fsize })) : (_jsx(Typography, { color: isUnknown ? "warning.main" : "text.secondary", children: isUnknown ? "Unknown" : "Empty" })), loads.map((mat, index) => (_jsxs(Box, { sx: { mt: 1 }, children: [_jsx(Typography, { children: loadingInstruction(mat) }), _jsxs(Typography, { variant: "body2", color: "text.secondary", children: [mat.partName, " \u00B7 Process ", mat.action.processAfterLoad ?? mat.process] })] }, `${mat.jobUnique}-${mat.process}-${index}`)))] }) }, slot));
|
|
201
|
-
}) }), work?.confirmEmpty && _jsxs(Typography, { children: ["Confirm basket ", basket.basketId, " is empty."] }), work && !work.ready && (_jsx(Alert, { severity: "info", children:
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
}, children: _jsxs(Box, { component: "section", "data-testid": `basket-load-station-slot-${slot}`, sx: { border: "1px solid", borderColor: "text.primary", p: 2 }, children: [_jsxs(Typography, { variant: "h6", children: ["Slot ", basketSlotLabel(slot)] }), slotMaterial.length > 0 ? (_jsx(SlotMaterial, { material: slotMaterial, fsize: fsize })) : (_jsx(Typography, { color: isUnknown ? "warning.main" : "text.secondary", children: isUnknown ? "Unknown" : "Empty" })), loads.map((mat, index) => (_jsxs(Box, { sx: { mt: 1 }, children: [_jsx(Typography, { children: loadingInstruction(mat) }), _jsxs(Typography, { variant: "body2", color: "text.secondary", children: [mat.partName, " \u00B7 Process ", mat.action.processAfterLoad ?? mat.process] })] }, `${mat.jobUnique}-${mat.process}-${index}`)))] }) }, slot));
|
|
203
|
+
}) }), work?.confirmEmpty && _jsxs(Typography, { children: ["Confirm basket ", basket.basketId, " is empty."] }), work && !work.ready && (_jsx(Alert, { severity: "info", children: blockedReason ||
|
|
204
|
+
(work.awaitingSlots.length > 0
|
|
205
|
+
? `Waiting for material for slots ${work.awaitingSlots.map(basketSlotLabel).join(", ")}.`
|
|
206
|
+
: "Basket work is not ready for confirmation.") })), work && submitCommand ? (_jsx(Box, { sx: { display: "flex", justifyContent: "flex-end" }, children: _jsx(Button, { variant: "contained", disabled: submissionDisabled, onClick: () => void submit(), children: "Confirm" }) })) : work ? (_jsx(Alert, { severity: "warning", children: "Basket work confirmation is not configured." })) : workState.type === "inconsistent" ? (_jsx(Alert, { severity: "warning", children: "Basket work is inconsistent. Wait for refreshed material actions before confirming." })) : null, submissionState === "accepted" ? (_jsx(Alert, { severity: "success", children: "Confirmation accepted. Waiting for refreshed work." })) : submissionState === "conflict" ? (_jsx(Alert, { severity: "warning", children: "Basket work changed before confirmation. Review the refreshed slots and try again." })) : submissionState === "error" ? (_jsx(Alert, { severity: "error", children: "Unable to confirm basket work. No work was assumed complete." })) : null] }));
|
|
204
207
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ILogEntry } from "../../network/api.js";
|
|
2
2
|
import { HashMap } from "@seedtactics/immutable-collections";
|
|
3
|
-
import { ReactNode } from "react";
|
|
4
3
|
export type InvalidateCycleState = {
|
|
5
4
|
readonly process: number | null;
|
|
6
5
|
readonly changeRawMat: string | null;
|
|
@@ -19,18 +18,3 @@ export declare function InvalidateCycleDialogButton(props: InvalidateCycleProps
|
|
|
19
18
|
readonly ignoreOperator?: boolean;
|
|
20
19
|
readonly loadStation?: boolean;
|
|
21
20
|
}): import("react").JSX.Element | null;
|
|
22
|
-
interface SwapMaterial {
|
|
23
|
-
readonly selectedMatToSwap: Readonly<IInProcessMaterial> | null;
|
|
24
|
-
readonly updating: boolean;
|
|
25
|
-
}
|
|
26
|
-
export type SwapMaterialState = SwapMaterial | null;
|
|
27
|
-
export interface SwapMaterialProps {
|
|
28
|
-
readonly st: SwapMaterialState;
|
|
29
|
-
readonly setState: (s: SwapMaterialState) => void;
|
|
30
|
-
}
|
|
31
|
-
export declare function SwapMaterialDialogContent(props: SwapMaterialProps): ReactNode;
|
|
32
|
-
export declare function SwapMaterialButtons(props: SwapMaterialProps & {
|
|
33
|
-
readonly onClose: () => void;
|
|
34
|
-
readonly ignoreOperator?: boolean;
|
|
35
|
-
}): import("react").JSX.Element | null;
|
|
36
|
-
export {};
|
|
@@ -47,14 +47,12 @@ import { last30Jobs } from "../../cell-status/scheduled-jobs.js";
|
|
|
47
47
|
import { PartIdenticon } from "./Material.js";
|
|
48
48
|
import { isLogEntryInvalidated } from "../LogEntry.js";
|
|
49
49
|
import { ApiException } from "../../network/api.js";
|
|
50
|
-
import { canInvalidateMaterial
|
|
50
|
+
import { canInvalidateMaterial } from "../../data/material-operation-policy.js";
|
|
51
51
|
const invalidatableEventTypes = LazySeq.of([
|
|
52
52
|
LogType.AddToQueue,
|
|
53
53
|
LogType.RemoveFromQueue,
|
|
54
54
|
LogType.LoadUnloadCycle,
|
|
55
55
|
LogType.MachineCycle,
|
|
56
|
-
LogType.BasketLoadUnload,
|
|
57
|
-
LogType.BasketCycle,
|
|
58
56
|
]).toRSet((eventType) => eventType);
|
|
59
57
|
export function affectedMaterialForInvalidation(events, materialId, process) {
|
|
60
58
|
let affected = HashMap.empty();
|
|
@@ -245,91 +243,3 @@ export function InvalidateCycleDialogButton(props) {
|
|
|
245
243
|
: "Invalidate Process " + props.st.process.toString()
|
|
246
244
|
: "Invalidate Cycle" })) : undefined] }));
|
|
247
245
|
}
|
|
248
|
-
function isNullOrEmpty(s) {
|
|
249
|
-
return s === undefined || s === null || s == "";
|
|
250
|
-
}
|
|
251
|
-
function matCanSwap(curMat, job) {
|
|
252
|
-
return (newMat) => {
|
|
253
|
-
if (isNullOrEmpty(newMat.serial))
|
|
254
|
-
return false;
|
|
255
|
-
if (newMat.location.type === LocType.OnPallet)
|
|
256
|
-
return false;
|
|
257
|
-
if (newMat.process !== curMat.process - 1)
|
|
258
|
-
return false;
|
|
259
|
-
if (isNullOrEmpty(newMat.jobUnique)) {
|
|
260
|
-
// if part name is wrong, check casting
|
|
261
|
-
if (isNullOrEmpty(newMat.partName))
|
|
262
|
-
return false;
|
|
263
|
-
if (newMat.partName !== curMat.partName) {
|
|
264
|
-
if (!job)
|
|
265
|
-
return false;
|
|
266
|
-
if (!LazySeq.of(job.procsAndPaths)
|
|
267
|
-
.flatMap((p) => p.paths)
|
|
268
|
-
.some((p) => p.casting === newMat.partName)) {
|
|
269
|
-
return false;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
else {
|
|
274
|
-
// check path
|
|
275
|
-
if (newMat.jobUnique !== curMat.jobUnique)
|
|
276
|
-
return false;
|
|
277
|
-
if (newMat.path !== curMat.path)
|
|
278
|
-
return false;
|
|
279
|
-
}
|
|
280
|
-
return true;
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
export function SwapMaterialDialogContent(props) {
|
|
284
|
-
const status = useAtomValue(currentStatus);
|
|
285
|
-
const curMat = useAtomValue(inProcessMaterialInDialog);
|
|
286
|
-
if (curMat === null || props.st === null)
|
|
287
|
-
return _jsx("div", {});
|
|
288
|
-
const curMatJob = status.jobs[curMat.jobUnique];
|
|
289
|
-
const availMats = status.material.filter(matCanSwap(curMat, curMatJob));
|
|
290
|
-
if (availMats.length === 0) {
|
|
291
|
-
return (_jsx("p", { style: { margin: "2em" }, children: "No material with the same job is available for swapping. You must edit the pallet using the cell controller software to remove the material from the pallet. Insight will automatically refresh once the cell controller software is updated." }));
|
|
292
|
-
}
|
|
293
|
-
else {
|
|
294
|
-
return (_jsxs("div", { style: { margin: "2em" }, children: [_jsx("p", { children: "Swap serial on pallet with material from the same job." }), _jsx("p", { children: "If material on the pallet is from a different job, you cannot use this screen. Instead, the material must first be removed from the pallet using the cell controller software. Insight will automatically refresh when this occurs." }), _jsx(TextField, { value: props.st?.selectedMatToSwap?.serial ?? "", select: true, onChange: (e) => props.st &&
|
|
295
|
-
props.setState({
|
|
296
|
-
...props.st,
|
|
297
|
-
selectedMatToSwap: availMats.find((m) => m.serial === e.target.value) ?? null,
|
|
298
|
-
}), style: { width: "20em" }, variant: "outlined", label: "Select serial to swap with " + (curMat.serial ?? ""), children: availMats.map((m) => (_jsx(MenuItem, { value: m.serial, children: m.serial }, m.materialID))) })] }));
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
export function SwapMaterialButtons(props) {
|
|
302
|
-
const fmsInfo = useAtomValue(fmsInformation);
|
|
303
|
-
const curMat = useAtomValue(inProcessMaterialInDialog);
|
|
304
|
-
const closeMatDialog = useSetAtom(materialDialogOpen);
|
|
305
|
-
let operator = useAtomValue(currentOperator);
|
|
306
|
-
if (!fmsInfo.allowSwapSerialAtLoadStation)
|
|
307
|
-
return null;
|
|
308
|
-
if (props.ignoreOperator)
|
|
309
|
-
operator = null;
|
|
310
|
-
if (!curMat ||
|
|
311
|
-
curMat.location.type !== LocType.OnPallet ||
|
|
312
|
-
isActiveLoadStationOperation(curMat)) {
|
|
313
|
-
return null;
|
|
314
|
-
}
|
|
315
|
-
function swapMats() {
|
|
316
|
-
if (curMat &&
|
|
317
|
-
props.st &&
|
|
318
|
-
props.st.selectedMatToSwap &&
|
|
319
|
-
curMat.location.type === LocType.OnPallet) {
|
|
320
|
-
props.setState({ selectedMatToSwap: props.st.selectedMatToSwap, updating: true });
|
|
321
|
-
JobsBackend.swapMaterialOnPallet(curMat.materialID, operator, {
|
|
322
|
-
pallet: curMat.location.palletNum ?? 0,
|
|
323
|
-
materialIDToSetOnPallet: props.st.selectedMatToSwap.materialID,
|
|
324
|
-
})
|
|
325
|
-
.catch(console.log)
|
|
326
|
-
.finally(() => {
|
|
327
|
-
closeMatDialog(null);
|
|
328
|
-
props.onClose();
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
return (_jsxs(_Fragment, { children: [props.st === null ? (_jsx(Button, { color: "primary", onClick: () => props.setState({ selectedMatToSwap: null, updating: false }), children: "Swap Serial" })) : undefined, props.st !== null ? (_jsx(Button, { color: "primary", onClick: swapMats, disabled: props.st.selectedMatToSwap === null || props.st.updating, children: props.st.selectedMatToSwap === null
|
|
333
|
-
? "Swap Serial"
|
|
334
|
-
: "Swap with " + (props.st.selectedMatToSwap.serial ?? "") })) : undefined] }));
|
|
335
|
-
}
|
|
@@ -54,7 +54,7 @@ import { QuarantineMatButton } from "./QuarantineButton.js";
|
|
|
54
54
|
import { CancelLoadButton } from "./CancelLoadButton.js";
|
|
55
55
|
import { durationToSeconds } from "../../util/parseISODuration.js";
|
|
56
56
|
import { formatSeconds } from "./SystemOverview.js";
|
|
57
|
-
import { InvalidateCycleDialogButton, InvalidateCycleDialogContent,
|
|
57
|
+
import { InvalidateCycleDialogButton, InvalidateCycleDialogContent, } from "./InvalidateCycle.js";
|
|
58
58
|
import { last30MaterialSummary } from "../../cell-status/material-summary.js";
|
|
59
59
|
import { addHours } from "date-fns";
|
|
60
60
|
import { PromptForQueue } from "./QueuesAddMaterial.js";
|
|
@@ -625,18 +625,16 @@ function AssignWorkorderButton() {
|
|
|
625
625
|
return (_jsx(Button, { color: "primary", onClick: () => setWorkorderDialogOpen(true), children: "Assign Workorder" }));
|
|
626
626
|
}
|
|
627
627
|
const LoadMatDialog = memo(function LoadMatDialog(props) {
|
|
628
|
-
const [swapSt, setSwapSt] = useState(null);
|
|
629
628
|
const [invalidateSt, setInvalidateSt] = useState(null);
|
|
630
629
|
// add material state
|
|
631
630
|
const [showAddMaterial, setShowAddMaterial] = useState(false);
|
|
632
631
|
const [selectedQueue, setSelectedQueue] = useState(null);
|
|
633
632
|
const onClose = useCallback(function onClose() {
|
|
634
|
-
setSwapSt(null);
|
|
635
633
|
setInvalidateSt(null);
|
|
636
634
|
setShowAddMaterial(false);
|
|
637
635
|
setSelectedQueue(null);
|
|
638
|
-
}, [
|
|
639
|
-
return (_jsx(MaterialDialog, { onClose: onClose, allowNote: true, highlightProcsGreaterOrEqualTo: invalidateSt?.process ?? undefined, extraDialogElements: _jsxs(_Fragment, { children: [
|
|
636
|
+
}, [setInvalidateSt]);
|
|
637
|
+
return (_jsx(MaterialDialog, { onClose: onClose, allowNote: true, highlightProcsGreaterOrEqualTo: invalidateSt?.process ?? undefined, extraDialogElements: _jsxs(_Fragment, { children: [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(InvalidateCycleDialogButton, { st: invalidateSt, setState: setInvalidateSt, onClose: onClose, loadStation: true }), _jsx(AssignWorkorderButton, {})] }) }));
|
|
640
638
|
});
|
|
641
639
|
function useGridLayout({ numMatCols, maxNumFaces, horizontal, showMatInCompleted, }) {
|
|
642
640
|
let rows = "";
|
|
@@ -48,7 +48,7 @@ import { currentStatus } from "../../cell-status/current-status.js";
|
|
|
48
48
|
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
|
-
import { basketDisplayName } from "../../cell-status/station-cycles.js";
|
|
51
|
+
import { basketDisplayName, basketSlotLabel } from "../../cell-status/station-cycles.js";
|
|
52
52
|
import { materialOperationState } from "../../data/material-operation-policy.js";
|
|
53
53
|
export class PartIdenticon extends PureComponent {
|
|
54
54
|
render() {
|
|
@@ -236,12 +236,14 @@ export function MaterialAction({ mat, displayActionForSinglePallet, fsize, }) {
|
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
238
|
case api.ActionType.LoadingToBasket:
|
|
239
|
-
return (_jsxs(MatCardDetail, { fsize: fsize, children: ["Load into ", basketName, " ", mat.action.loadToBasketId ?? "", mat.action.loadToBasketSlot !== undefined
|
|
239
|
+
return (_jsxs(MatCardDetail, { fsize: fsize, children: ["Load into ", basketName, " ", mat.action.loadToBasketId ?? "", mat.action.loadToBasketSlot !== undefined
|
|
240
|
+
? ` slot ${basketSlotLabel(mat.action.loadToBasketSlot)}`
|
|
241
|
+
: ""] }));
|
|
240
242
|
case api.ActionType.UnloadToInProcess:
|
|
241
243
|
case api.ActionType.UnloadToCompletedMaterial:
|
|
242
244
|
if (mat.action.unloadToBasketId) {
|
|
243
245
|
return (_jsxs(MatCardDetail, { fsize: fsize, children: ["Unload to ", basketName, " ", mat.action.unloadToBasketId, mat.action.unloadToBasketSlot !== undefined
|
|
244
|
-
? ` slot ${mat.action.unloadToBasketSlot}`
|
|
246
|
+
? ` slot ${basketSlotLabel(mat.action.unloadToBasketSlot)}`
|
|
245
247
|
: ""] }));
|
|
246
248
|
}
|
|
247
249
|
else if (mat.action.unloadIntoQueue) {
|
|
@@ -42,7 +42,7 @@ import { materialDialogOpen } from "../../cell-status/material-details.js";
|
|
|
42
42
|
import { last30Jobs } from "../../cell-status/scheduled-jobs.js";
|
|
43
43
|
import { addDays } from "date-fns";
|
|
44
44
|
import { durationToSeconds } from "../../util/parseISODuration.js";
|
|
45
|
-
import { InvalidateCycleDialogButton, InvalidateCycleDialogContent,
|
|
45
|
+
import { InvalidateCycleDialogButton, InvalidateCycleDialogContent, } from "./InvalidateCycle.js";
|
|
46
46
|
import { CancelLoadButton } from "./CancelLoadButton.js";
|
|
47
47
|
import { QuarantineMatButton } from "./QuarantineButton.js";
|
|
48
48
|
import { SelectInspTypeDialog, SignalInspectionButton } from "./SelectInspType.js";
|
|
@@ -824,13 +824,11 @@ export const SystemOverview = memo(function SystemOverview({ overview, }) {
|
|
|
824
824
|
}, children: [overview.stockerPals.map((pal) => (_jsx(StockerPallet, { pallet: pal, maxNumFaces: overview.maxNumFacesOnPallet }, pal.pallet.palletNum))), overview.floatingBaskets.map((basket) => (_jsx(FloatingBasket, { basket: basket }, basket.basket.basketId))), overview.storageBaskets ? (_jsx(BasketStorageSummary, { empty: overview.storageBaskets.empty, filled: overview.storageBaskets.filled })) : undefined] })) : undefined] }));
|
|
825
825
|
});
|
|
826
826
|
const SystemOverviewMaterialDialog = memo(function SystemOverviewMaterialDialog({ ignoreOperator, }) {
|
|
827
|
-
const [swapSt, setSwapSt] = useState(null);
|
|
828
827
|
const [invalidateSt, setInvalidateSt] = useState(null);
|
|
829
828
|
function onClose() {
|
|
830
|
-
setSwapSt(null);
|
|
831
829
|
setInvalidateSt(null);
|
|
832
830
|
}
|
|
833
|
-
return (_jsx(MaterialDialog, { onClose: onClose, allowNote: true, highlightProcsGreaterOrEqualTo: invalidateSt?.process ?? undefined, extraDialogElements:
|
|
831
|
+
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, { ignoreOperator: ignoreOperator }), _jsx(CancelLoadButton, { onClose: onClose, ignoreOperator: ignoreOperator }), _jsx(SignalInspectionButton, {}), _jsx(InvalidateCycleDialogButton, { st: invalidateSt, setState: setInvalidateSt, onClose: onClose, ignoreOperator: ignoreOperator })] }) }));
|
|
834
832
|
});
|
|
835
833
|
export function SystemOverviewPage({ ignoreOperator, whiteBackground, }) {
|
|
836
834
|
useSetTitle("System Overview");
|
package/dist/index.html
CHANGED
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
</style>
|
|
46
|
-
<script type="module" crossorigin src="/assets/index-
|
|
46
|
+
<script type="module" crossorigin src="/assets/index-MFZreX-b.js"></script>
|
|
47
47
|
<link rel="stylesheet" crossorigin href="/assets/index-DXfAwuj-.css">
|
|
48
48
|
</head>
|
|
49
49
|
<body>
|
package/dist/network/api.d.ts
CHANGED
|
@@ -59,8 +59,6 @@ export declare class JobsClient {
|
|
|
59
59
|
protected processCancelLoad(response: Response): Promise<void>;
|
|
60
60
|
invalidatePalletCycle(materialId: number, operName: string | null | undefined, changeCastingTo: string | null | undefined, changeJobUniqueTo: string | null | undefined, process: number, signal?: AbortSignal): Promise<MaterialDetails>;
|
|
61
61
|
protected processInvalidatePalletCycle(response: Response): Promise<MaterialDetails>;
|
|
62
|
-
swapMaterialOnPallet(materialId: number, operName: string | null | undefined, mat: MatToPutOnPallet, signal?: AbortSignal): Promise<void>;
|
|
63
|
-
protected processSwapMaterialOnPallet(response: Response): Promise<void>;
|
|
64
62
|
bulkRemoveMaterialFromQueues(operName: string | null | undefined, id: number[], signal?: AbortSignal): Promise<void>;
|
|
65
63
|
protected processBulkRemoveMaterialFromQueues(response: Response): Promise<void>;
|
|
66
64
|
decrementQuantities(loadDecrementsStrictlyAfterDecrementId: number | null | undefined, loadDecrementsAfterTimeUTC: Date | null | undefined, signal?: AbortSignal): Promise<JobAndDecrementQuantity[]>;
|
|
@@ -148,7 +146,6 @@ export declare class FMSInfo implements IFMSInfo {
|
|
|
148
146
|
customStationMonitorDialogUrl?: string | undefined;
|
|
149
147
|
supportsRebookings?: string | undefined;
|
|
150
148
|
allowChangeWorkorderAtLoadStation?: boolean | undefined;
|
|
151
|
-
allowSwapSerialAtLoadStation?: boolean | undefined;
|
|
152
149
|
allowInvalidateMaterialAtLoadStation?: boolean | undefined;
|
|
153
150
|
loadStationNames?: {
|
|
154
151
|
[key: string]: string;
|
|
@@ -179,7 +176,6 @@ export interface IFMSInfo {
|
|
|
179
176
|
customStationMonitorDialogUrl?: string | undefined;
|
|
180
177
|
supportsRebookings?: string | undefined;
|
|
181
178
|
allowChangeWorkorderAtLoadStation?: boolean | undefined;
|
|
182
|
-
allowSwapSerialAtLoadStation?: boolean | undefined;
|
|
183
179
|
allowInvalidateMaterialAtLoadStation?: boolean | undefined;
|
|
184
180
|
loadStationNames?: {
|
|
185
181
|
[key: string]: string;
|
|
@@ -202,7 +198,6 @@ export declare class ServerEvent implements IServerEvent {
|
|
|
202
198
|
logEntry?: LogEntry | undefined;
|
|
203
199
|
newJobs?: NewJobs | undefined;
|
|
204
200
|
newCurrentStatus?: CurrentStatus | undefined;
|
|
205
|
-
editMaterialInLog?: EditMaterialInLogEvents | undefined;
|
|
206
201
|
constructor(data?: IServerEvent);
|
|
207
202
|
init(_data?: any): void;
|
|
208
203
|
static fromJS(data: any): ServerEvent;
|
|
@@ -212,7 +207,6 @@ export interface IServerEvent {
|
|
|
212
207
|
logEntry?: LogEntry | undefined;
|
|
213
208
|
newJobs?: NewJobs | undefined;
|
|
214
209
|
newCurrentStatus?: CurrentStatus | undefined;
|
|
215
|
-
editMaterialInLog?: EditMaterialInLogEvents | undefined;
|
|
216
210
|
}
|
|
217
211
|
export declare class LogEntry implements ILogEntry {
|
|
218
212
|
counter: number;
|
|
@@ -1080,6 +1074,7 @@ export declare class BasketLoadStationWork implements IBasketLoadStationWork {
|
|
|
1080
1074
|
workId: string;
|
|
1081
1075
|
type: BasketLoadStationWorkType;
|
|
1082
1076
|
readyToConfirm: boolean;
|
|
1077
|
+
confirmationBlockedReason?: string | undefined;
|
|
1083
1078
|
awaitingMaterialSlots?: number[];
|
|
1084
1079
|
constructor(data?: IBasketLoadStationWork);
|
|
1085
1080
|
init(_data?: any): void;
|
|
@@ -1090,6 +1085,7 @@ export interface IBasketLoadStationWork {
|
|
|
1090
1085
|
workId: string;
|
|
1091
1086
|
type: BasketLoadStationWorkType;
|
|
1092
1087
|
readyToConfirm: boolean;
|
|
1088
|
+
confirmationBlockedReason?: string | undefined;
|
|
1093
1089
|
awaitingMaterialSlots?: number[];
|
|
1094
1090
|
}
|
|
1095
1091
|
export declare enum BasketLoadStationWorkType {
|
|
@@ -1150,20 +1146,6 @@ export declare enum BasketMoveReason {
|
|
|
1150
1146
|
RemoveForCorrection = "RemoveForCorrection",
|
|
1151
1147
|
Other = "Other"
|
|
1152
1148
|
}
|
|
1153
|
-
export declare class EditMaterialInLogEvents implements IEditMaterialInLogEvents {
|
|
1154
|
-
oldMaterialID: number;
|
|
1155
|
-
newMaterialID: number;
|
|
1156
|
-
editedEvents: LogEntry[];
|
|
1157
|
-
constructor(data?: IEditMaterialInLogEvents);
|
|
1158
|
-
init(_data?: any): void;
|
|
1159
|
-
static fromJS(data: any): EditMaterialInLogEvents;
|
|
1160
|
-
toJSON(data?: any): any;
|
|
1161
|
-
}
|
|
1162
|
-
export interface IEditMaterialInLogEvents {
|
|
1163
|
-
oldMaterialID: number;
|
|
1164
|
-
newMaterialID: number;
|
|
1165
|
-
editedEvents: LogEntry[];
|
|
1166
|
-
}
|
|
1167
1149
|
export declare class ProblemDetails implements IProblemDetails {
|
|
1168
1150
|
type?: string | undefined;
|
|
1169
1151
|
title?: string | undefined;
|
|
@@ -1400,18 +1382,6 @@ export interface ICancelLoadRequest {
|
|
|
1400
1382
|
expectedLoadCancellationId: string;
|
|
1401
1383
|
reason?: string | undefined;
|
|
1402
1384
|
}
|
|
1403
|
-
export declare class MatToPutOnPallet implements IMatToPutOnPallet {
|
|
1404
|
-
pallet: number;
|
|
1405
|
-
materialIDToSetOnPallet: number;
|
|
1406
|
-
constructor(data?: IMatToPutOnPallet);
|
|
1407
|
-
init(_data?: any): void;
|
|
1408
|
-
static fromJS(data: any): MatToPutOnPallet;
|
|
1409
|
-
toJSON(data?: any): any;
|
|
1410
|
-
}
|
|
1411
|
-
export interface IMatToPutOnPallet {
|
|
1412
|
-
pallet: number;
|
|
1413
|
-
materialIDToSetOnPallet: number;
|
|
1414
|
-
}
|
|
1415
1385
|
export declare class JobAndDecrementQuantity implements IJobAndDecrementQuantity {
|
|
1416
1386
|
decrementId: number;
|
|
1417
1387
|
jobUnique: string;
|