@seedtactics/insight-client 17.0.1-beta.5 → 17.0.1-beta.7
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-CNJT3DX_.js +388 -0
- package/dist/components/station-monitor/BasketLoadStationWork.js +60 -15
- package/dist/index.html +1 -1
- package/dist/network/api.d.ts +22 -0
- package/dist/network/api.js +51 -0
- package/docs/mazak.md +13 -0
- package/package.json +1 -1
- package/dist/assets/index-C6EBFHuW.js +0 -388
|
@@ -69,14 +69,48 @@ function basketAction(mat, basketId) {
|
|
|
69
69
|
}
|
|
70
70
|
return undefined;
|
|
71
71
|
}
|
|
72
|
-
function
|
|
72
|
+
function stationWork(material, basket) {
|
|
73
73
|
const classifiedActions = LazySeq.of(material)
|
|
74
|
-
.collect((mat) => basketAction(mat, basketId))
|
|
74
|
+
.collect((mat) => basketAction(mat, basket.basketId))
|
|
75
75
|
.toRArray();
|
|
76
76
|
if (classifiedActions.some((action) => action.type === "invalid")) {
|
|
77
77
|
return { type: "inconsistent" };
|
|
78
78
|
}
|
|
79
79
|
const validActions = classifiedActions.filter((action) => action.type === "valid");
|
|
80
|
+
const descriptor = basket.loadStationWork;
|
|
81
|
+
if (descriptor !== undefined) {
|
|
82
|
+
if (!descriptor ||
|
|
83
|
+
!isNonBlank(descriptor.workId) ||
|
|
84
|
+
typeof descriptor.readyToConfirm !== "boolean")
|
|
85
|
+
return { type: "inconsistent" };
|
|
86
|
+
const awaiting = descriptor.awaitingMaterialSlots ?? [];
|
|
87
|
+
if (!Array.isArray(awaiting) ||
|
|
88
|
+
!awaiting.every(isPositiveInteger) ||
|
|
89
|
+
new Set(awaiting).size !== awaiting.length ||
|
|
90
|
+
(descriptor.readyToConfirm && awaiting.length > 0) ||
|
|
91
|
+
validActions.some((action) => action.workId !== descriptor.workId))
|
|
92
|
+
return { type: "inconsistent" };
|
|
93
|
+
const empty = descriptor.type === api.BasketLoadStationWorkType.ConfirmEmptyBasket;
|
|
94
|
+
if (empty) {
|
|
95
|
+
if (validActions.length > 0 ||
|
|
96
|
+
awaiting.length > 0 ||
|
|
97
|
+
material.some((mat) => mat.location.type === api.LocType.InBasket && mat.location.basketId === basket.basketId))
|
|
98
|
+
return { type: "inconsistent" };
|
|
99
|
+
}
|
|
100
|
+
else if (descriptor.type !== api.BasketLoadStationWorkType.Material ||
|
|
101
|
+
(descriptor.readyToConfirm && validActions.length === 0)) {
|
|
102
|
+
return { type: "inconsistent" };
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
type: "active",
|
|
106
|
+
work: {
|
|
107
|
+
workId: descriptor.workId,
|
|
108
|
+
ready: descriptor.readyToConfirm,
|
|
109
|
+
confirmEmpty: empty,
|
|
110
|
+
awaitingSlots: awaiting,
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
80
114
|
if (validActions.length === 0)
|
|
81
115
|
return { type: "none" };
|
|
82
116
|
const tagged = validActions.filter((action) => isNonBlank(action.workId));
|
|
@@ -85,8 +119,8 @@ function confirmableWork(material, basketId) {
|
|
|
85
119
|
return { type: "inconsistent" };
|
|
86
120
|
}
|
|
87
121
|
return {
|
|
88
|
-
type: "
|
|
89
|
-
work: { workId: tagged[0].workId },
|
|
122
|
+
type: "active",
|
|
123
|
+
work: { workId: tagged[0].workId, ready: true, confirmEmpty: false, awaitingSlots: [] },
|
|
90
124
|
};
|
|
91
125
|
}
|
|
92
126
|
function loadingInstruction(mat) {
|
|
@@ -105,21 +139,28 @@ function SlotMaterial({ material, fsize, }) {
|
|
|
105
139
|
}
|
|
106
140
|
export function BasketLoadStationWorkflow({ stationNumber, basket, material, fsize, submitCommand, }) {
|
|
107
141
|
const [submission, setSubmission] = useState();
|
|
108
|
-
const workState = useMemo(() =>
|
|
109
|
-
const work = workState.type === "
|
|
110
|
-
const submissionState = submission !== undefined &&
|
|
142
|
+
const workState = useMemo(() => stationWork(material, basket), [basket, material]);
|
|
143
|
+
const work = workState.type === "active" ? workState.work : undefined;
|
|
144
|
+
const submissionState = submission !== undefined &&
|
|
145
|
+
submission.workId === work?.workId &&
|
|
146
|
+
// A conflict rejects the submitted status snapshot, not the preserved occurrence.
|
|
147
|
+
// Compare the captured snapshot even when refresh precedes the response.
|
|
148
|
+
(submission.state !== "conflict" ||
|
|
149
|
+
(submission.basket === basket && submission.material === material))
|
|
150
|
+
? submission.state
|
|
151
|
+
: "idle";
|
|
111
152
|
const materialBySlot = useMemo(() => LazySeq.of(material)
|
|
112
153
|
.filter((mat) => mat.location.type === api.LocType.InBasket &&
|
|
113
154
|
mat.location.basketId === basket.basketId &&
|
|
114
155
|
mat.location.basketSlot !== undefined)
|
|
115
156
|
.groupBy((mat) => mat.location.basketSlot ?? 0)
|
|
116
|
-
.toHashMap((entry) => entry), [basket
|
|
157
|
+
.toHashMap((entry) => entry), [basket, material]);
|
|
117
158
|
const loadsBySlot = useMemo(() => LazySeq.of(material)
|
|
118
159
|
.filter((mat) => mat.action.type === api.ActionType.LoadingToBasket &&
|
|
119
160
|
mat.action.loadToBasketId === basket.basketId &&
|
|
120
161
|
mat.action.loadToBasketSlot !== undefined)
|
|
121
162
|
.groupBy((mat) => mat.action.loadToBasketSlot ?? 0)
|
|
122
|
-
.toHashMap((entry) => entry), [basket
|
|
163
|
+
.toHashMap((entry) => entry), [basket, material]);
|
|
123
164
|
const slots = useMemo(() => LazySeq.of(basket.emptySlots ?? [])
|
|
124
165
|
.concat(basket.unknownSlots ?? [])
|
|
125
166
|
.concat(materialBySlot.keysToLazySeq())
|
|
@@ -127,19 +168,21 @@ export function BasketLoadStationWorkflow({ stationNumber, basket, material, fsi
|
|
|
127
168
|
.distinctBy((slot) => slot)
|
|
128
169
|
.toSortedArray((slot) => slot), [basket.emptySlots, basket.unknownSlots, materialBySlot, loadsBySlot]);
|
|
129
170
|
async function submit() {
|
|
130
|
-
if (work === undefined || submitCommand === undefined)
|
|
171
|
+
if (work === undefined || !work.ready || submitCommand === undefined)
|
|
131
172
|
return;
|
|
132
173
|
const submittedWorkId = work.workId;
|
|
133
|
-
|
|
174
|
+
const pending = { workId: submittedWorkId, basket, material, state: "submitting" };
|
|
175
|
+
setSubmission(pending);
|
|
134
176
|
try {
|
|
135
177
|
const state = await submitCommand(stationNumber, { workId: submittedWorkId });
|
|
136
|
-
setSubmission((current) => current
|
|
178
|
+
setSubmission((current) => (current === pending ? { ...pending, state } : current));
|
|
137
179
|
}
|
|
138
180
|
catch {
|
|
139
|
-
setSubmission((current) => current
|
|
181
|
+
setSubmission((current) => (current === pending ? { ...pending, state: "error" } : current));
|
|
140
182
|
}
|
|
141
183
|
}
|
|
142
|
-
const submissionDisabled =
|
|
184
|
+
const submissionDisabled = !work?.ready ||
|
|
185
|
+
submissionState === "submitting" ||
|
|
143
186
|
submissionState === "accepted" ||
|
|
144
187
|
submissionState === "conflict";
|
|
145
188
|
return (_jsxs(Stack, { spacing: 2, sx: { mt: 2 }, children: [_jsx(Typography, { variant: "h6", children: "Basket slots" }), _jsx(Box, { sx: {
|
|
@@ -155,5 +198,7 @@ export function BasketLoadStationWorkflow({ stationNumber, basket, material, fsi
|
|
|
155
198
|
basketId: basket.basketId,
|
|
156
199
|
slot,
|
|
157
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));
|
|
158
|
-
}) }), work &&
|
|
201
|
+
}) }), work?.confirmEmpty && _jsxs(Typography, { children: ["Confirm basket ", basket.basketId, " is empty."] }), work && !work.ready && (_jsx(Alert, { severity: "info", children: work.awaitingSlots.length > 0
|
|
202
|
+
? `Waiting for material for slots ${work.awaitingSlots.join(", ")}.`
|
|
203
|
+
: "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] }));
|
|
159
204
|
}
|
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-CNJT3DX_.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
|
@@ -1060,6 +1060,7 @@ export declare enum WorkorderSerialCloseout {
|
|
|
1060
1060
|
}
|
|
1061
1061
|
export declare class BasketStatus implements IBasketStatus {
|
|
1062
1062
|
basketId: number;
|
|
1063
|
+
loadStationWork?: BasketLoadStationWork | undefined;
|
|
1063
1064
|
position?: BasketPosition | undefined;
|
|
1064
1065
|
emptySlots?: number[];
|
|
1065
1066
|
unknownSlots?: number[];
|
|
@@ -1070,10 +1071,31 @@ export declare class BasketStatus implements IBasketStatus {
|
|
|
1070
1071
|
}
|
|
1071
1072
|
export interface IBasketStatus {
|
|
1072
1073
|
basketId: number;
|
|
1074
|
+
loadStationWork?: BasketLoadStationWork | undefined;
|
|
1073
1075
|
position?: BasketPosition | undefined;
|
|
1074
1076
|
emptySlots?: number[];
|
|
1075
1077
|
unknownSlots?: number[];
|
|
1076
1078
|
}
|
|
1079
|
+
export declare class BasketLoadStationWork implements IBasketLoadStationWork {
|
|
1080
|
+
workId: string;
|
|
1081
|
+
type: BasketLoadStationWorkType;
|
|
1082
|
+
readyToConfirm: boolean;
|
|
1083
|
+
awaitingMaterialSlots?: number[];
|
|
1084
|
+
constructor(data?: IBasketLoadStationWork);
|
|
1085
|
+
init(_data?: any): void;
|
|
1086
|
+
static fromJS(data: any): BasketLoadStationWork;
|
|
1087
|
+
toJSON(data?: any): any;
|
|
1088
|
+
}
|
|
1089
|
+
export interface IBasketLoadStationWork {
|
|
1090
|
+
workId: string;
|
|
1091
|
+
type: BasketLoadStationWorkType;
|
|
1092
|
+
readyToConfirm: boolean;
|
|
1093
|
+
awaitingMaterialSlots?: number[];
|
|
1094
|
+
}
|
|
1095
|
+
export declare enum BasketLoadStationWorkType {
|
|
1096
|
+
Material = "Material",
|
|
1097
|
+
ConfirmEmptyBasket = "ConfirmEmptyBasket"
|
|
1098
|
+
}
|
|
1077
1099
|
export declare class BasketPosition implements IBasketPosition {
|
|
1078
1100
|
location: BasketLocationEnum;
|
|
1079
1101
|
locationNum: number;
|
package/dist/network/api.js
CHANGED
|
@@ -4412,6 +4412,9 @@ export class BasketStatus {
|
|
|
4412
4412
|
init(_data) {
|
|
4413
4413
|
if (_data) {
|
|
4414
4414
|
this.basketId = _data["BasketId"];
|
|
4415
|
+
this.loadStationWork = _data["LoadStationWork"]
|
|
4416
|
+
? BasketLoadStationWork.fromJS(_data["LoadStationWork"])
|
|
4417
|
+
: undefined;
|
|
4415
4418
|
this.position = _data["Position"]
|
|
4416
4419
|
? BasketPosition.fromJS(_data["Position"])
|
|
4417
4420
|
: undefined;
|
|
@@ -4436,6 +4439,9 @@ export class BasketStatus {
|
|
|
4436
4439
|
toJSON(data) {
|
|
4437
4440
|
data = typeof data === "object" ? data : {};
|
|
4438
4441
|
data["BasketId"] = this.basketId;
|
|
4442
|
+
data["LoadStationWork"] = this.loadStationWork
|
|
4443
|
+
? this.loadStationWork.toJSON()
|
|
4444
|
+
: undefined;
|
|
4439
4445
|
data["Position"] = this.position ? this.position.toJSON() : undefined;
|
|
4440
4446
|
if (Array.isArray(this.emptySlots)) {
|
|
4441
4447
|
data["EmptySlots"] = [];
|
|
@@ -4450,6 +4456,51 @@ export class BasketStatus {
|
|
|
4450
4456
|
return data;
|
|
4451
4457
|
}
|
|
4452
4458
|
}
|
|
4459
|
+
export class BasketLoadStationWork {
|
|
4460
|
+
constructor(data) {
|
|
4461
|
+
if (data) {
|
|
4462
|
+
for (var property in data) {
|
|
4463
|
+
if (data.hasOwnProperty(property))
|
|
4464
|
+
this[property] = data[property];
|
|
4465
|
+
}
|
|
4466
|
+
}
|
|
4467
|
+
}
|
|
4468
|
+
init(_data) {
|
|
4469
|
+
if (_data) {
|
|
4470
|
+
this.workId = _data["WorkId"];
|
|
4471
|
+
this.type = _data["Type"];
|
|
4472
|
+
this.readyToConfirm = _data["ReadyToConfirm"];
|
|
4473
|
+
if (Array.isArray(_data["AwaitingMaterialSlots"])) {
|
|
4474
|
+
this.awaitingMaterialSlots = [];
|
|
4475
|
+
for (let item of _data["AwaitingMaterialSlots"])
|
|
4476
|
+
this.awaitingMaterialSlots.push(item);
|
|
4477
|
+
}
|
|
4478
|
+
}
|
|
4479
|
+
}
|
|
4480
|
+
static fromJS(data) {
|
|
4481
|
+
data = typeof data === "object" ? data : {};
|
|
4482
|
+
let result = new BasketLoadStationWork();
|
|
4483
|
+
result.init(data);
|
|
4484
|
+
return result;
|
|
4485
|
+
}
|
|
4486
|
+
toJSON(data) {
|
|
4487
|
+
data = typeof data === "object" ? data : {};
|
|
4488
|
+
data["WorkId"] = this.workId;
|
|
4489
|
+
data["Type"] = this.type;
|
|
4490
|
+
data["ReadyToConfirm"] = this.readyToConfirm;
|
|
4491
|
+
if (Array.isArray(this.awaitingMaterialSlots)) {
|
|
4492
|
+
data["AwaitingMaterialSlots"] = [];
|
|
4493
|
+
for (let item of this.awaitingMaterialSlots)
|
|
4494
|
+
data["AwaitingMaterialSlots"].push(item);
|
|
4495
|
+
}
|
|
4496
|
+
return data;
|
|
4497
|
+
}
|
|
4498
|
+
}
|
|
4499
|
+
export var BasketLoadStationWorkType;
|
|
4500
|
+
(function (BasketLoadStationWorkType) {
|
|
4501
|
+
BasketLoadStationWorkType["Material"] = "Material";
|
|
4502
|
+
BasketLoadStationWorkType["ConfirmEmptyBasket"] = "ConfirmEmptyBasket";
|
|
4503
|
+
})(BasketLoadStationWorkType || (BasketLoadStationWorkType = {}));
|
|
4453
4504
|
export class BasketPosition {
|
|
4454
4505
|
constructor(data) {
|
|
4455
4506
|
if (data) {
|
package/docs/mazak.md
CHANGED
|
@@ -13,6 +13,19 @@ FMS Insight works with all Palletech cell controller versions from Mazak: Versio
|
|
|
13
13
|
and Smooth PMC. FMS Insight can read all events from the cell controller and can also edit almost
|
|
14
14
|
all the data in the cell controller.
|
|
15
15
|
|
|
16
|
+
## Load station numbering
|
|
17
|
+
|
|
18
|
+
In the Mazak configuration section, Load Station Numbers = 10,30 maps controller L/U 1 to Insight
|
|
19
|
+
station 10 and controller L/U 2 to Insight station 30. This works like Machine Numbers: list
|
|
20
|
+
positions identify controller equipment, while values identify equipment in jobs, logs and APIs.
|
|
21
|
+
Both job downloads and status/event reads translate through the same map. Station display names are
|
|
22
|
+
maintained separately.
|
|
23
|
+
|
|
24
|
+
Omitting the list preserves identity numbering. Explicit lists must contain unique positive IDs and
|
|
25
|
+
cover every controller L/U station used. Job routes outside the map are rejected. The old Starting
|
|
26
|
+
Load Station Number setting has been removed and is rejected; replace it with an explicit list when
|
|
27
|
+
updating configuration.
|
|
28
|
+
|
|
16
29
|
## Open Database Kit
|
|
17
30
|
|
|
18
31
|
To facilitate the communication between FMS Insight and the Mazak cell controller, you must acquire
|