@seedtactics/insight-client 17.0.0-beta.0 → 17.0.0-beta.2
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-BkKYqUM0.js → index-BvhibzJZ.js} +61 -61
- package/dist/cell-status/rebookings.d.ts +1 -0
- package/dist/cell-status/rebookings.js +4 -1
- package/dist/components/App.d.ts +3 -0
- package/dist/components/App.js +1 -1
- package/dist/components/LogEntry.js +65 -4
- package/dist/components/station-monitor/BasketLoadStationWork.js +6 -2
- package/dist/components/station-monitor/BasketMovementArrival.d.ts +38 -0
- package/dist/components/station-monitor/BasketMovementArrival.js +175 -0
- package/dist/components/station-monitor/LoadStation.d.ts +3 -0
- package/dist/components/station-monitor/LoadStation.js +79 -27
- package/dist/components/station-monitor/Material.js +2 -0
- package/dist/data/move-arrows.d.ts +6 -1
- package/dist/data/move-arrows.js +14 -2
- package/dist/extension.d.ts +1 -0
- package/dist/index.html +1 -1
- package/dist/network/api.d.ts +14 -4
- package/dist/network/api.js +14 -4
- package/dist/network/backend.d.ts +1 -1
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import { Atom } from "jotai";
|
|
|
2
2
|
import { ServerEventAndTime } from "./loading";
|
|
3
3
|
import { ILogEntry, IRebooking, IRecentHistoricData } from "../network/api";
|
|
4
4
|
import { OrderedMap } from "@seedtactics/immutable-collections";
|
|
5
|
+
export declare function mapUnscheduledRebookings(bookings: ReadonlyArray<Readonly<IRebooking>> | null | undefined): OrderedMap<string, Readonly<IRebooking>>;
|
|
5
6
|
export declare const last30Rebookings: Atom<OrderedMap<string, Readonly<IRebooking>>>;
|
|
6
7
|
export declare const canceledRebookings: Atom<OrderedMap<string, Date>>;
|
|
7
8
|
type ScheduledBooking = {
|
|
@@ -46,8 +46,11 @@ const unschRebookings = unwrap(atom(async (_, { signal }) => {
|
|
|
46
46
|
return OrderedMap.empty();
|
|
47
47
|
}
|
|
48
48
|
const bookings = await JobsBackend.unscheduledRebookings(signal);
|
|
49
|
-
return
|
|
49
|
+
return mapUnscheduledRebookings(bookings);
|
|
50
50
|
}), (prev) => prev ?? OrderedMap.empty());
|
|
51
|
+
export function mapUnscheduledRebookings(bookings) {
|
|
52
|
+
return OrderedMap.build(bookings ?? [], (booking) => booking.bookingId);
|
|
53
|
+
}
|
|
51
54
|
export const last30Rebookings = atom((get) => {
|
|
52
55
|
const evts = get(rebookingEvts);
|
|
53
56
|
const unsch = get(unschRebookings);
|
package/dist/components/App.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { ReactNode, ComponentType } from "react";
|
|
|
2
2
|
import { ChooseModeItem } from "./ChooseMode.js";
|
|
3
3
|
import * as serverSettings from "../network/server-settings.js";
|
|
4
4
|
import type { SubmitBasketLoadStationCommand } from "./station-monitor/BasketLoadStationWork.js";
|
|
5
|
+
import type { SubmitBasketLocationCorrection, SubmitBasketMovementCompletion } from "./station-monitor/BasketMovementArrival.js";
|
|
5
6
|
export declare function NavTabs({ children }: {
|
|
6
7
|
children?: ReactNode;
|
|
7
8
|
}): import("react").JSX.Element;
|
|
@@ -12,6 +13,8 @@ export interface AppProps {
|
|
|
12
13
|
};
|
|
13
14
|
readonly chooseModes?: (i: serverSettings.FMSInfoAndUser) => ReadonlyArray<ChooseModeItem> | null;
|
|
14
15
|
readonly submitBasketLoadStationCommand?: SubmitBasketLoadStationCommand;
|
|
16
|
+
readonly submitBasketMovementCompletion?: SubmitBasketMovementCompletion;
|
|
17
|
+
readonly submitBasketLocationCorrection?: SubmitBasketLocationCorrection;
|
|
15
18
|
}
|
|
16
19
|
declare const App: import("react").MemoExoticComponent<(props: AppProps) => import("react").JSX.Element>;
|
|
17
20
|
export default App;
|
package/dist/components/App.js
CHANGED
|
@@ -310,7 +310,7 @@ const App = memo(function App(props) {
|
|
|
310
310
|
else {
|
|
311
311
|
switch (route.route) {
|
|
312
312
|
case routes.RouteLocation.Station_LoadMonitor:
|
|
313
|
-
page = (_jsx(LoadStation, { loadNum: route.loadNum, queues: route.queues, completed: route.completed, submitBasketLoadStationCommand: props.submitBasketLoadStationCommand }));
|
|
313
|
+
page = (_jsx(LoadStation, { loadNum: route.loadNum, queues: route.queues, completed: route.completed, submitBasketLoadStationCommand: props.submitBasketLoadStationCommand, submitBasketMovementCompletion: props.submitBasketMovementCompletion, submitBasketLocationCorrection: props.submitBasketLocationCorrection }, route.loadNum));
|
|
314
314
|
nav1 = StationToolbar;
|
|
315
315
|
nav2 = StationToolbarOverviewButton;
|
|
316
316
|
showOperator = true;
|
|
@@ -93,10 +93,22 @@ function logType(entry, fmsInfo) {
|
|
|
93
93
|
else {
|
|
94
94
|
return "Depart";
|
|
95
95
|
}
|
|
96
|
-
case api.LogType.
|
|
97
|
-
return `${basketName} Identity
|
|
96
|
+
case api.LogType.BasketIdentityAssociation:
|
|
97
|
+
return `${basketName} Identity Association`;
|
|
98
|
+
case api.LogType.BasketIdentityAssociationCorrection:
|
|
99
|
+
return `${basketName} Identity Correction`;
|
|
98
100
|
case api.LogType.BasketContentSnapshot:
|
|
99
101
|
return `${basketName} Content Snapshot`;
|
|
102
|
+
case api.LogType.BasketLocationObservation:
|
|
103
|
+
return `${basketName} Location Observation`;
|
|
104
|
+
case api.LogType.BasketLocationObservationCorrection:
|
|
105
|
+
return `${basketName} Location Correction`;
|
|
106
|
+
case api.LogType.BasketRegionSurvey:
|
|
107
|
+
return `${basketName} Region Survey`;
|
|
108
|
+
case api.LogType.BasketMisload:
|
|
109
|
+
return `${basketName} Inspection Hold`;
|
|
110
|
+
case api.LogType.BasketMisloadResolution:
|
|
111
|
+
return `${basketName} Inspection Resolution`;
|
|
100
112
|
case api.LogType.MachineCycle:
|
|
101
113
|
if (entry.startofcycle) {
|
|
102
114
|
return "Start Cycle";
|
|
@@ -141,6 +153,12 @@ function logType(entry, fmsInfo) {
|
|
|
141
153
|
return "Message";
|
|
142
154
|
}
|
|
143
155
|
}
|
|
156
|
+
function evidencePosition(entry) {
|
|
157
|
+
const title = entry.details?.locationTitle ?? entry.details?.location ?? entry.loc;
|
|
158
|
+
const locationNumber = entry.locnum > 0 ? ` ${entry.locnum}` : "";
|
|
159
|
+
const zone = entry.details?.zone === undefined ? "" : ` zone ${entry.details.zone}`;
|
|
160
|
+
return `${title}${locationNumber}${zone}`;
|
|
161
|
+
}
|
|
144
162
|
export function isLogEntryInvalidated(e) {
|
|
145
163
|
return e.details?.["PalletCycleInvalidated"] === "1";
|
|
146
164
|
}
|
|
@@ -202,14 +220,57 @@ function display(props, fmsInfo) {
|
|
|
202
220
|
return (_jsxs("span", { children: [basketContainerName(entry, basketName), " departed from ", entry.loc, entry.locnum > 0 ? ` position ${entry.locnum}` : ""] }));
|
|
203
221
|
}
|
|
204
222
|
}
|
|
205
|
-
case api.LogType.
|
|
223
|
+
case api.LogType.BasketIdentityAssociation: {
|
|
224
|
+
const basketName = basketDisplayName(fmsInfo.basketName);
|
|
225
|
+
const episodeCount = entry.details?.episodeCount;
|
|
226
|
+
const source = entry.details?.sourceName;
|
|
227
|
+
const note = entry.details?.note;
|
|
228
|
+
return (_jsxs("span", { children: [source === undefined ? "" : `${source} recorded `, episodeCount === undefined
|
|
229
|
+
? `content episodes associated with ${basketName} ${entry.pal}`
|
|
230
|
+
: `${episodeCount} content episode${episodeCount === "1" ? "" : "s"} associated with ${basketName} ${entry.pal}`, entry.details?.location === undefined && entry.details?.locationTitle === undefined
|
|
231
|
+
? ""
|
|
232
|
+
: ` at ${evidencePosition(entry)}`, note === undefined ? "" : `: ${note}`] }));
|
|
233
|
+
}
|
|
234
|
+
case api.LogType.BasketIdentityAssociationCorrection: {
|
|
206
235
|
const basketName = basketDisplayName(fmsInfo.basketName);
|
|
207
|
-
return (_jsxs("span", { children: [
|
|
236
|
+
return (_jsxs("span", { children: ["Identity association for ", basketName, " ", entry.pal, " corrected"] }));
|
|
208
237
|
}
|
|
209
238
|
case api.LogType.BasketContentSnapshot: {
|
|
210
239
|
const basketName = basketDisplayName(fmsInfo.basketName);
|
|
211
240
|
return (_jsxs("span", { children: [basketContainerName(entry, basketName), " contained ", displayMat(entry.material)] }));
|
|
212
241
|
}
|
|
242
|
+
case api.LogType.BasketLocationObservation: {
|
|
243
|
+
const basketName = basketDisplayName(fmsInfo.basketName);
|
|
244
|
+
const operator = entry.details?.sourceName ?? entry.details?.operator ?? "Operator";
|
|
245
|
+
return (_jsxs("span", { children: [operator, " observed ", basketName, " ", entry.pal, " at ", evidencePosition(entry)] }));
|
|
246
|
+
}
|
|
247
|
+
case api.LogType.BasketLocationObservationCorrection: {
|
|
248
|
+
const basketName = basketDisplayName(fmsInfo.basketName);
|
|
249
|
+
const operator = entry.details?.sourceName ?? entry.details?.operator ?? "Operator";
|
|
250
|
+
const location = evidencePosition(entry);
|
|
251
|
+
const replacementBasketId = entry.details?.replacementBasketId;
|
|
252
|
+
return replacementBasketId === undefined ? (_jsxs("span", { children: [operator, " retracted the observation of ", basketName, " ", entry.pal, " at ", location] })) : (_jsxs("span", { children: [operator, " changed the observation of ", basketName, " ", entry.pal, " at ", location, " to", " ", basketName, " ", replacementBasketId, " at ", location] }));
|
|
253
|
+
}
|
|
254
|
+
case api.LogType.BasketRegionSurvey: {
|
|
255
|
+
const basketName = basketDisplayName(fmsInfo.basketName);
|
|
256
|
+
const source = entry.details?.sourceName;
|
|
257
|
+
const observed = entry.details?.observedBasketCount;
|
|
258
|
+
const unidentified = entry.details?.unidentifiedBasketCount;
|
|
259
|
+
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 ? "" : ")"] }));
|
|
260
|
+
}
|
|
261
|
+
case api.LogType.BasketMisload: {
|
|
262
|
+
const basketName = basketDisplayName(fmsInfo.basketName);
|
|
263
|
+
const source = entry.details?.sourceName;
|
|
264
|
+
const reason = entry.details?.reason;
|
|
265
|
+
const subject = entry.pal > 0 ? `${basketName} ${entry.pal}` : `Unnumbered ${basketName.toLowerCase()}`;
|
|
266
|
+
return (_jsxs("span", { children: [source === undefined ? subject : `${source} reported ${subject}`, " requires inspection at", " ", evidencePosition(entry), reason === undefined ? "" : `: ${reason}`] }));
|
|
267
|
+
}
|
|
268
|
+
case api.LogType.BasketMisloadResolution: {
|
|
269
|
+
const basketName = basketDisplayName(fmsInfo.basketName);
|
|
270
|
+
const source = entry.details?.sourceName;
|
|
271
|
+
const subject = entry.pal > 0 ? `${basketName} ${entry.pal}` : `Unnumbered ${basketName.toLowerCase()}`;
|
|
272
|
+
return (_jsxs("span", { children: [source === undefined ? "Inspection hold" : `${source} resolved inspection hold`, " for", " ", subject, " at ", evidencePosition(entry), ": ", entry.result] }));
|
|
273
|
+
}
|
|
213
274
|
case api.LogType.MachineCycle:
|
|
214
275
|
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] }));
|
|
215
276
|
case api.LogType.PartMark:
|
|
@@ -29,7 +29,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
29
29
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
30
30
|
*/
|
|
31
31
|
import { useMemo, useState } from "react";
|
|
32
|
-
import { Alert, Box, Button,
|
|
32
|
+
import { Alert, Box, Button, Stack, Typography } from "@mui/material";
|
|
33
33
|
import { LazySeq } from "@seedtactics/immutable-collections";
|
|
34
34
|
import * as api from "../../network/api.js";
|
|
35
35
|
import { InProcMaterial } from "./Material.js";
|
|
@@ -150,6 +150,10 @@ export function BasketLoadStationWorkflow({ stationNumber, basket, material, fsi
|
|
|
150
150
|
const slotMaterial = materialBySlot.get(slot) ?? [];
|
|
151
151
|
const loads = loadsBySlot.get(slot) ?? [];
|
|
152
152
|
const isUnknown = basket.unknownSlots?.includes(slot) === true;
|
|
153
|
-
return (_jsx(
|
|
153
|
+
return (_jsx(MoveMaterialArrowNode, { kind: {
|
|
154
|
+
type: MoveMaterialNodeKindType.BasketSlotZone,
|
|
155
|
+
basketId: basket.basketId,
|
|
156
|
+
slot,
|
|
157
|
+
}, 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));
|
|
154
158
|
}) }), 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] }));
|
|
155
159
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as api from "../../network/api.js";
|
|
2
|
+
export interface BasketMovementCompletionCommand {
|
|
3
|
+
readonly commandId: string;
|
|
4
|
+
readonly instructionId: string;
|
|
5
|
+
readonly observedBasketId: number;
|
|
6
|
+
}
|
|
7
|
+
export interface BasketMovementCompletionReceipt {
|
|
8
|
+
readonly stationNumber: number;
|
|
9
|
+
readonly instructionId: string;
|
|
10
|
+
readonly observationId: string;
|
|
11
|
+
readonly observedBasketId: number;
|
|
12
|
+
}
|
|
13
|
+
export type SubmitBasketMovementCompletion = (stationNumber: number, command: BasketMovementCompletionCommand) => Promise<BasketMovementCompletionReceipt | "conflict">;
|
|
14
|
+
export interface BasketLocationCorrectionCommand {
|
|
15
|
+
readonly correctionId: string;
|
|
16
|
+
readonly targetObservationId: string;
|
|
17
|
+
readonly replacementBasketId: number | null;
|
|
18
|
+
readonly replacementObservationId: string | null;
|
|
19
|
+
}
|
|
20
|
+
export type SubmitBasketLocationCorrection = (stationNumber: number, command: BasketLocationCorrectionCommand) => Promise<"accepted" | "conflict">;
|
|
21
|
+
export interface BasketArrivalReceipt {
|
|
22
|
+
readonly stationNumber: number;
|
|
23
|
+
readonly instruction: Readonly<api.IBasketMoveInstruction>;
|
|
24
|
+
readonly command: BasketMovementCompletionCommand;
|
|
25
|
+
readonly receipt: BasketMovementCompletionReceipt;
|
|
26
|
+
readonly status: "recorded" | "corrected" | "retracted";
|
|
27
|
+
}
|
|
28
|
+
export declare function loadStationArrivalInstruction(instructions: ReadonlyArray<Readonly<api.IBasketMoveInstruction>>, stationNumber: number): Readonly<api.IBasketMoveInstruction> | undefined;
|
|
29
|
+
export declare function BasketMovementArrival({ stationNumber, basketName, instruction, submitCommand, submitCorrection, receipt, onAccepted, onCorrected, }: {
|
|
30
|
+
readonly stationNumber: number;
|
|
31
|
+
readonly basketName: string;
|
|
32
|
+
readonly instruction: Readonly<api.IBasketMoveInstruction>;
|
|
33
|
+
readonly submitCommand: SubmitBasketMovementCompletion | undefined;
|
|
34
|
+
readonly submitCorrection: SubmitBasketLocationCorrection | undefined;
|
|
35
|
+
readonly receipt?: BasketArrivalReceipt;
|
|
36
|
+
readonly onAccepted?: (receipt: BasketArrivalReceipt) => void;
|
|
37
|
+
readonly onCorrected?: (command: BasketLocationCorrectionCommand) => void;
|
|
38
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/* Copyright (c) 2026, John Lenz
|
|
3
|
+
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
* Redistributions of source code must retain the above copyright
|
|
10
|
+
notice, this list of conditions and the following disclaimer.
|
|
11
|
+
* Redistributions in binary form must reproduce the above copyright
|
|
12
|
+
notice, this list of conditions and the following disclaimer in the
|
|
13
|
+
documentation and/or other materials provided with the distribution.
|
|
14
|
+
* Neither the name of John Lenz, Black Maple Software, SeedTactics,
|
|
15
|
+
nor the names of other contributors may be used to endorse or
|
|
16
|
+
promote products derived from this software without specific
|
|
17
|
+
prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
20
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
21
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
22
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
23
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
24
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
25
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
26
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
27
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
28
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
30
|
+
*/
|
|
31
|
+
import { useEffect, useRef, useState } from "react";
|
|
32
|
+
import { Alert, Box, Button, Paper, Stack, TextField, Typography } from "@mui/material";
|
|
33
|
+
import * as api from "../../network/api.js";
|
|
34
|
+
export function loadStationArrivalInstruction(instructions, stationNumber) {
|
|
35
|
+
const activeIds = new Set(instructions.map((instruction) => instruction.instructionId));
|
|
36
|
+
return instructions.find((instruction) => instruction.basketId !== undefined &&
|
|
37
|
+
instruction.destination.location === api.BasketLocationEnum.LoadUnload &&
|
|
38
|
+
instruction.destination.locationNum === stationNumber &&
|
|
39
|
+
(instruction.prerequisiteInstructionId === undefined ||
|
|
40
|
+
!activeIds.has(instruction.prerequisiteInstructionId)));
|
|
41
|
+
}
|
|
42
|
+
export function BasketMovementArrival({ stationNumber, basketName, instruction, submitCommand, submitCorrection, receipt, onAccepted, onCorrected, }) {
|
|
43
|
+
const [chooseDifferent, setChooseDifferent] = useState(false);
|
|
44
|
+
const [differentBasket, setDifferentBasket] = useState("");
|
|
45
|
+
const [submission, setSubmission] = useState();
|
|
46
|
+
const [changingRecordedBasket, setChangingRecordedBasket] = useState(false);
|
|
47
|
+
const [correctionSubmission, setCorrectionSubmission] = useState();
|
|
48
|
+
const currentInstructionId = useRef(instruction.instructionId);
|
|
49
|
+
const currentStationNumber = useRef(stationNumber);
|
|
50
|
+
const currentCorrectionTargetId = useRef(undefined);
|
|
51
|
+
currentInstructionId.current = instruction.instructionId;
|
|
52
|
+
currentStationNumber.current = stationNumber;
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
setChooseDifferent(false);
|
|
55
|
+
setDifferentBasket("");
|
|
56
|
+
setSubmission((current) => current?.state === "error" && current.command.instructionId === instruction.instructionId
|
|
57
|
+
? current
|
|
58
|
+
: undefined);
|
|
59
|
+
setChangingRecordedBasket(false);
|
|
60
|
+
setCorrectionSubmission(undefined);
|
|
61
|
+
}, [instruction.instructionId, stationNumber]);
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
setChangingRecordedBasket(false);
|
|
64
|
+
setDifferentBasket("");
|
|
65
|
+
setCorrectionSubmission((current) => current?.state === "error" &&
|
|
66
|
+
receipt?.status !== "retracted" &&
|
|
67
|
+
current.command.targetObservationId === receipt?.receipt.observationId
|
|
68
|
+
? current
|
|
69
|
+
: undefined);
|
|
70
|
+
}, [receipt?.receipt.observationId, receipt?.status]);
|
|
71
|
+
const expectedBasketId = instruction.basketId;
|
|
72
|
+
if (expectedBasketId === undefined) {
|
|
73
|
+
return (_jsx(Alert, { severity: "warning", children: "This tracked basket must be handled through the recovery workflow." }));
|
|
74
|
+
}
|
|
75
|
+
async function record(command) {
|
|
76
|
+
if (submitCommand === undefined)
|
|
77
|
+
return;
|
|
78
|
+
setSubmission({ state: "submitting", command });
|
|
79
|
+
try {
|
|
80
|
+
const result = await submitCommand(stationNumber, command);
|
|
81
|
+
if (currentStationNumber.current !== stationNumber ||
|
|
82
|
+
currentInstructionId.current !== command.instructionId)
|
|
83
|
+
return;
|
|
84
|
+
if (result === "conflict") {
|
|
85
|
+
setSubmission({ state: result, command });
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
setSubmission({ state: "accepted", command, receipt: result });
|
|
89
|
+
onAccepted?.({
|
|
90
|
+
stationNumber,
|
|
91
|
+
instruction,
|
|
92
|
+
command,
|
|
93
|
+
receipt: result,
|
|
94
|
+
status: "recorded",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (currentStationNumber.current !== stationNumber ||
|
|
100
|
+
currentInstructionId.current !== command.instructionId)
|
|
101
|
+
return;
|
|
102
|
+
setSubmission({
|
|
103
|
+
state: "error",
|
|
104
|
+
command,
|
|
105
|
+
message: error instanceof Error ? error.message : "Unable to record basket arrival",
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async function correct(command) {
|
|
110
|
+
if (submitCorrection === undefined || activeCommand === undefined)
|
|
111
|
+
return;
|
|
112
|
+
setCorrectionSubmission({ state: "submitting", command });
|
|
113
|
+
try {
|
|
114
|
+
const result = await submitCorrection(stationNumber, command);
|
|
115
|
+
if (currentStationNumber.current !== stationNumber ||
|
|
116
|
+
currentCorrectionTargetId.current !== command.targetObservationId)
|
|
117
|
+
return;
|
|
118
|
+
setCorrectionSubmission({ state: result, command });
|
|
119
|
+
if (result === "accepted")
|
|
120
|
+
onCorrected?.(command);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
if (currentStationNumber.current !== stationNumber ||
|
|
124
|
+
currentCorrectionTargetId.current !== command.targetObservationId)
|
|
125
|
+
return;
|
|
126
|
+
setCorrectionSubmission({ state: "error", command });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function createCommand(basketId) {
|
|
130
|
+
return {
|
|
131
|
+
commandId: crypto.randomUUID(),
|
|
132
|
+
instructionId: instruction.instructionId,
|
|
133
|
+
observedBasketId: basketId,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
const parsedDifferentBasket = Number(differentBasket);
|
|
137
|
+
const activeCommand = receipt?.status === "retracted"
|
|
138
|
+
? undefined
|
|
139
|
+
: (receipt?.command ??
|
|
140
|
+
(submission?.state === "accepted" &&
|
|
141
|
+
submission.command.instructionId === instruction.instructionId
|
|
142
|
+
? submission.command
|
|
143
|
+
: undefined));
|
|
144
|
+
const activeObservationId = receipt?.status === "retracted"
|
|
145
|
+
? undefined
|
|
146
|
+
: (receipt?.receipt.observationId ??
|
|
147
|
+
(submission?.state === "accepted" ? submission.receipt.observationId : undefined));
|
|
148
|
+
currentCorrectionTargetId.current = activeObservationId;
|
|
149
|
+
function createCorrection(replacementBasketId) {
|
|
150
|
+
return {
|
|
151
|
+
correctionId: crypto.randomUUID(),
|
|
152
|
+
targetObservationId: activeObservationId ?? "",
|
|
153
|
+
replacementBasketId,
|
|
154
|
+
replacementObservationId: replacementBasketId === null ? null : crypto.randomUUID(),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const validDifferentBasket = Number.isInteger(parsedDifferentBasket) &&
|
|
158
|
+
parsedDifferentBasket > 0 &&
|
|
159
|
+
parsedDifferentBasket !== (activeCommand?.observedBasketId ?? expectedBasketId);
|
|
160
|
+
const disabled = submitCommand === undefined ||
|
|
161
|
+
activeCommand !== undefined ||
|
|
162
|
+
(submission !== undefined && submission.state !== "error");
|
|
163
|
+
const receiptMessage = receipt?.status === "retracted"
|
|
164
|
+
? "Arrival observation retracted."
|
|
165
|
+
: receipt?.status === "corrected"
|
|
166
|
+
? `Arrival corrected to ${basketName.toLocaleLowerCase()} ${receipt.command.observedBasketId}.`
|
|
167
|
+
: "Arrival recorded. Waiting for updated status.";
|
|
168
|
+
return (_jsx(Paper, { component: "section", elevation: 2, sx: { margin: 1, padding: 2 }, children: _jsxs(Stack, { spacing: 2, children: [_jsxs(Box, { children: [_jsx(Typography, { variant: "overline", children: receipt === undefined ? "Basket arrival" : "Basket arrival receipt" }), _jsx(Typography, { variant: "h4", children: receipt?.status === "retracted"
|
|
169
|
+
? "Retracted basket arrival"
|
|
170
|
+
: receipt === undefined
|
|
171
|
+
? `Bring ${basketName.toLocaleLowerCase()} ${expectedBasketId} to this station`
|
|
172
|
+
: `${basketName} ${receipt.command.observedBasketId} at this station` }), receipt === undefined ? (_jsx(Typography, { children: "Record arrival after the basket is physically in place." })) : null] }), receipt === undefined ? (_jsxs(Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, children: [_jsx(Button, { disabled: disabled, onClick: () => void record(createCommand(expectedBasketId)), size: "large", variant: "contained", children: submission?.state === "submitting"
|
|
173
|
+
? "Recording arrival…"
|
|
174
|
+
: `${basketName} ${expectedBasketId} arrived` }), _jsxs(Button, { disabled: disabled, onClick: () => setChooseDifferent((visible) => !visible), size: "large", variant: "outlined", children: ["Different ", basketName.toLocaleLowerCase()] })] })) : null, receipt === undefined && chooseDifferent && !disabled ? (_jsxs(Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, children: [_jsx(TextField, { label: `${basketName} number`, onChange: (event) => setDifferentBasket(event.target.value), type: "number", value: differentBasket, slotProps: { htmlInput: { inputMode: "numeric", min: 1 } } }), _jsxs(Button, { disabled: !validDifferentBasket, onClick: () => void record(createCommand(parsedDifferentBasket)), variant: "contained", children: ["Record ", basketName.toLocaleLowerCase(), " arrival"] })] })) : null, submitCommand === undefined ? (_jsx(Alert, { severity: "warning", children: "Basket arrival completion is not configured." })) : activeCommand !== undefined || receipt?.status === "retracted" ? (_jsxs(Stack, { spacing: 1, children: [_jsx(Alert, { severity: "success", children: receiptMessage }), submitCorrection === undefined || activeCommand === undefined ? null : (_jsxs(Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, children: [_jsx(Button, { disabled: correctionSubmission !== undefined, onClick: () => setChangingRecordedBasket((visible) => !visible), variant: "outlined", children: "Change" }), _jsx(Button, { color: "error", disabled: correctionSubmission !== undefined, onClick: () => void correct(createCorrection(null)), variant: "text", children: "Undo" })] })), changingRecordedBasket && correctionSubmission === undefined ? (_jsxs(Stack, { direction: { xs: "column", sm: "row" }, spacing: 1, children: [_jsx(TextField, { label: `Correct ${basketName.toLocaleLowerCase()} number`, onChange: (event) => setDifferentBasket(event.target.value), type: "number", value: differentBasket, slotProps: { htmlInput: { inputMode: "numeric", min: 1 } } }), _jsx(Button, { disabled: !validDifferentBasket, onClick: () => void correct(createCorrection(parsedDifferentBasket)), variant: "contained", children: "Save correction" })] })) : null, correctionSubmission?.state === "accepted" ? (_jsx(Alert, { severity: "success", children: "Correction recorded." })) : correctionSubmission?.state === "conflict" ? (_jsx(Alert, { severity: "warning", children: "Basket evidence changed. Review the refreshed status." })) : correctionSubmission?.state === "error" ? (_jsx(Alert, { action: _jsx(Button, { color: "inherit", onClick: () => void correct(correctionSubmission.command), children: "Retry correction" }), severity: "error", children: "Unable to correct the recorded arrival." })) : null] })) : submission?.state === "conflict" ? (_jsx(Alert, { severity: "warning", children: "Basket movement changed. Review the refreshed instruction." })) : submission?.state === "error" ? (_jsx(Alert, { action: _jsx(Button, { onClick: () => void record(submission.command), color: "inherit", children: "Retry arrival" }), severity: "error", children: submission.message })) : null] }) }));
|
|
175
|
+
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
2
|
import { SubmitBasketLoadStationCommand } from "./BasketLoadStationWork.js";
|
|
3
|
+
import { SubmitBasketLocationCorrection, SubmitBasketMovementCompletion } from "./BasketMovementArrival.js";
|
|
3
4
|
interface LoadStationProps {
|
|
4
5
|
readonly loadNum: number;
|
|
5
6
|
readonly queues: ReadonlyArray<string>;
|
|
6
7
|
readonly completed: boolean;
|
|
7
8
|
readonly whiteBackground?: boolean;
|
|
8
9
|
readonly submitBasketLoadStationCommand?: SubmitBasketLoadStationCommand;
|
|
10
|
+
readonly submitBasketMovementCompletion?: SubmitBasketMovementCompletion;
|
|
11
|
+
readonly submitBasketLocationCorrection?: SubmitBasketLocationCorrection;
|
|
9
12
|
}
|
|
10
13
|
export declare function LoadStation(props: LoadStationProps): import("react").JSX.Element;
|
|
11
14
|
declare function LoadStationCheckWidth(props: LoadStationProps): ReactNode;
|
|
@@ -31,7 +31,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
31
31
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
32
32
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
33
33
|
*/
|
|
34
|
-
import { useMemo, memo, useState, useCallback } from "react";
|
|
34
|
+
import { useMemo, memo, useState, useCallback, useEffect } from "react";
|
|
35
35
|
import { Box, useMediaQuery, Button, Typography } from "@mui/material";
|
|
36
36
|
import { LazySeq, mkCompareByProperties, OrderedMap } from "@seedtactics/immutable-collections";
|
|
37
37
|
import { FolderOpen as FolderOpenIcon } from "@mui/icons-material";
|
|
@@ -64,6 +64,7 @@ import { hideNonLoadingMaterialOnLoadStation } from "../../data/queue-material.j
|
|
|
64
64
|
import { basketDisplayName, loadStationDisplayName } from "../../cell-status/station-cycles.js";
|
|
65
65
|
import { canAddOrMoveMaterialToQueue } from "../../data/material-operation-policy.js";
|
|
66
66
|
import { BasketLoadStationWorkflow, } from "./BasketLoadStationWork.js";
|
|
67
|
+
import { BasketMovementArrival, loadStationArrivalInstruction, } from "./BasketMovementArrival.js";
|
|
67
68
|
function encodeLoadStationRegionIdPart(value) {
|
|
68
69
|
return encodeURIComponent(value.toString());
|
|
69
70
|
}
|
|
@@ -284,6 +285,21 @@ function selectLoadStationAndQueueProps(loadNum, queues, curSt, hideNonLoading)
|
|
|
284
285
|
queueMat.forEach((queue) => queue.mats.sort(mkCompareByProperties((mat) => mat.location.queuePosition ?? 0)));
|
|
285
286
|
basketMat.forEach((basket) => basket.mats.sort(mkCompareByProperties((mat) => mat.location.basketSlot ?? 0)));
|
|
286
287
|
const matCount = freeLoading.length + palFaces.valuesToAscLazySeq().sumBy((x) => x.length);
|
|
288
|
+
const activeBasketSlotCount = activeBasket
|
|
289
|
+
? LazySeq.of(activeBasket.emptySlots ?? [])
|
|
290
|
+
.concat(activeBasket.unknownSlots ?? [])
|
|
291
|
+
.concat(LazySeq.of(curSt.material).collect((mat) => mat.location.type === api.LocType.InBasket &&
|
|
292
|
+
mat.location.basketId === activeBasket.basketId
|
|
293
|
+
? mat.location.basketSlot
|
|
294
|
+
: undefined))
|
|
295
|
+
.concat(LazySeq.of(curSt.material).collect((mat) => mat.action.type === api.ActionType.LoadingToBasket &&
|
|
296
|
+
mat.action.loadToBasketId === activeBasket.basketId
|
|
297
|
+
? mat.action.loadToBasketSlot
|
|
298
|
+
: undefined))
|
|
299
|
+
.distinctBy((slot) => slot)
|
|
300
|
+
.toRArray().length
|
|
301
|
+
: 0;
|
|
302
|
+
const layoutCount = Math.max(matCount, activeBasketSlotCount);
|
|
287
303
|
return {
|
|
288
304
|
pallet: pal,
|
|
289
305
|
activeBasket,
|
|
@@ -293,7 +309,7 @@ function selectLoadStationAndQueueProps(loadNum, queues, curSt, hideNonLoading)
|
|
|
293
309
|
queues: queueMat,
|
|
294
310
|
baskets: basketMat,
|
|
295
311
|
elapsedLoadingTime,
|
|
296
|
-
fsize:
|
|
312
|
+
fsize: layoutCount <= 2 ? "x-large" : layoutCount <= 6 ? "large" : "normal",
|
|
297
313
|
};
|
|
298
314
|
}
|
|
299
315
|
function MultiInstructionButton({ loadData }) {
|
|
@@ -648,6 +664,20 @@ export function LoadStation(props) {
|
|
|
648
664
|
const currentSt = useAtomValue(currentStatus);
|
|
649
665
|
const hideNonLoading = useAtomValue(hideNonLoadingMaterialOnLoadStation);
|
|
650
666
|
const data = useMemo(() => selectLoadStationAndQueueProps(props.loadNum, props.queues, currentSt, hideNonLoading), [currentSt, props.loadNum, props.queues, hideNonLoading]);
|
|
667
|
+
const arrivalInstruction = loadStationArrivalInstruction(currentSt.basketMoveInstructions ?? [], props.loadNum);
|
|
668
|
+
const [recentArrivalReceipt, setRecentArrivalReceipt] = useState();
|
|
669
|
+
useEffect(() => {
|
|
670
|
+
if (recentArrivalReceipt !== undefined &&
|
|
671
|
+
(recentArrivalReceipt.stationNumber !== props.loadNum ||
|
|
672
|
+
(arrivalInstruction !== undefined &&
|
|
673
|
+
arrivalInstruction.instructionId !== recentArrivalReceipt.instruction.instructionId)))
|
|
674
|
+
setRecentArrivalReceipt(undefined);
|
|
675
|
+
}, [arrivalInstruction, props.loadNum, recentArrivalReceipt]);
|
|
676
|
+
const displayedArrivalInstruction = arrivalInstruction ?? recentArrivalReceipt?.instruction;
|
|
677
|
+
const displayedArrivalReceipt = recentArrivalReceipt?.stationNumber === props.loadNum &&
|
|
678
|
+
displayedArrivalInstruction?.instructionId === recentArrivalReceipt?.instruction.instructionId
|
|
679
|
+
? recentArrivalReceipt
|
|
680
|
+
: undefined;
|
|
651
681
|
const queueCols = LazySeq.of(data.queues)
|
|
652
682
|
.sortBy(([q, _]) => q)
|
|
653
683
|
.map(([q, mats]) => ({
|
|
@@ -694,31 +724,53 @@ export function LoadStation(props) {
|
|
|
694
724
|
horizontal: fillViewPort,
|
|
695
725
|
showMatInCompleted: props.completed,
|
|
696
726
|
});
|
|
697
|
-
return (_jsx(
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
727
|
+
return (_jsxs(_Fragment, { children: [displayedArrivalInstruction === undefined ? null : (_jsx(BasketMovementArrival, { basketName: basketName, instruction: displayedArrivalInstruction, stationNumber: props.loadNum, submitCommand: props.submitBasketMovementCompletion, submitCorrection: props.submitBasketLocationCorrection, receipt: displayedArrivalReceipt, onAccepted: setRecentArrivalReceipt, onCorrected: (command) => setRecentArrivalReceipt((current) => {
|
|
728
|
+
if (current === undefined ||
|
|
729
|
+
current.stationNumber !== props.loadNum ||
|
|
730
|
+
current.receipt.observationId !== command.targetObservationId)
|
|
731
|
+
return current;
|
|
732
|
+
return command.replacementBasketId === null ||
|
|
733
|
+
command.replacementObservationId === null
|
|
734
|
+
? { ...current, status: "retracted" }
|
|
735
|
+
: {
|
|
736
|
+
...current,
|
|
737
|
+
receipt: {
|
|
738
|
+
...current.receipt,
|
|
739
|
+
observationId: command.replacementObservationId,
|
|
740
|
+
observedBasketId: command.replacementBasketId,
|
|
741
|
+
},
|
|
742
|
+
command: {
|
|
743
|
+
...current.command,
|
|
744
|
+
commandId: command.replacementObservationId,
|
|
745
|
+
observedBasketId: command.replacementBasketId,
|
|
746
|
+
},
|
|
747
|
+
status: "corrected",
|
|
748
|
+
};
|
|
749
|
+
}) })), _jsx(MoveMaterialArrowContainer, { hideArrows: !fillViewPort, whiteBackground: props.whiteBackground, children: _jsxs(Box, { component: "main", sx: {
|
|
750
|
+
width: "100%",
|
|
751
|
+
display: "grid",
|
|
752
|
+
gridTemplate: grid,
|
|
753
|
+
minHeight: {
|
|
754
|
+
xs: "calc(100vh - 64px - 32px)",
|
|
755
|
+
sm: "calc(100vh - 64px - 40px)",
|
|
756
|
+
md: "calc(100vh - 64px)",
|
|
757
|
+
},
|
|
758
|
+
padding: fillViewPort ? undefined : "8px",
|
|
759
|
+
}, children: [matCols.map((col, idx) => (_jsx(Box, { "data-testid": materialColumnTestId(col), sx: {
|
|
760
|
+
gridArea: `mat${idx}`,
|
|
761
|
+
padding: "8px",
|
|
762
|
+
borderRight: fillViewPort ? "1px solid black" : undefined,
|
|
763
|
+
borderBottom: !fillViewPort ? "1px solid black" : undefined,
|
|
764
|
+
}, children: _jsx(MaterialColumn, { data: data, region: col }) }, idx))), data.face.keysToAscLazySeq().map((faceNum, idx) => (_jsx(Box, { sx: {
|
|
765
|
+
marginLeft: "15px",
|
|
766
|
+
gridArea: `palface${idx}`,
|
|
767
|
+
padding: "8px",
|
|
768
|
+
borderTop: data.pallet && idx !== 0 ? "1px solid black" : undefined,
|
|
769
|
+
}, children: _jsx(PalletFace, { data: data, faceNum: faceNum, loadNum: props.loadNum, submitBasketLoadStationCommand: props.submitBasketLoadStationCommand }) }, faceNum))), _jsx(Box, { "data-testid": "load-station-completed", sx: {
|
|
770
|
+
borderLeft: fillViewPort ? "1px solid black" : undefined,
|
|
771
|
+
borderTop: !fillViewPort ? "1px solid black" : undefined,
|
|
772
|
+
gridArea: "completed",
|
|
773
|
+
}, children: _jsx(CompletedCol, { fillViewPort: fillViewPort, showMaterial: props.completed }) }), _jsx(MultiInstructionButton, { loadData: data }), _jsx(SelectWorkorderDialog, {}), _jsx(SelectInspTypeDialog, {}), _jsx(LoadMatDialog, { pallet: data.pallet?.palletNum ?? null, queues: props.queues })] }) })] }));
|
|
722
774
|
}
|
|
723
775
|
function LoadStationCheckWidth(props) {
|
|
724
776
|
const fmsInfo = useAtomValue(fmsInformation);
|
|
@@ -377,6 +377,7 @@ const MatCard = forwardRef(function MatCard(props, ref) {
|
|
|
377
377
|
}, children: [_jsx(PartIdenticon, { part: props.mat.partName }), _jsxs(Box, { sx: {
|
|
378
378
|
marginLeft: "8px",
|
|
379
379
|
flexGrow: 1,
|
|
380
|
+
minWidth: 0,
|
|
380
381
|
}, children: [_jsx(MatCardHeader, { fsize: props.fsize, children: props.mat.partName }), props.displayJob ? (_jsx(MatCardDetail, { fsize: props.fsize, children: props.mat.jobUnique && props.mat.jobUnique !== ""
|
|
381
382
|
? "Assigned to " + props.mat.jobUnique
|
|
382
383
|
: "Unassigned material" })) : undefined, !props.hideEmptySerial || props.mat.serial ? (_jsxs(MatCardDetail, { fsize: props.fsize, children: ["Serial: ", props.mat.serial ? props.mat.serial : "none"] })) : undefined, props.mat.workorderId === undefined ||
|
|
@@ -391,6 +392,7 @@ const MatCard = forwardRef(function MatCard(props, ref) {
|
|
|
391
392
|
justifyContent: "space-between",
|
|
392
393
|
alignItems: "flex-end",
|
|
393
394
|
alignSelf: "start",
|
|
395
|
+
flexShrink: 0,
|
|
394
396
|
}, children: [props.mat.serial && props.mat.serial.length >= 1 && !props.hideAvatar ? (_jsx("div", { children: _jsx(Avatar, { style: { width: "30px", height: "30px" }, children: props.mat.serial.slice(-1) }) })) : undefined, props.hideWarningIcon ? undefined : (_jsx("div", { children: _jsx(Warning, { mat: props.mat }) }))] })] }) })] }));
|
|
395
397
|
});
|
|
396
398
|
export const MatSummary = memo(MatCard);
|
|
@@ -7,7 +7,8 @@ export declare enum MoveMaterialNodeKindType {
|
|
|
7
7
|
CompletedExpandedMaterialZone = 3,
|
|
8
8
|
PalletFaceZone = 4,
|
|
9
9
|
QueueZone = 5,
|
|
10
|
-
BasketZone = 6
|
|
10
|
+
BasketZone = 6,
|
|
11
|
+
BasketSlotZone = 7
|
|
11
12
|
}
|
|
12
13
|
export type MoveMaterialNodeKind = {
|
|
13
14
|
readonly type: MoveMaterialNodeKindType.Material;
|
|
@@ -28,6 +29,10 @@ export type MoveMaterialNodeKind = {
|
|
|
28
29
|
} | {
|
|
29
30
|
readonly type: MoveMaterialNodeKindType.BasketZone;
|
|
30
31
|
readonly basketId: number;
|
|
32
|
+
} | {
|
|
33
|
+
readonly type: MoveMaterialNodeKindType.BasketSlotZone;
|
|
34
|
+
readonly basketId: number;
|
|
35
|
+
readonly slot: number;
|
|
31
36
|
};
|
|
32
37
|
export type MoveMaterialIdentifier = string;
|
|
33
38
|
export declare function uniqueIdForNodeKind(kind: MoveMaterialNodeKind): MoveMaterialIdentifier;
|