@seedtactics/insight-client 16.5.2 → 16.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dist/assets/ProgramHighlight-DPTeZ8Si.js +3 -0
  2. package/dist/assets/index-bPAFn3jp.js +364 -0
  3. package/dist/cell-status/basket-cycles.d.ts +21 -0
  4. package/dist/cell-status/basket-cycles.js +80 -0
  5. package/dist/cell-status/current-status.js +11 -3
  6. package/dist/cell-status/estimated-cycle-times.js +8 -4
  7. package/dist/cell-status/inspections.js +2 -2
  8. package/dist/cell-status/loading.js +4 -0
  9. package/dist/cell-status/material-details.d.ts +12 -4
  10. package/dist/cell-status/material-details.js +24 -13
  11. package/dist/cell-status/rebookings.js +15 -17
  12. package/dist/cell-status/scheduled-jobs.d.ts +1 -1
  13. package/dist/cell-status/scheduled-jobs.js +10 -3
  14. package/dist/cell-status/sim-production.js +3 -3
  15. package/dist/cell-status/sim-station-use.d.ts +1 -0
  16. package/dist/cell-status/sim-station-use.js +14 -8
  17. package/dist/cell-status/station-cycles.d.ts +29 -2
  18. package/dist/cell-status/station-cycles.js +81 -11
  19. package/dist/cell-status/tool-replacements.js +1 -1
  20. package/dist/cell-status/tool-usage.js +1 -1
  21. package/dist/components/App.js +101 -66
  22. package/dist/components/BarcodeScanning.js +12 -2
  23. package/dist/components/ErrorsAndLoading.js +10 -1
  24. package/dist/components/LogEntry.d.ts +0 -1
  25. package/dist/components/LogEntry.js +50 -26
  26. package/dist/components/Navigation.js +30 -4
  27. package/dist/components/analysis/AnalysisSelectToolbar.js +5 -1
  28. package/dist/components/analysis/BasketCycleCards.d.ts +1 -0
  29. package/dist/components/analysis/BasketCycleCards.js +145 -0
  30. package/dist/components/analysis/BufferChart.js +10 -4
  31. package/dist/components/analysis/CostPerPiece.js +28 -8
  32. package/dist/components/analysis/CycleChart.js +1 -1
  33. package/dist/components/analysis/DataTable.js +6 -4
  34. package/dist/components/analysis/HeatChart.js +27 -14
  35. package/dist/components/analysis/InspectionSankey.js +17 -6
  36. package/dist/components/analysis/PalletCycleCards.js +15 -4
  37. package/dist/components/analysis/PartCycleCards.js +62 -18
  38. package/dist/components/analysis/StationDataTable.js +14 -11
  39. package/dist/components/analysis/ToolReplacements.js +16 -10
  40. package/dist/components/log-entry-queue-filter.d.ts +2 -0
  41. package/dist/components/log-entry-queue-filter.js +21 -0
  42. package/dist/components/operations/AllMaterial.js +26 -10
  43. package/dist/components/operations/ChartRangeEdit.js +82 -4
  44. package/dist/components/operations/CloseoutReport.js +13 -4
  45. package/dist/components/operations/CompletedParts.js +23 -11
  46. package/dist/components/operations/CurrentWorkorders.js +31 -9
  47. package/dist/components/operations/OEEChart.js +8 -2
  48. package/dist/components/operations/Outliers.js +18 -7
  49. package/dist/components/operations/ProgramHighlight.js +4 -6
  50. package/dist/components/operations/Programs.js +9 -3
  51. package/dist/components/operations/Rebookings.js +8 -4
  52. package/dist/components/operations/RecentCycleChart.js +5 -3
  53. package/dist/components/operations/RecentProduction.js +30 -13
  54. package/dist/components/operations/RecentSchedules.js +6 -2
  55. package/dist/components/operations/RecentStationCycles.js +38 -11
  56. package/dist/components/operations/ShiftSettings.js +3 -3
  57. package/dist/components/operations/SimDayUsage.js +27 -4
  58. package/dist/components/operations/ToolReport.js +5 -1
  59. package/dist/components/operations/WorkorderGantt.js +22 -2
  60. package/dist/components/quality/QualityMaterial.js +11 -8
  61. package/dist/components/quality/RecentFailedInspections.js +3 -1
  62. package/dist/components/routes.d.ts +3 -0
  63. package/dist/components/routes.js +2 -0
  64. package/dist/components/station-monitor/BulkRawMaterial.js +11 -7
  65. package/dist/components/station-monitor/Closeout.js +14 -2
  66. package/dist/components/station-monitor/CustomStationMonitorDialog.js +1 -1
  67. package/dist/components/station-monitor/Inspection.js +23 -11
  68. package/dist/components/station-monitor/InvalidateCycle.js +3 -3
  69. package/dist/components/station-monitor/JobDetails.js +15 -2
  70. package/dist/components/station-monitor/LoadStation.js +274 -31
  71. package/dist/components/station-monitor/Material.js +71 -11
  72. package/dist/components/station-monitor/MoveMaterialArrows.js +4 -4
  73. package/dist/components/station-monitor/QuarantineButton.js +11 -0
  74. package/dist/components/station-monitor/Queues.js +28 -9
  75. package/dist/components/station-monitor/QueuesAddMaterial.js +8 -6
  76. package/dist/components/station-monitor/SelectInspType.js +1 -1
  77. package/dist/components/station-monitor/SelectWorkorder.js +1 -1
  78. package/dist/components/station-monitor/StationToolbar.js +17 -5
  79. package/dist/components/station-monitor/SystemOverview.d.ts +19 -1
  80. package/dist/components/station-monitor/SystemOverview.js +439 -20
  81. package/dist/components/station-monitor/Whiteboard.js +15 -7
  82. package/dist/data/all-material-bins.d.ts +7 -0
  83. package/dist/data/all-material-bins.js +47 -1
  84. package/dist/data/cost-per-piece.js +11 -8
  85. package/dist/data/current-cycles.d.ts +1 -1
  86. package/dist/data/current-cycles.js +62 -17
  87. package/dist/data/move-arrows.d.ts +5 -1
  88. package/dist/data/move-arrows.js +54 -4
  89. package/dist/data/part-summary.js +13 -13
  90. package/dist/data/path-lookup.js +6 -23
  91. package/dist/data/queue-material.d.ts +1 -1
  92. package/dist/data/queue-material.js +18 -17
  93. package/dist/data/results.completed-parts.js +4 -3
  94. package/dist/data/results.cycles.d.ts +15 -6
  95. package/dist/data/results.cycles.js +51 -30
  96. package/dist/data/results.inspection.js +11 -6
  97. package/dist/data/results.oee.js +8 -8
  98. package/dist/data/results.schedules.js +2 -11
  99. package/dist/data/tools-programs.js +5 -6
  100. package/dist/index.html +1 -1
  101. package/dist/network/api.d.ts +22 -4
  102. package/dist/network/api.js +40 -5
  103. package/dist/network/backend-mock.js +15 -8
  104. package/dist/network/backend.js +3 -3
  105. package/dist/network/websocket.js +15 -15
  106. package/dist/util/chart-helpers.d.ts +1 -1
  107. package/dist/util/chart-helpers.js +14 -8
  108. package/package.json +29 -31
  109. package/dist/assets/ProgramHighlight-LvRM40Qr.js +0 -3
  110. package/dist/assets/index-gAFi3Oss.js +0 -364
@@ -31,7 +31,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
31
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
32
  */
33
33
  import * as api from "../network/api.js";
34
- import { LazySeq } from "@seedtactics/immutable-collections";
34
+ import { LazySeq, OrderedMap } from "@seedtactics/immutable-collections";
35
35
  import { LogBackend } from "../network/backend.js";
36
36
  import { differenceInSeconds } from "date-fns";
37
37
  import { useAtomValue } from "jotai";
@@ -150,9 +150,6 @@ export function extractJobRawMaterial(jobs, mats, queue) {
150
150
  return prec;
151
151
  });
152
152
  }
153
- function compareByQueuePos(m1, m2) {
154
- return (m1.location.queuePosition ?? 10000000000) - (m2.location.queuePosition ?? 10000000000);
155
- }
156
153
  export function selectQueueData(queuesToCheck, curSt, rawMatQueues, inProcQueues) {
157
154
  const queues = [];
158
155
  const queueNames = [...queuesToCheck];
@@ -160,12 +157,14 @@ export function selectQueueData(queuesToCheck, curSt, rawMatQueues, inProcQueues
160
157
  for (const queueName of queueNames) {
161
158
  const isRawMat = rawMatQueues.has(queueName);
162
159
  if (isRawMat) {
163
- const material = [];
160
+ const materialByPos = OrderedMap.empty();
164
161
  const matByPartThenUniq = new Map();
165
162
  for (const m of curSt.material) {
166
- if (m.location.type === api.LocType.InQueue && m.location.currentQueue === queueName) {
163
+ if (m.location.type === api.LocType.InQueue &&
164
+ m.location.currentQueue === queueName &&
165
+ m.location.queuePosition !== undefined) {
167
166
  if ((m.serial && m.serial !== "") || m.action.type !== api.ActionType.Waiting) {
168
- material.push(m);
167
+ materialByPos.set(m.location.queuePosition, m);
169
168
  }
170
169
  else {
171
170
  let matsForPart = matByPartThenUniq.get(m.partName);
@@ -208,7 +207,7 @@ export function selectQueueData(queuesToCheck, curSt, rawMatQueues, inProcQueues
208
207
  free: false,
209
208
  rawMaterialQueue: true,
210
209
  inProcQueue: false,
211
- material: material.sort(compareByQueuePos),
210
+ material: [...materialByPos.values()],
212
211
  groupedRawMat: matGroups,
213
212
  });
214
213
  }
@@ -218,17 +217,19 @@ export function selectQueueData(queuesToCheck, curSt, rawMatQueues, inProcQueues
218
217
  free: false,
219
218
  rawMaterialQueue: false,
220
219
  inProcQueue: inProcQueues.has(queueName),
221
- material: curSt.material
222
- .filter((m) => m.location.type === api.LocType.InQueue && m.location.currentQueue === queueName)
223
- .sort(compareByQueuePos),
220
+ material: LazySeq.of(curSt.material)
221
+ .filter((m) => m.location.type === api.LocType.InQueue &&
222
+ m.location.currentQueue === queueName &&
223
+ m.location.queuePosition !== undefined)
224
+ .toSortedArray((m) => m.location.queuePosition ?? 0),
224
225
  });
225
226
  }
226
227
  }
227
228
  return queues;
228
229
  }
229
- export async function loadRawMaterialEvents(material) {
230
+ export async function loadRawMaterialEvents(materials) {
230
231
  const events = [];
231
- for (const chunk of LazySeq.of(material).chunk(15)) {
232
+ for (const chunk of LazySeq.of(materials).chunk(15)) {
232
233
  events.push(...(await LogBackend.logForMaterials(chunk.map((m) => m.materialID))));
233
234
  }
234
235
  events.sort((a, b) => a.endUTC.getTime() - b.endUTC.getTime());
@@ -236,18 +237,18 @@ export async function loadRawMaterialEvents(material) {
236
237
  for (let i = 0; i < events.length; i++) {
237
238
  const evt = events[i];
238
239
  if (evt.type === api.LogType.AddToQueue || evt.type === api.LogType.RemoveFromQueue) {
239
- const material = [...evt.material];
240
+ const groupedMaterial = [...evt.material];
240
241
  while (i + 1 < events.length &&
241
242
  events[i + 1].type === evt.type &&
242
243
  differenceInSeconds(events[i + 1].endUTC, evt.endUTC) < 10) {
243
- material.push(...events[i + 1].material);
244
+ groupedMaterial.push(...events[i + 1].material);
244
245
  i += 1;
245
246
  }
246
- if (material.length === evt.material.length) {
247
+ if (groupedMaterial.length === evt.material.length) {
247
248
  groupedEvents.push(evt);
248
249
  }
249
250
  else {
250
- groupedEvents.push({ ...evt, material: material });
251
+ groupedEvents.push({ ...evt, material: groupedMaterial });
251
252
  }
252
253
  }
253
254
  else {
@@ -32,6 +32,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
32
  */
33
33
  import { startOfDay } from "date-fns";
34
34
  import copy from "copy-to-clipboard";
35
+ import { isMachineCycle } from "../cell-status/station-cycles.js";
35
36
  import { hashValues, LazySeq } from "@seedtactics/immutable-collections";
36
37
  // --------------------------------------------------------------------------------
37
38
  // Actual
@@ -85,7 +86,7 @@ export function binCyclesByDayAndPart(cycles, matsById, start, end) {
85
86
  const activeTimeByMatId = LazySeq.of(cycles)
86
87
  .filter((cycle) => cycle.endTime >= start &&
87
88
  cycle.endTime <= end &&
88
- !cycle.isLabor &&
89
+ isMachineCycle(cycle) &&
89
90
  cycle.activeMinutes > 0 &&
90
91
  cycle.material.length > 0)
91
92
  .flatMap((cycle) => cycle.material.map((mat) => ({
@@ -99,7 +100,7 @@ export function binCyclesByDayAndPart(cycles, matsById, start, end) {
99
100
  .filter(([_, unloadTime]) => unloadTime >= start && unloadTime <= end)
100
101
  .map(([proc, unloadTime]) => ({
101
102
  day: startOfDay(unloadTime),
102
- part: details.partName + "-" + proc.toString(),
103
+ part: details.partName + "-" + proc,
103
104
  value: {
104
105
  count: 1,
105
106
  activeMachineMins: activeTimeByMatId.get(new MatIdAndProcess(matId, parseInt(proc))) ?? 0,
@@ -177,5 +178,5 @@ export function buildCompletedPartsHeatmapTable(points) {
177
178
  return table;
178
179
  }
179
180
  export function copyCompletedPartsHeatmapToClipboard(points) {
180
- copy(buildCompletedPartsHeatmapTable(points));
181
+ void copy(buildCompletedPartsHeatmapTable(points));
181
182
  }
@@ -14,7 +14,10 @@ export interface CycleFilterOptions {
14
14
  readonly allLoadStationNames: ReadonlyArray<string>;
15
15
  readonly allMachineNames: ReadonlyArray<string>;
16
16
  readonly allMachineOperations: ReadonlyArray<PartAndStationOperation>;
17
+ readonly hasBasketCycles: boolean;
17
18
  }
19
+ export type CarrierKindFilter = "Any" | "Pallet" | "Basket";
20
+ export declare function normalizeCarrierKindFilter(carrierKind: CarrierKindFilter | undefined, hasBasketCycles: boolean): CarrierKindFilter | undefined;
18
21
  export type PartCycleChartData = PartCycleData & {
19
22
  readonly x: Date;
20
23
  readonly y: number;
@@ -34,9 +37,10 @@ export interface StationCycleFilter {
34
37
  readonly pallet?: number;
35
38
  readonly station?: string;
36
39
  readonly operation?: PartAndStationOperation;
40
+ readonly carrierKind?: CarrierKindFilter;
37
41
  }
38
42
  export declare function emptyStationCycles(allCycles: Iterable<PartCycleData>): FilteredStationCycles & CycleFilterOptions;
39
- export declare function filterStationCycles(allCycles: Iterable<PartCycleData>, { zoom, partAndProc, pallet, station, operation }: StationCycleFilter): FilteredStationCycles & CycleFilterOptions;
43
+ export declare function filterStationCycles(allCycles: Iterable<PartCycleData>, { zoom, partAndProc, pallet, station, operation, carrierKind }: StationCycleFilter): FilteredStationCycles & CycleFilterOptions;
40
44
  export interface LoadCycleData extends PartCycleChartData {
41
45
  readonly operations?: ReadonlyArray<{
42
46
  readonly mat: Readonly<api.ILogMaterial>;
@@ -55,8 +59,9 @@ export interface LoadCycleFilter {
55
59
  readonly partAndProc?: PartAndProcess;
56
60
  readonly pallet?: number;
57
61
  readonly station?: string;
62
+ readonly carrierKind?: CarrierKindFilter;
58
63
  }
59
- export declare function loadOccupancyCycles(allCycles: Iterable<PartCycleData>, { zoom, partAndProc, pallet, station }: LoadCycleFilter): FilteredLoadCycles & CycleFilterOptions;
64
+ export declare function loadOccupancyCycles(allCycles: Iterable<PartCycleData>, { zoom, partAndProc, pallet, station, carrierKind }: LoadCycleFilter): FilteredLoadCycles & CycleFilterOptions;
60
65
  export declare function plannedOperationMinutes(s: FilteredStationCycles, forSingleMat: boolean): number | undefined;
61
66
  export interface RecentCycle {
62
67
  readonly station: string;
@@ -75,12 +80,16 @@ export type ClipboardStationCycles = {
75
80
  readonly seriesLabel: string;
76
81
  readonly data: ReadonlyMap<string, ReadonlyArray<PartCycleData>>;
77
82
  };
78
- export declare function buildCycleTable(cycles: ClipboardStationCycles, matsById: HashMap<number, MaterialSummaryAndCompletedData>, startD: Date | undefined, endD: Date | undefined, hideMedian?: boolean): string;
83
+ export declare function buildCycleTable(cycles: ClipboardStationCycles, matsById: HashMap<number, MaterialSummaryAndCompletedData>, startD: Date | undefined, endD: Date | undefined, hideMedian?: boolean, loadStationNames?: {
84
+ [key: string]: string;
85
+ }, basketName?: string): string;
79
86
  export declare function copyCyclesToClipboard(cycles: ClipboardStationCycles, matsById: HashMap<number, MaterialSummaryAndCompletedData>, zoom: {
80
87
  start: Date;
81
88
  end: Date;
82
- } | undefined, hideMedian?: boolean): void;
83
- export declare function buildPalletCycleTable(points: PalletCyclesByPallet): string;
84
- export declare function copyPalletCyclesToClipboard(points: PalletCyclesByPallet): void;
89
+ } | undefined, hideMedian?: boolean, loadStationNames?: {
90
+ [key: string]: string;
91
+ }, basketName?: string): void;
92
+ export declare function buildPalletCycleTable(points: PalletCyclesByPallet, carrierColumnLabel?: string): string;
93
+ export declare function copyPalletCyclesToClipboard(points: PalletCyclesByPallet, carrierColumnLabel?: string): void;
85
94
  export declare function buildLogEntriesTable(cycles: Iterable<Readonly<api.ILogEntry>>): string;
86
95
  export declare function copyLogEntriesToClipboard(cycles: Iterable<Readonly<api.ILogEntry>>): void;
@@ -35,21 +35,29 @@ import { addMinutes, addSeconds } from "date-fns";
35
35
  import { durationToMinutes } from "../util/parseISODuration.js";
36
36
  import copy from "copy-to-clipboard";
37
37
  import { chunkCyclesWithSimilarEndTime, PartAndStationOperation, } from "../cell-status/estimated-cycle-times.js";
38
- import { stat_name_and_num } from "../cell-status/station-cycles.js";
38
+ import { basketDisplayName, basketForCycle, carrierLabel, displayStationName, isBasketLoadCycle, isLaborCycle, palletForCycle, } from "../cell-status/station-cycles.js";
39
39
  import { LazySeq, OrderedSet, OrderedMap } from "@seedtactics/immutable-collections";
40
+ export function normalizeCarrierKindFilter(carrierKind, hasBasketCycles) {
41
+ return !hasBasketCycles && carrierKind === "Basket" ? "Any" : carrierKind;
42
+ }
40
43
  function extractFilterOptions(cycles, selectedPart) {
41
44
  let palNames = OrderedSet.empty();
42
45
  let lulNames = OrderedSet.empty();
43
46
  let mcNames = OrderedSet.empty();
44
47
  let partNames = OrderedMap.empty();
45
48
  let oper = OrderedSet.empty();
49
+ let hasBasket = false;
46
50
  for (const c of cycles) {
47
- palNames = palNames.add(c.pallet);
48
- if (c.isLabor) {
49
- lulNames = lulNames.add(stat_name_and_num(c.stationGroup, c.stationNumber));
51
+ const pallet = palletForCycle(c);
52
+ if (pallet !== undefined) {
53
+ palNames = palNames.add(pallet);
54
+ }
55
+ hasBasket = hasBasket || isBasketLoadCycle(c);
56
+ if (isLaborCycle(c)) {
57
+ lulNames = lulNames.add(c.stationLabel);
50
58
  }
51
59
  else {
52
- mcNames = mcNames.add(stat_name_and_num(c.stationGroup, c.stationNumber));
60
+ mcNames = mcNames.add(c.stationLabel);
53
61
  if (selectedPart &&
54
62
  c.part == selectedPart.part &&
55
63
  c.material.some((m) => m.proc === selectedPart.proc)) {
@@ -69,6 +77,7 @@ function extractFilterOptions(cycles, selectedPart) {
69
77
  .flatMap(([part, procs]) => procs.toAscLazySeq().map((proc) => ({ part: part, proc: proc })))
70
78
  .toRArray(),
71
79
  allMachineOperations: oper.toAscLazySeq().toRArray(),
80
+ hasBasketCycles: hasBasket,
72
81
  };
73
82
  }
74
83
  export const FilterAnyMachineKey = "@@@_FMSInsight_FilterAnyMachineKey_@@@";
@@ -80,12 +89,12 @@ export function emptyStationCycles(allCycles) {
80
89
  data: new Map(),
81
90
  };
82
91
  }
83
- export function filterStationCycles(allCycles, { zoom, partAndProc, pallet, station, operation }) {
92
+ export function filterStationCycles(allCycles, { zoom, partAndProc, pallet, station, operation, carrierKind }) {
84
93
  const groupByPal = partAndProc && station && station !== FilterAnyMachineKey && station !== FilterAnyLoadKey;
85
94
  const groupByPart = pallet && !operation && station && station !== FilterAnyMachineKey && station !== FilterAnyLoadKey;
86
95
  return {
87
96
  ...extractFilterOptions(allCycles, partAndProc),
88
- seriesLabel: groupByPal ? "Pallet" : groupByPart ? "Part" : "Station",
97
+ seriesLabel: groupByPal ? "Carrier" : groupByPart ? "Part" : "Station",
89
98
  data: LazySeq.of(allCycles)
90
99
  .filter((e) => {
91
100
  if (zoom && (e.endTime < zoom.start || e.endTime > zoom.end)) {
@@ -95,20 +104,26 @@ export function filterStationCycles(allCycles, { zoom, partAndProc, pallet, stat
95
104
  (e.part !== partAndProc.part || !e.material.some((m) => m.proc === partAndProc.proc))) {
96
105
  return false;
97
106
  }
98
- if (pallet && e.pallet !== pallet) {
107
+ if (pallet && palletForCycle(e) !== pallet) {
108
+ return false;
109
+ }
110
+ if (carrierKind === "Pallet" && basketForCycle(e) !== undefined) {
111
+ return false;
112
+ }
113
+ if (carrierKind === "Basket" && basketForCycle(e) === undefined) {
99
114
  return false;
100
115
  }
101
116
  if (station === FilterAnyMachineKey) {
102
- if (e.isLabor) {
117
+ if (isLaborCycle(e)) {
103
118
  return false;
104
119
  }
105
120
  }
106
121
  else if (station === FilterAnyLoadKey) {
107
- if (!e.isLabor) {
122
+ if (!isLaborCycle(e)) {
108
123
  return false;
109
124
  }
110
125
  }
111
- else if (station && stat_name_and_num(e.stationGroup, e.stationNumber) !== station) {
126
+ else if (station && e.stationLabel !== station) {
112
127
  return false;
113
128
  }
114
129
  if (operation && operation.compare(PartAndStationOperation.ofPartCycle(e)) !== 0) {
@@ -118,7 +133,7 @@ export function filterStationCycles(allCycles, { zoom, partAndProc, pallet, stat
118
133
  })
119
134
  .toRLookup((e) => {
120
135
  if (groupByPal) {
121
- return e.pallet.toString();
136
+ return carrierLabel(e);
122
137
  }
123
138
  else if (groupByPart) {
124
139
  return (e.part +
@@ -130,7 +145,7 @@ export function filterStationCycles(allCycles, { zoom, partAndProc, pallet, stat
130
145
  .join(":"));
131
146
  }
132
147
  else {
133
- return stat_name_and_num(e.stationGroup, e.stationNumber);
148
+ return e.stationLabel;
134
149
  }
135
150
  }, (e) => ({
136
151
  ...e,
@@ -139,19 +154,25 @@ export function filterStationCycles(allCycles, { zoom, partAndProc, pallet, stat
139
154
  })),
140
155
  };
141
156
  }
142
- export function loadOccupancyCycles(allCycles, { zoom, partAndProc, pallet, station }) {
157
+ export function loadOccupancyCycles(allCycles, { zoom, partAndProc, pallet, station, carrierKind }) {
143
158
  const filteredCycles = LazySeq.of(allCycles).filter((e) => {
159
+ if (carrierKind === "Pallet" && basketForCycle(e) !== undefined) {
160
+ return false;
161
+ }
162
+ if (carrierKind === "Basket" && basketForCycle(e) === undefined) {
163
+ return false;
164
+ }
144
165
  if (!station || station === FilterAnyLoadKey) {
145
- return e.isLabor;
166
+ return isLaborCycle(e);
146
167
  }
147
168
  else {
148
- return stat_name_and_num(e.stationGroup, e.stationNumber) === station;
169
+ return isLaborCycle(e) && e.stationLabel === station;
149
170
  }
150
171
  });
151
172
  return {
152
173
  ...extractFilterOptions(allCycles, partAndProc),
153
174
  seriesLabel: "Station",
154
- data: chunkCyclesWithSimilarEndTime(filteredCycles, (c) => stat_name_and_num(c.stationGroup, c.stationNumber), (c) => c.endTime)
175
+ data: chunkCyclesWithSimilarEndTime(filteredCycles, (c) => c.stationLabel, (c) => c.endTime)
155
176
  .map(([statNameAndNum, cyclesForStat]) => [
156
177
  statNameAndNum,
157
178
  LazySeq.of(cyclesForStat)
@@ -164,7 +185,7 @@ export function loadOccupancyCycles(allCycles, { zoom, partAndProc, pallet, stat
164
185
  (e.part !== partAndProc.part || !e.material.some((m) => m.proc === partAndProc.proc))) {
165
186
  return false;
166
187
  }
167
- if (pallet && e.pallet !== pallet) {
188
+ if (pallet && palletForCycle(e) !== pallet) {
168
189
  return false;
169
190
  }
170
191
  return true;
@@ -207,7 +228,7 @@ export function plannedOperationMinutes(s, forSingleMat) {
207
228
  return planned?.mins;
208
229
  }
209
230
  export function recentCycles(allCycles) {
210
- return chunkCyclesWithSimilarEndTime(allCycles, (c) => stat_name_and_num(c.stationGroup, c.stationNumber), (c) => c.endTime)
231
+ return chunkCyclesWithSimilarEndTime(allCycles, (c) => c.stationLabel, (c) => c.endTime)
211
232
  .flatMap(function* procChunk([station, chunks]) {
212
233
  for (const chunk of chunks) {
213
234
  // sum elapsed time for chunk and subtract from end time to get start time
@@ -268,9 +289,9 @@ export function format_cycle_inspection(c, matsById) {
268
289
  }
269
290
  return ret.join(", ");
270
291
  }
271
- export function buildCycleTable(cycles, matsById, startD, endD, hideMedian) {
292
+ export function buildCycleTable(cycles, matsById, startD, endD, hideMedian, loadStationNames, basketName) {
272
293
  let table = "<table>\n<thead><tr>";
273
- table += "<th>Date</th><th>Part</th><th>Station</th><th>Pallet</th>";
294
+ table += "<th>Date</th><th>Part</th><th>Station</th><th>Carrier</th>";
274
295
  table += "<th>Serial</th><th>Workorder</th><th>Inspection</th>";
275
296
  table += "<th>Elapsed Min</th><th>Target Min</th>";
276
297
  if (!hideMedian) {
@@ -303,8 +324,8 @@ export function buildCycleTable(cycles, matsById, startD, endD, hideMedian) {
303
324
  .toRArray()
304
325
  .join(":") +
305
326
  "</td>";
306
- table += "<td>" + stat_name_and_num(cycle.stationGroup, cycle.stationNumber) + "</td>";
307
- table += "<td>" + cycle.pallet.toString() + "</td>";
327
+ table += "<td>" + displayStationName(cycle.stationGroup, cycle.stationNumber, loadStationNames) + "</td>";
328
+ table += "<td>" + carrierLabel(cycle, basketDisplayName(basketName)) + "</td>";
308
329
  table +=
309
330
  "<td>" +
310
331
  cycle.material
@@ -331,12 +352,12 @@ export function buildCycleTable(cycles, matsById, startD, endD, hideMedian) {
331
352
  table += "</tbody>\n</table>";
332
353
  return table;
333
354
  }
334
- export function copyCyclesToClipboard(cycles, matsById, zoom, hideMedian) {
335
- copy(buildCycleTable(cycles, matsById, zoom ? zoom.start : undefined, zoom ? zoom.end : undefined, hideMedian));
355
+ export function copyCyclesToClipboard(cycles, matsById, zoom, hideMedian, loadStationNames, basketName) {
356
+ copy(buildCycleTable(cycles, matsById, zoom ? zoom.start : undefined, zoom ? zoom.end : undefined, hideMedian, loadStationNames, basketName)).catch(console.error);
336
357
  }
337
- export function buildPalletCycleTable(points) {
358
+ export function buildPalletCycleTable(points, carrierColumnLabel = "Pallet") {
338
359
  let table = "<table>\n<thead><tr>";
339
- table += "<th>Pallet</th><th>Date</th><th>Elapsed (min)</th>";
360
+ table += `<th>${carrierColumnLabel}</th><th>Date</th><th>Elapsed (min)</th>`;
340
361
  table += "</tr></thead>\n<tbody>\n";
341
362
  const pals = points.keysToLazySeq().toSortedArray((x) => x);
342
363
  for (const pal of pals) {
@@ -360,8 +381,8 @@ export function buildPalletCycleTable(points) {
360
381
  table += "</tbody>\n</table>";
361
382
  return table;
362
383
  }
363
- export function copyPalletCyclesToClipboard(points) {
364
- copy(buildPalletCycleTable(points));
384
+ export function copyPalletCyclesToClipboard(points, carrierColumnLabel = "Pallet") {
385
+ copy(buildPalletCycleTable(points, carrierColumnLabel)).catch(console.error);
365
386
  }
366
387
  function stat_name(e) {
367
388
  switch (e.type) {
@@ -450,5 +471,5 @@ export function buildLogEntriesTable(cycles) {
450
471
  return table;
451
472
  }
452
473
  export function copyLogEntriesToClipboard(cycles) {
453
- copy(buildLogEntriesTable(cycles));
474
+ copy(buildLogEntriesTable(cycles)).catch(console.error);
454
475
  }
@@ -32,13 +32,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
32
  */
33
33
  import * as api from "../network/api.js";
34
34
  import { InspectionLogResultType } from "../cell-status/inspections.js";
35
- import { LazySeq, mkCompareByProperties } from "@seedtactics/immutable-collections";
35
+ import { LazySeq } from "@seedtactics/immutable-collections";
36
36
  import copy from "copy-to-clipboard";
37
37
  export function buildPathString(procs) {
38
38
  const pathStrs = [];
39
39
  for (const proc of procs) {
40
40
  for (const stop of proc.stops) {
41
- pathStrs.push("P" + proc.pallet.toString() + "," + "M" + stop.stationNum.toString());
41
+ pathStrs.push(`P${proc.pallet},M${stop.stationNum}`);
42
42
  }
43
43
  }
44
44
  return pathStrs.join(" -> ");
@@ -81,7 +81,7 @@ export function groupInspectionsByPath(entries, dateRange, sortOn) {
81
81
  return a;
82
82
  })
83
83
  .mapValues((mats) => ({
84
- material: mats.sort(mkCompareByProperties(sortOn, (e) => e.time.getTime())),
84
+ material: LazySeq.of(mats).toSortedArray(sortOn, (e) => e.time.getTime()),
85
85
  failedCnt: mats.reduce((acc, e) => acc + (e.failed ? 1 : 0), 0),
86
86
  }));
87
87
  }
@@ -114,9 +114,14 @@ export function extractPath(evts) {
114
114
  for (const e of evts) {
115
115
  if (e.type === api.LogType.Inspection) {
116
116
  const pathsJson = JSON.parse((e.details || {}).ActualPath || "[]");
117
+ if (!Array.isArray(pathsJson)) {
118
+ continue;
119
+ }
117
120
  const paths = [];
118
121
  for (const pathJson of pathsJson) {
119
- paths.push(api.MaterialProcessActualPath.fromJS(pathJson));
122
+ if (typeof pathJson === "object" && pathJson !== null) {
123
+ paths.push(api.MaterialProcessActualPath.fromJS(pathJson));
124
+ }
120
125
  }
121
126
  if (paths.length > 0) {
122
127
  return paths;
@@ -165,7 +170,7 @@ export function buildInspectionTable(part, inspType, entries) {
165
170
  return table;
166
171
  }
167
172
  export function copyInspectionEntriesToClipboard(part, inspType, entries) {
168
- copy(buildInspectionTable(part, inspType, entries));
173
+ void copy(buildInspectionTable(part, inspType, entries));
169
174
  }
170
175
  export function buildFailedInspTable(entries) {
171
176
  let table = "<table>\n<thead><tr>";
@@ -184,5 +189,5 @@ export function buildFailedInspTable(entries) {
184
189
  return table;
185
190
  }
186
191
  export function copyFailedInspectionsToClipboard(entries) {
187
- copy(buildFailedInspTable(entries));
192
+ void copy(buildFailedInspTable(entries));
188
193
  }
@@ -33,7 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
33
  import { startOfDay, addSeconds, addDays, max, min, differenceInMinutes } from "date-fns";
34
34
  import copy from "copy-to-clipboard";
35
35
  import { chunkCyclesWithSimilarEndTime } from "../cell-status/estimated-cycle-times.js";
36
- import { stat_name_and_num } from "../cell-status/station-cycles.js";
36
+ import { isLaborCycle } from "../cell-status/station-cycles.js";
37
37
  import { hashValues, LazySeq } from "@seedtactics/immutable-collections";
38
38
  // --------------------------------------------------------------------------------
39
39
  // Actual
@@ -86,7 +86,7 @@ function splitTimeToDays(startTime, endTime, mins) {
86
86
  }
87
87
  }
88
88
  function binCycles(cycles, f) {
89
- return chunkCyclesWithSimilarEndTime(LazySeq.of(cycles), (c) => stat_name_and_num(c.stationGroup, c.stationNumber), (c) => c.endTime)
89
+ return chunkCyclesWithSimilarEndTime(LazySeq.of(cycles), (c) => c.stationLabel, (c) => c.endTime)
90
90
  .flatMap(([statNameAndNum, cyclesForStat]) => cyclesForStat
91
91
  .flatMap((chunk) => {
92
92
  // sum elapsed time for chunk and subtract from end time to get start time
@@ -135,7 +135,7 @@ function mergeSortedIntervals(intervals) {
135
135
  export function binDowntimeToDayAndStat(simUses) {
136
136
  return LazySeq.of(simUses)
137
137
  .filter((simUse) => simUse.plannedDown)
138
- .toLookupOrderedMap((simUse) => simUse.station, (simUse) => simUse.start)
138
+ .toLookupOrderedMap((simUse) => simUse.stationLabel, (simUse) => simUse.start)
139
139
  .toAscLazySeq()
140
140
  .flatMap(([station, uses]) => mergeSortedIntervals(uses.valuesToAscLazySeq()).flatMap((simUse) => splitTimeToDays(simUse.start, simUse.end, differenceInMinutes(simUse.end, simUse.start)).map((x) => ({
141
141
  ...x,
@@ -146,11 +146,11 @@ export function binDowntimeToDayAndStat(simUses) {
146
146
  export function binSimStationUseByDayAndStat(simUses) {
147
147
  const downtimes = LazySeq.of(simUses)
148
148
  .filter((simUse) => simUse.plannedDown)
149
- .toLookupOrderedMap((simUse) => simUse.station, (simUse) => simUse.start)
149
+ .toLookupOrderedMap((simUse) => simUse.stationLabel, (simUse) => simUse.start)
150
150
  .mapValues((uses) => mergeSortedIntervals(uses.valuesToAscLazySeq()));
151
151
  return LazySeq.of(simUses)
152
152
  .filter((simUse) => !simUse.plannedDown)
153
- .toLookupOrderedMap((simUse) => simUse.station, (simUse) => simUse.start)
153
+ .toLookupOrderedMap((simUse) => simUse.stationLabel, (simUse) => simUse.start)
154
154
  .toAscLazySeq()
155
155
  .flatMap(([station, uses]) => {
156
156
  const sorted = mergeSortedIntervals(uses.valuesToAscLazySeq());
@@ -220,7 +220,7 @@ export function binSimStationUseByDayAndStat(simUses) {
220
220
  .toHashMap((s) => [new DayAndStation(s.day, s.station), s.value], (v1, v2) => v1 + v2);
221
221
  }
222
222
  export function buildOeeSeries(start, end, ty, cycles, statUse) {
223
- const filteredCycles = LazySeq.of(cycles).filter((e) => (ty === "labor") === e.isLabor && e.endTime >= start && e.endTime <= end);
223
+ const filteredCycles = LazySeq.of(cycles).filter((e) => (ty === "labor") === isLaborCycle(e) && e.endTime >= start && e.endTime <= end);
224
224
  const actualBins = binActiveCyclesByDayAndStat(filteredCycles);
225
225
  const filteredStatUse = LazySeq.of(statUse).filter((e) => (ty === "labor") === e.station.startsWith("L/U") && e.end >= start && e.start <= end);
226
226
  const downtimes = binDowntimeToDayAndStat(filteredStatUse);
@@ -306,7 +306,7 @@ export function buildOeeHeatmapTable(yTitle, points) {
306
306
  return table;
307
307
  }
308
308
  export function copyOeeHeatmapToClipboard(yTitle, points) {
309
- copy(buildOeeHeatmapTable(yTitle, points));
309
+ void copy(buildOeeHeatmapTable(yTitle, points));
310
310
  }
311
311
  export function buildOeeTable(series) {
312
312
  let table = "<table>\n<thead><tr>";
@@ -326,5 +326,5 @@ export function buildOeeTable(series) {
326
326
  return table;
327
327
  }
328
328
  export function copyOeeToClipboard(series) {
329
- copy(buildOeeTable(series));
329
+ void copy(buildOeeTable(series));
330
330
  }
@@ -99,16 +99,7 @@ export function buildScheduledJobs(zoom, matIds, schJobs, currentSt) {
99
99
  }
100
100
  }
101
101
  }
102
- const sorted = Array.from(result.values()).sort((j1, j2) => {
103
- // sort starting time high to low, then by part
104
- const timeDiff = j2.routeStartTime.getTime() - j1.routeStartTime.getTime();
105
- if (timeDiff == 0) {
106
- return j1.partName.localeCompare(j2.partName);
107
- }
108
- else {
109
- return timeDiff;
110
- }
111
- });
102
+ const sorted = LazySeq.of(result.values()).toSortedArray({ desc: (j) => j.routeStartTime.getTime() }, (j) => j.partName);
112
103
  let lastSchId = null;
113
104
  let curDark = true;
114
105
  for (const job of sorted) {
@@ -153,5 +144,5 @@ export function buildScheduledJobsTable(jobs, showMaterial) {
153
144
  return table;
154
145
  }
155
146
  export function copyScheduledJobsToClipboard(jobs, showMaterial) {
156
- copy(buildScheduledJobsTable(jobs, showMaterial));
147
+ void copy(buildScheduledJobsTable(jobs, showMaterial));
157
148
  }
@@ -207,11 +207,10 @@ export const machinesWithTools = atom((get) => {
207
207
  const toolsInMach = get(toolsInMachine);
208
208
  if (toolsInMach === null)
209
209
  return [];
210
- const names = new Set();
211
- for (const t of toolsInMach.tools) {
212
- names.add(stat_name_and_num(t.machineGroupName, t.machineNum));
213
- }
214
- return Array.from(names).sort((a, b) => a.localeCompare(b));
210
+ return LazySeq.of(toolsInMach.tools)
211
+ .toOrderedSet((n) => stat_name_and_num(n.machineGroupName, n.machineNum))
212
+ .toAscLazySeq()
213
+ .toRArray();
215
214
  });
216
215
  export const currentToolReport = atom((get) => {
217
216
  const toolsInMach = get(toolsInMachine);
@@ -282,7 +281,7 @@ export function useCopyToolReportToClipboard() {
282
281
  const tools = store.get(currentToolReport);
283
282
  if (!tools)
284
283
  return;
285
- copy(buildToolReportHTML(tools));
284
+ void copy(buildToolReportHTML(tools));
286
285
  }, [store]);
287
286
  }
288
287
  export function calcProgramReport(usage, cycleTimes, jobs, progsInCellCtrl, progsToShow) {
package/dist/index.html CHANGED
@@ -44,7 +44,7 @@
44
44
  }
45
45
  }
46
46
  </style>
47
- <script type="module" crossorigin src="/assets/index-gAFi3Oss.js"></script>
47
+ <script type="module" crossorigin src="/assets/index-bPAFn3jp.js"></script>
48
48
  <link rel="stylesheet" crossorigin href="/assets/index-CbqW4-gR.css">
49
49
  </head>
50
50
  <body>
@@ -452,6 +452,10 @@ export interface IHoldPattern {
452
452
  holdUnholdPatternRepeats: boolean;
453
453
  }
454
454
  export declare class ProcessInfo implements IProcessInfo {
455
+ basketLoadStations?: number[] | undefined;
456
+ expectedBasketLoadTime?: string | undefined;
457
+ basketUnloadStations?: number[] | undefined;
458
+ expectedBasketUnloadTime?: string | undefined;
455
459
  paths: ProcPathInfo[];
456
460
  constructor(data?: IProcessInfo);
457
461
  init(_data?: any): void;
@@ -459,6 +463,10 @@ export declare class ProcessInfo implements IProcessInfo {
459
463
  toJSON(data?: any): any;
460
464
  }
461
465
  export interface IProcessInfo {
466
+ basketLoadStations?: number[] | undefined;
467
+ expectedBasketLoadTime?: string | undefined;
468
+ basketUnloadStations?: number[] | undefined;
469
+ expectedBasketUnloadTime?: string | undefined;
462
470
  paths: ProcPathInfo[];
463
471
  }
464
472
  export declare class ProcPathInfo implements IProcPathInfo {
@@ -1030,8 +1038,10 @@ export declare enum WorkorderSerialCloseout {
1030
1038
  }
1031
1039
  export declare class BasketStatus implements IBasketStatus {
1032
1040
  basketId: number;
1033
- locationName: string;
1034
- locationPosition?: number | undefined;
1041
+ location: BasketLocationEnum;
1042
+ locationNum: number;
1043
+ locationTitle?: string | undefined;
1044
+ slot?: number | undefined;
1035
1045
  constructor(data?: IBasketStatus);
1036
1046
  init(_data?: any): void;
1037
1047
  static fromJS(data: any): BasketStatus;
@@ -1039,8 +1049,16 @@ export declare class BasketStatus implements IBasketStatus {
1039
1049
  }
1040
1050
  export interface IBasketStatus {
1041
1051
  basketId: number;
1042
- locationName: string;
1043
- locationPosition?: number | undefined;
1052
+ location: BasketLocationEnum;
1053
+ locationNum: number;
1054
+ locationTitle?: string | undefined;
1055
+ slot?: number | undefined;
1056
+ }
1057
+ export declare enum BasketLocationEnum {
1058
+ LoadUnload = "LoadUnload",
1059
+ LoadStationStaging = "LoadStationStaging",
1060
+ Storage = "Storage",
1061
+ InTransit = "InTransit"
1044
1062
  }
1045
1063
  export declare class EditMaterialInLogEvents implements IEditMaterialInLogEvents {
1046
1064
  oldMaterialID: number;