@seedtactics/insight-client 16.4.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 (298) hide show
  1. package/README.md +37 -0
  2. package/dist/cell-status/buffers.d.ts +36 -0
  3. package/dist/cell-status/buffers.js +127 -0
  4. package/dist/cell-status/current-status.d.ts +30 -0
  5. package/dist/cell-status/current-status.js +200 -0
  6. package/dist/cell-status/estimated-cycle-times.d.ts +41 -0
  7. package/dist/cell-status/estimated-cycle-times.js +257 -0
  8. package/dist/cell-status/inspections.d.ts +55 -0
  9. package/dist/cell-status/inspections.js +213 -0
  10. package/dist/cell-status/loading.d.ts +26 -0
  11. package/dist/cell-status/loading.js +112 -0
  12. package/dist/cell-status/material-details.d.ts +116 -0
  13. package/dist/cell-status/material-details.js +422 -0
  14. package/dist/cell-status/material-summary.d.ts +52 -0
  15. package/dist/cell-status/material-summary.js +312 -0
  16. package/dist/cell-status/names.d.ts +19 -0
  17. package/dist/cell-status/names.js +134 -0
  18. package/dist/cell-status/pallet-cycles.d.ts +24 -0
  19. package/dist/cell-status/pallet-cycles.js +78 -0
  20. package/dist/cell-status/rebookings.d.ts +30 -0
  21. package/dist/cell-status/rebookings.js +139 -0
  22. package/dist/cell-status/scheduled-jobs.d.ts +18 -0
  23. package/dist/cell-status/scheduled-jobs.js +94 -0
  24. package/dist/cell-status/sim-day-usage.d.ts +14 -0
  25. package/dist/cell-status/sim-day-usage.js +54 -0
  26. package/dist/cell-status/sim-production.d.ts +22 -0
  27. package/dist/cell-status/sim-production.js +91 -0
  28. package/dist/cell-status/sim-station-use.d.ts +25 -0
  29. package/dist/cell-status/sim-station-use.js +71 -0
  30. package/dist/cell-status/station-cycles.d.ts +34 -0
  31. package/dist/cell-status/station-cycles.js +145 -0
  32. package/dist/cell-status/tool-replacements.d.ts +44 -0
  33. package/dist/cell-status/tool-replacements.js +155 -0
  34. package/dist/cell-status/tool-usage.d.ts +25 -0
  35. package/dist/cell-status/tool-usage.js +95 -0
  36. package/dist/components/App.d.ts +15 -0
  37. package/dist/components/App.js +549 -0
  38. package/dist/components/AxisAndGrid.d.ts +51 -0
  39. package/dist/components/AxisAndGrid.js +47 -0
  40. package/dist/components/BarcodeScanning.d.ts +6 -0
  41. package/dist/components/BarcodeScanning.js +150 -0
  42. package/dist/components/ChartTooltip.d.ts +28 -0
  43. package/dist/components/ChartTooltip.js +95 -0
  44. package/dist/components/ChooseMode.d.ts +18 -0
  45. package/dist/components/ChooseMode.js +136 -0
  46. package/dist/components/ChooseOperator.d.ts +1 -0
  47. package/dist/components/ChooseOperator.js +93 -0
  48. package/dist/components/ErrorsAndLoading.d.ts +9 -0
  49. package/dist/components/ErrorsAndLoading.js +55 -0
  50. package/dist/components/LoadingIcon.d.ts +1 -0
  51. package/dist/components/LoadingIcon.js +48 -0
  52. package/dist/components/LogEntry.d.ts +16 -0
  53. package/dist/components/LogEntry.js +365 -0
  54. package/dist/components/ManualSerialEntry.d.ts +5 -0
  55. package/dist/components/ManualSerialEntry.js +91 -0
  56. package/dist/components/MonthSelect.d.ts +6 -0
  57. package/dist/components/MonthSelect.js +67 -0
  58. package/dist/components/Navigation.d.ts +23 -0
  59. package/dist/components/Navigation.js +120 -0
  60. package/dist/components/VerboseLogging.d.ts +1 -0
  61. package/dist/components/VerboseLogging.js +47 -0
  62. package/dist/components/analysis/AnalysisSelectToolbar.d.ts +1 -0
  63. package/dist/components/analysis/AnalysisSelectToolbar.js +55 -0
  64. package/dist/components/analysis/BufferChart.d.ts +1 -0
  65. package/dist/components/analysis/BufferChart.js +139 -0
  66. package/dist/components/analysis/CostPerPiece.d.ts +2 -0
  67. package/dist/components/analysis/CostPerPiece.js +175 -0
  68. package/dist/components/analysis/CycleChart.d.ts +42 -0
  69. package/dist/components/analysis/CycleChart.js +281 -0
  70. package/dist/components/analysis/DataTable.d.ts +83 -0
  71. package/dist/components/analysis/DataTable.js +215 -0
  72. package/dist/components/analysis/EfficiencyPage.d.ts +2 -0
  73. package/dist/components/analysis/EfficiencyPage.js +138 -0
  74. package/dist/components/analysis/HeatChart.d.ts +22 -0
  75. package/dist/components/analysis/HeatChart.js +161 -0
  76. package/dist/components/analysis/InspectionDataTable.d.ts +10 -0
  77. package/dist/components/analysis/InspectionDataTable.js +148 -0
  78. package/dist/components/analysis/InspectionSankey.d.ts +12 -0
  79. package/dist/components/analysis/InspectionSankey.js +140 -0
  80. package/dist/components/analysis/PalletCycleCards.d.ts +1 -0
  81. package/dist/components/analysis/PalletCycleCards.js +137 -0
  82. package/dist/components/analysis/PartCycleCards.d.ts +2 -0
  83. package/dist/components/analysis/PartCycleCards.js +331 -0
  84. package/dist/components/analysis/QualityPage.d.ts +1 -0
  85. package/dist/components/analysis/QualityPage.js +49 -0
  86. package/dist/components/analysis/ScheduleHistory.d.ts +3 -0
  87. package/dist/components/analysis/ScheduleHistory.js +108 -0
  88. package/dist/components/analysis/StationDataTable.d.ts +25 -0
  89. package/dist/components/analysis/StationDataTable.js +246 -0
  90. package/dist/components/analysis/ToolReplacements.d.ts +1 -0
  91. package/dist/components/analysis/ToolReplacements.js +370 -0
  92. package/dist/components/operations/AllMaterial.d.ts +5 -0
  93. package/dist/components/operations/AllMaterial.js +267 -0
  94. package/dist/components/operations/ChartRangeEdit.d.ts +4 -0
  95. package/dist/components/operations/ChartRangeEdit.js +148 -0
  96. package/dist/components/operations/CloseoutReport.d.ts +2 -0
  97. package/dist/components/operations/CloseoutReport.js +172 -0
  98. package/dist/components/operations/CompletedParts.d.ts +2 -0
  99. package/dist/components/operations/CompletedParts.js +286 -0
  100. package/dist/components/operations/CurrentWorkorders.d.ts +3 -0
  101. package/dist/components/operations/CurrentWorkorders.js +368 -0
  102. package/dist/components/operations/Dashboard.d.ts +2 -0
  103. package/dist/components/operations/Dashboard.js +90 -0
  104. package/dist/components/operations/OEEChart.d.ts +10 -0
  105. package/dist/components/operations/OEEChart.js +173 -0
  106. package/dist/components/operations/Outliers.d.ts +4 -0
  107. package/dist/components/operations/Outliers.js +69 -0
  108. package/dist/components/operations/ProgramHighlight.d.ts +1 -0
  109. package/dist/components/operations/ProgramHighlight.js +9 -0
  110. package/dist/components/operations/Programs.d.ts +5 -0
  111. package/dist/components/operations/Programs.js +363 -0
  112. package/dist/components/operations/Rebookings.d.ts +1 -0
  113. package/dist/components/operations/Rebookings.js +213 -0
  114. package/dist/components/operations/RecentCycleChart.d.ts +4 -0
  115. package/dist/components/operations/RecentCycleChart.js +240 -0
  116. package/dist/components/operations/RecentProduction.d.ts +2 -0
  117. package/dist/components/operations/RecentProduction.js +213 -0
  118. package/dist/components/operations/RecentSchedules.d.ts +12 -0
  119. package/dist/components/operations/RecentSchedules.js +180 -0
  120. package/dist/components/operations/RecentStationCycles.d.ts +4 -0
  121. package/dist/components/operations/RecentStationCycles.js +159 -0
  122. package/dist/components/operations/ShiftSettings.d.ts +6 -0
  123. package/dist/components/operations/ShiftSettings.js +134 -0
  124. package/dist/components/operations/SimDayUsage.d.ts +1 -0
  125. package/dist/components/operations/SimDayUsage.js +133 -0
  126. package/dist/components/operations/ToolReport.d.ts +3 -0
  127. package/dist/components/operations/ToolReport.js +233 -0
  128. package/dist/components/operations/WorkorderGantt.d.ts +1 -0
  129. package/dist/components/operations/WorkorderGantt.js +124 -0
  130. package/dist/components/quality/QualityMaterial.d.ts +2 -0
  131. package/dist/components/quality/QualityMaterial.js +169 -0
  132. package/dist/components/quality/QualityPaths.d.ts +1 -0
  133. package/dist/components/quality/QualityPaths.js +53 -0
  134. package/dist/components/quality/RecentFailedInspections.d.ts +1 -0
  135. package/dist/components/quality/RecentFailedInspections.js +123 -0
  136. package/dist/components/routes.d.ts +170 -0
  137. package/dist/components/routes.js +301 -0
  138. package/dist/components/station-monitor/BulkRawMaterial.d.ts +11 -0
  139. package/dist/components/station-monitor/BulkRawMaterial.js +251 -0
  140. package/dist/components/station-monitor/Closeout.d.ts +5 -0
  141. package/dist/components/station-monitor/Closeout.js +162 -0
  142. package/dist/components/station-monitor/CustomStationMonitorDialog.d.ts +1 -0
  143. package/dist/components/station-monitor/CustomStationMonitorDialog.js +55 -0
  144. package/dist/components/station-monitor/Inspection.d.ts +8 -0
  145. package/dist/components/station-monitor/Inspection.js +164 -0
  146. package/dist/components/station-monitor/InvalidateCycle.d.ts +33 -0
  147. package/dist/components/station-monitor/InvalidateCycle.js +262 -0
  148. package/dist/components/station-monitor/JobDetails.d.ts +7 -0
  149. package/dist/components/station-monitor/JobDetails.js +108 -0
  150. package/dist/components/station-monitor/LoadStation.d.ts +10 -0
  151. package/dist/components/station-monitor/LoadStation.js +450 -0
  152. package/dist/components/station-monitor/Material.d.ts +77 -0
  153. package/dist/components/station-monitor/Material.js +489 -0
  154. package/dist/components/station-monitor/MoveMaterialArrows.d.ts +11 -0
  155. package/dist/components/station-monitor/MoveMaterialArrows.js +118 -0
  156. package/dist/components/station-monitor/PrintedLabel.d.ts +29 -0
  157. package/dist/components/station-monitor/PrintedLabel.js +166 -0
  158. package/dist/components/station-monitor/QuarantineButton.d.ts +4 -0
  159. package/dist/components/station-monitor/QuarantineButton.js +184 -0
  160. package/dist/components/station-monitor/Queues.d.ts +23 -0
  161. package/dist/components/station-monitor/Queues.js +312 -0
  162. package/dist/components/station-monitor/QueuesAddMaterial.d.ts +30 -0
  163. package/dist/components/station-monitor/QueuesAddMaterial.js +248 -0
  164. package/dist/components/station-monitor/SelectInspType.d.ts +2 -0
  165. package/dist/components/station-monitor/SelectInspType.js +99 -0
  166. package/dist/components/station-monitor/SelectWorkorder.d.ts +4 -0
  167. package/dist/components/station-monitor/SelectWorkorder.js +100 -0
  168. package/dist/components/station-monitor/StationToolbar.d.ts +3 -0
  169. package/dist/components/station-monitor/StationToolbar.js +168 -0
  170. package/dist/components/station-monitor/SystemOverview.d.ts +46 -0
  171. package/dist/components/station-monitor/SystemOverview.js +439 -0
  172. package/dist/components/station-monitor/Whiteboard.d.ts +10 -0
  173. package/dist/components/station-monitor/Whiteboard.js +67 -0
  174. package/dist/data/all-material-bins.d.ts +45 -0
  175. package/dist/data/all-material-bins.js +224 -0
  176. package/dist/data/chart-times.d.ts +20 -0
  177. package/dist/data/chart-times.js +99 -0
  178. package/dist/data/cost-per-piece.d.ts +32 -0
  179. package/dist/data/cost-per-piece.js +183 -0
  180. package/dist/data/current-cycles.d.ts +13 -0
  181. package/dist/data/current-cycles.js +144 -0
  182. package/dist/data/inspection-sankey.d.ts +15 -0
  183. package/dist/data/inspection-sankey.js +147 -0
  184. package/dist/data/move-arrows.d.ts +48 -0
  185. package/dist/data/move-arrows.js +217 -0
  186. package/dist/data/operators.d.ts +2 -0
  187. package/dist/data/operators.js +44 -0
  188. package/dist/data/part-summary.d.ts +17 -0
  189. package/dist/data/part-summary.js +107 -0
  190. package/dist/data/path-lookup.d.ts +13 -0
  191. package/dist/data/path-lookup.js +107 -0
  192. package/dist/data/queue-material.d.ts +46 -0
  193. package/dist/data/queue-material.js +256 -0
  194. package/dist/data/results.bufferchart.d.ts +10 -0
  195. package/dist/data/results.bufferchart.js +90 -0
  196. package/dist/data/results.completed-parts.d.ts +26 -0
  197. package/dist/data/results.completed-parts.js +181 -0
  198. package/dist/data/results.cycles.d.ts +86 -0
  199. package/dist/data/results.cycles.js +454 -0
  200. package/dist/data/results.inspection.d.ts +36 -0
  201. package/dist/data/results.inspection.js +188 -0
  202. package/dist/data/results.oee.d.ts +40 -0
  203. package/dist/data/results.oee.js +330 -0
  204. package/dist/data/results.schedules.d.ts +23 -0
  205. package/dist/data/results.schedules.js +157 -0
  206. package/dist/data/tools-programs.d.ts +78 -0
  207. package/dist/data/tools-programs.js +376 -0
  208. package/dist/index.d.ts +1 -0
  209. package/dist/index.js +60 -0
  210. package/dist/network/api.d.ts +1390 -0
  211. package/dist/network/api.js +4971 -0
  212. package/dist/network/backend-mock.d.ts +11 -0
  213. package/dist/network/backend-mock.js +512 -0
  214. package/dist/network/backend.d.ts +57 -0
  215. package/dist/network/backend.js +77 -0
  216. package/dist/network/load-specific-month.d.ts +13 -0
  217. package/dist/network/load-specific-month.js +77 -0
  218. package/dist/network/server-settings.d.ts +12 -0
  219. package/dist/network/server-settings.js +92 -0
  220. package/dist/network/websocket.d.ts +4 -0
  221. package/dist/network/websocket.js +165 -0
  222. package/dist/renderer.d.ts +8 -0
  223. package/dist/renderer.js +55 -0
  224. package/dist/seedtactics-logo.d.ts +2 -0
  225. package/dist/seedtactics-logo.js +4 -0
  226. package/dist/util/chart-colors.d.ts +1 -0
  227. package/dist/util/chart-colors.js +116 -0
  228. package/dist/util/chart-helpers.d.ts +3 -0
  229. package/dist/util/chart-helpers.js +51 -0
  230. package/dist/util/parseISODuration.d.ts +4 -0
  231. package/dist/util/parseISODuration.js +40 -0
  232. package/docs/client-efficiency.md +355 -0
  233. package/docs/client-engineering.md +54 -0
  234. package/docs/client-launch.md +55 -0
  235. package/docs/client-operations.md +88 -0
  236. package/docs/client-quality.md +74 -0
  237. package/docs/client-sales.md +61 -0
  238. package/docs/client-scanners.md +41 -0
  239. package/docs/client-station-monitor.md +149 -0
  240. package/docs/client-tools-programs.md +74 -0
  241. package/docs/improve-fms.md +141 -0
  242. package/docs/makino.md +40 -0
  243. package/docs/material-quarantine.md +82 -0
  244. package/docs/material-tracking.md +236 -0
  245. package/docs/mazak.md +115 -0
  246. package/docs/niigata.md +228 -0
  247. package/docs/operator-procedures.md +106 -0
  248. package/docs/part-instructions.md +63 -0
  249. package/docs/screenshots/insight-all-material.png +0 -0
  250. package/docs/screenshots/insight-analysis-pallets.png +0 -0
  251. package/docs/screenshots/insight-analysis-part-completed.png +0 -0
  252. package/docs/screenshots/insight-analysis-sankey.png +0 -0
  253. package/docs/screenshots/insight-analysis-station-oee.png +0 -0
  254. package/docs/screenshots/insight-buffer-occupancy.png +0 -0
  255. package/docs/screenshots/insight-choose-analysis-month.png +0 -0
  256. package/docs/screenshots/insight-closeout.png +0 -0
  257. package/docs/screenshots/insight-cost-percentages.png +0 -0
  258. package/docs/screenshots/insight-dashboard.png +0 -0
  259. package/docs/screenshots/insight-event-custom-view.jpg +0 -0
  260. package/docs/screenshots/insight-event-viewer.jpg +0 -0
  261. package/docs/screenshots/insight-inspection.png +0 -0
  262. package/docs/screenshots/insight-load-station-details.png +0 -0
  263. package/docs/screenshots/insight-load-station.png +0 -0
  264. package/docs/screenshots/insight-loadcycle-graph.png +0 -0
  265. package/docs/screenshots/insight-loadstation-small.jpg +0 -0
  266. package/docs/screenshots/insight-machinecycle-graph.png +0 -0
  267. package/docs/screenshots/insight-machinecycle-table.png +0 -0
  268. package/docs/screenshots/insight-machinecycles.png +0 -0
  269. package/docs/screenshots/insight-machinehours.png +0 -0
  270. package/docs/screenshots/insight-machineoutliers.png +0 -0
  271. package/docs/screenshots/insight-monthly-schedules.png +0 -0
  272. package/docs/screenshots/insight-operations-material.png +0 -0
  273. package/docs/screenshots/insight-operations-overview.png +0 -0
  274. package/docs/screenshots/insight-operations-reports.png +0 -0
  275. package/docs/screenshots/insight-part-cost.png +0 -0
  276. package/docs/screenshots/insight-program-report.png +0 -0
  277. package/docs/screenshots/insight-quality-material-details.png +0 -0
  278. package/docs/screenshots/insight-quality-material.png +0 -0
  279. package/docs/screenshots/insight-quality-quarantine.png +0 -0
  280. package/docs/screenshots/insight-quality-sankey.png +0 -0
  281. package/docs/screenshots/insight-quality-similar-paths.png +0 -0
  282. package/docs/screenshots/insight-queue-details.png +0 -0
  283. package/docs/screenshots/insight-queues-jobs-table.png +0 -0
  284. package/docs/screenshots/insight-queues.png +0 -0
  285. package/docs/screenshots/insight-sim-day-usage.png +0 -0
  286. package/docs/screenshots/insight-station-system-overview-buttons.png +0 -0
  287. package/docs/screenshots/insight-station-system-overview.png +0 -0
  288. package/docs/screenshots/insight-system-overview.png +0 -0
  289. package/docs/screenshots/insight-tool-replacements.png +0 -0
  290. package/docs/screenshots/insight-tool-report.png +0 -0
  291. package/docs/screenshots/insight-toolbar-btns.png +0 -0
  292. package/docs/screenshots/insight-workorder-gantt.png +0 -0
  293. package/docs/screenshots/insight-workorders.png +0 -0
  294. package/docs/security.md +131 -0
  295. package/docs/server-config.md +56 -0
  296. package/docs/server-errors.md +44 -0
  297. package/package.json +90 -0
  298. package/src/index.ts +65 -0
@@ -0,0 +1,173 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /* Copyright (c) 2025, 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
+
12
+ * Redistributions in binary form must reproduce the above
13
+ copyright notice, this list of conditions and the following
14
+ disclaimer in the documentation and/or other materials provided
15
+ with the distribution.
16
+
17
+ * Neither the name of John Lenz, Black Maple Software, SeedTactics,
18
+ nor the names of other contributors may be used to endorse or
19
+ promote products derived from this software without specific
20
+ prior written permission.
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
+ */
34
+ import { memo, useMemo } from "react";
35
+ import { Box, Grid, IconButton, Table, Tooltip as MuiTooltip, Select, MenuItem, Typography, FormControl, } from "@mui/material";
36
+ import { DataTableHead, DataTableBody, useColSort } from "../analysis/DataTable.js";
37
+ import { LazySeq } from "@seedtactics/immutable-collections";
38
+ import { buildOeeSeries, copyOeeToClipboard, } from "../../data/results.oee.js";
39
+ import { seriesColor } from "../../util/chart-colors.js";
40
+ import { addDays, startOfToday } from "date-fns";
41
+ import { last30StationCycles } from "../../cell-status/station-cycles.js";
42
+ import { last30SimStationUse } from "../../cell-status/sim-station-use.js";
43
+ import { ImportExport } from "@mui/icons-material";
44
+ import { useSetTitle } from "../routes.js";
45
+ import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
46
+ import { scaleBand, scaleLinear } from "d3-scale";
47
+ import { AxisBottom, AxisLeft, GridRows } from "../AxisAndGrid.js";
48
+ import { ChartWithTooltip } from "../ChartTooltip.js";
49
+ import { localPoint } from "../../util/chart-helpers.js";
50
+ const actualOeeColor = seriesColor(0, 2);
51
+ const plannedOeeColor = seriesColor(1, 2);
52
+ const marginLeft = 50;
53
+ const marginBottom = 30;
54
+ const marginTop = 10;
55
+ const marginRight = 10;
56
+ function BarChart({ width, height, points, setTooltip, }) {
57
+ const yMax = height - marginTop - marginBottom;
58
+ const hourScale = useMemo(() => scaleLinear().domain([0, 24]).range([yMax, 0]), [yMax]);
59
+ const dateScale = useMemo(() => scaleBand()
60
+ .domain(LazySeq.of(points)
61
+ .map((p) => p.x)
62
+ .distinct())
63
+ .range([0, width - marginLeft - marginRight])
64
+ .padding(0.1), [points, width]);
65
+ const actualPlanningScale = useMemo(() => scaleBand().domain(["Actual", "Planned"]).range([0, dateScale.bandwidth()]).padding(0.05), [dateScale]);
66
+ return (_jsx("svg", { width: width, height: height, children: _jsxs("g", { transform: `translate(${marginLeft},${marginTop})`, children: [_jsx(AxisBottom, { scale: dateScale, top: yMax }), _jsx(AxisLeft, { scale: hourScale, left: 0, label: "Hours" }), _jsx(GridRows, { scale: hourScale, width: width - marginLeft - marginRight }), points.map((p, i) => (_jsxs("g", { transform: `translate(${dateScale(p.x)},0)`, children: [_jsx("rect", { x: actualPlanningScale("Actual"), y: hourScale(p.y), width: actualPlanningScale.bandwidth(), height: yMax - hourScale(p.y), fill: actualOeeColor, onMouseEnter: (e) => {
67
+ const pt = localPoint(e);
68
+ setTooltip({
69
+ left: pt?.x ?? 0,
70
+ top: pt?.y ?? 0,
71
+ datum: p,
72
+ });
73
+ }, onMouseLeave: () => setTooltip(null) }), _jsx("rect", { x: actualPlanningScale("Planned"), y: hourScale(p.plannedHours), width: actualPlanningScale.bandwidth(), height: yMax - hourScale(p.plannedHours), fill: plannedOeeColor, onMouseEnter: (e) => {
74
+ const pt = localPoint(e);
75
+ setTooltip({
76
+ left: pt?.x ?? 0,
77
+ top: pt?.y ?? 0,
78
+ datum: p,
79
+ });
80
+ }, onMouseLeave: () => setTooltip(null) })] }, i)))] }) }));
81
+ }
82
+ function OEELegend({ station }) {
83
+ return (_jsxs("div", { style: { marginTop: "1em", display: "flex", flexWrap: "wrap", justifyContent: "space-evenly" }, children: [_jsxs("div", { style: { display: "flex", alignItems: "center" }, children: [_jsx("div", { style: { width: "14px", height: "14px", backgroundColor: actualOeeColor } }), _jsxs("div", { style: { marginLeft: "1em" }, children: [station, " Actual"] })] }), _jsxs("div", { style: { display: "flex", alignItems: "center" }, children: [_jsx("div", { style: { width: "14px", height: "14px", backgroundColor: plannedOeeColor } }), _jsxs("div", { style: { marginLeft: "1em" }, children: [station, " Planned"] })] })] }));
84
+ }
85
+ function OEETooltip({ tooltip }) {
86
+ return (_jsxs("div", { children: [_jsx("div", { children: tooltip.datum.x }), _jsxs("div", { children: ["Actual Hours: ", tooltip.datum.y?.toFixed(1)] }), _jsxs("div", { children: ["Planned Hours: ", tooltip.datum?.plannedHours?.toFixed(1)] })] }));
87
+ }
88
+ function OEESeries({ series }) {
89
+ const tooltipAtom = useMemo(() => atom(null), []);
90
+ const setTooltip = useSetAtom(tooltipAtom);
91
+ return (_jsxs(Grid, { size: { xs: 12, md: 6 }, onMouseLeave: () => setTooltip(null), children: [_jsx(ChartWithTooltip, { sx: { height: "calc(100vh / 2 - 200px)" }, chart: ({ width, height }) => (_jsx(BarChart, { width: width, height: height, points: series.points, setTooltip: setTooltip })), tooltipAtom: tooltipAtom, TooltipContent: OEETooltip }), _jsx(OEELegend, { station: series.station })] }));
92
+ }
93
+ export function OEEChart({ points }) {
94
+ return (_jsx(Grid, { container: true, children: points.map((series, idx) => (_jsx(OEESeries, { series: series }, idx))) }));
95
+ }
96
+ var ColumnId;
97
+ (function (ColumnId) {
98
+ ColumnId[ColumnId["Date"] = 0] = "Date";
99
+ ColumnId[ColumnId["Station"] = 1] = "Station";
100
+ ColumnId[ColumnId["ActualHours"] = 2] = "ActualHours";
101
+ ColumnId[ColumnId["ActualOEE"] = 3] = "ActualOEE";
102
+ ColumnId[ColumnId["PlannedHours"] = 4] = "PlannedHours";
103
+ ColumnId[ColumnId["PlannedOEE"] = 5] = "PlannedOEE";
104
+ })(ColumnId || (ColumnId = {}));
105
+ const columns = [
106
+ {
107
+ id: ColumnId.Date,
108
+ numeric: false,
109
+ label: "Date",
110
+ getDisplay: (c) => c.x,
111
+ getForSort: (c) => c.day.getTime(),
112
+ },
113
+ {
114
+ id: ColumnId.Station,
115
+ numeric: false,
116
+ label: "Station",
117
+ getDisplay: (c) => c.station,
118
+ },
119
+ {
120
+ id: ColumnId.ActualHours,
121
+ numeric: true,
122
+ label: "Actual Hours",
123
+ getDisplay: (c) => c.y.toFixed(1),
124
+ getForSort: (c) => c.y,
125
+ },
126
+ {
127
+ id: ColumnId.ActualOEE,
128
+ numeric: true,
129
+ label: "Actual OEE",
130
+ getDisplay: (c) => (c.actualOee * 100).toFixed(0) + "%",
131
+ getForSort: (c) => c.actualOee,
132
+ },
133
+ {
134
+ id: ColumnId.PlannedHours,
135
+ numeric: true,
136
+ label: "Planned Hours",
137
+ getDisplay: (c) => c.plannedHours.toFixed(1),
138
+ getForSort: (c) => c.plannedHours,
139
+ },
140
+ {
141
+ id: ColumnId.PlannedOEE,
142
+ numeric: true,
143
+ label: "Planned OEE",
144
+ getDisplay: (c) => (c.plannedOee * 100).toFixed(0) + "%",
145
+ getForSort: (c) => c.plannedOee,
146
+ },
147
+ ];
148
+ function dataForTable(series, sortOn) {
149
+ return LazySeq.of(series)
150
+ .flatMap((e) => e.points)
151
+ .toSortedArray(sortOn);
152
+ }
153
+ export const OEETable = memo(function OEETableF({ points }) {
154
+ const sort = useColSort(ColumnId.Date, columns);
155
+ return (_jsxs(Table, { children: [_jsx(DataTableHead, { columns: columns, sort: sort, showDetailsCol: false }), _jsx(DataTableBody, { columns: columns, pageData: dataForTable(points, sort.sortOn) })] }));
156
+ });
157
+ const lulShowChart = atom(true);
158
+ const mcShowChart = atom(true);
159
+ export function StationOEEPage({ ty }) {
160
+ useSetTitle(ty === "labor" ? "L/U OEE" : "Machine OEE");
161
+ const [showChart, setShowChart] = useAtom(ty === "labor" ? lulShowChart : mcShowChart);
162
+ const start = addDays(startOfToday(), -6);
163
+ const end = addDays(startOfToday(), 1);
164
+ const cycles = useAtomValue(last30StationCycles);
165
+ const statUse = useAtomValue(last30SimStationUse);
166
+ const points = useMemo(() => buildOeeSeries(start, end, ty, cycles.valuesToLazySeq(), statUse), [start, end, ty, cycles, statUse]);
167
+ return (_jsxs(Box, { paddingLeft: "24px", paddingRight: "24px", paddingTop: "10px", children: [_jsxs(Box, { component: "nav", sx: {
168
+ display: "flex",
169
+ minHeight: "2.5em",
170
+ alignItems: "center",
171
+ maxWidth: "calc(100vw - 24px - 24px)",
172
+ }, children: [_jsxs(Typography, { variant: "subtitle1", children: [ty === "labor" ? "Load/Unload" : "Machine", " OEE: comparing flexplan hours between actual and simulated production"] }), _jsx(Box, { flexGrow: 1 }), _jsx(FormControl, { size: "small", children: _jsxs(Select, { autoWidth: true, value: showChart ? "chart" : "table", onChange: (e) => setShowChart(e.target.value === "chart"), children: [_jsx(MenuItem, { value: "chart", children: "Chart" }, "chart"), _jsx(MenuItem, { value: "table", children: "Table" }, "table")] }) }), _jsx(MuiTooltip, { title: "Copy to Clipboard", children: _jsx(IconButton, { style: { height: "25px", paddingTop: 0, paddingBottom: 0 }, onClick: () => copyOeeToClipboard(points), size: "large", children: _jsx(ImportExport, {}) }) })] }), _jsx("main", { children: showChart ? _jsx(OEEChart, { points: points }) : _jsx(OEETable, { points: points }) })] }));
173
+ }
@@ -0,0 +1,4 @@
1
+ export type OutlierType = "labor" | "machine";
2
+ export declare function OutlierCycles({ outlierTy }: {
3
+ outlierTy: OutlierType;
4
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,69 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ /* Copyright (c) 2023, 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
+
12
+ * Redistributions in binary form must reproduce the above
13
+ copyright notice, this list of conditions and the following
14
+ disclaimer in the documentation and/or other materials provided
15
+ with the distribution.
16
+
17
+ * Neither the name of John Lenz, Black Maple Software, SeedTactics,
18
+ nor the names of other contributors may be used to endorse or
19
+ promote products derived from this software without specific
20
+ prior written permission.
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
+ */
34
+ import { useMemo } from "react";
35
+ import { Box, Typography } from "@mui/material";
36
+ import { addDays, startOfToday } from "date-fns";
37
+ import { Tooltip } from "@mui/material";
38
+ import { IconButton } from "@mui/material";
39
+ import { ImportExport } from "@mui/icons-material";
40
+ import StationDataTable from "../analysis/StationDataTable.js";
41
+ import { copyCyclesToClipboard } from "../../data/results.cycles.js";
42
+ import { last30MaterialSummary } from "../../cell-status/material-summary.js";
43
+ import { last30StationCycles } from "../../cell-status/station-cycles.js";
44
+ import { useSetTitle } from "../routes.js";
45
+ import { useAtomValue } from "jotai";
46
+ export function OutlierCycles({ outlierTy }) {
47
+ useSetTitle(outlierTy === "machine" ? "Machine Outliers" : "L/U Outliers");
48
+ const matSummary = useAtomValue(last30MaterialSummary);
49
+ const today = startOfToday();
50
+ const allCycles = useAtomValue(last30StationCycles);
51
+ const points = useMemo(() => {
52
+ const today = startOfToday();
53
+ const start = addDays(today, -4);
54
+ const end = addDays(today, 1);
55
+ return {
56
+ seriesLabel: "Part",
57
+ data: allCycles
58
+ .valuesToLazySeq()
59
+ .filter((c) => c.isOutlier && c.endTime >= start && c.endTime < end && c.isLabor === (outlierTy === "labor"))
60
+ .toRLookup((e) => e.part + "-" + e.material[0].proc.toString()),
61
+ };
62
+ }, [outlierTy, allCycles]);
63
+ return (_jsxs(Box, { paddingLeft: "24px", paddingRight: "24px", paddingTop: "10px", children: [_jsxs(Box, { component: "nav", sx: {
64
+ display: "flex",
65
+ minHeight: "2.5em",
66
+ alignItems: "center",
67
+ maxWidth: "calc(100vw - 24px - 24px)",
68
+ }, children: [_jsxs(Typography, { variant: "subtitle1", children: [outlierTy === "labor" ? "Load/Unload" : "Machine", " cycles from the past 5 days statistically outside expected range"] }), _jsx(Box, { flexGrow: 1 }), _jsx(Tooltip, { title: "Copy to Clipboard", children: _jsx(IconButton, { style: { height: "25px", paddingTop: 0, paddingBottom: 0 }, onClick: () => copyCyclesToClipboard(points, matSummary.matsById, undefined), size: "large", children: _jsx(ImportExport, {}) }) })] }), _jsx("main", { children: _jsx(StationDataTable, { points: points.data, matsById: matSummary.matsById, current_date_zoom: { start: addDays(today, -4), end: addDays(today, 1) }, set_date_zoom_range: undefined, period: { type: "Last30" }, showWorkorderAndInspect: false, defaultSortDesc: true }) })] }));
69
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ /* eslint-disable @typescript-eslint/no-unsafe-call */
4
+ import hljs from "highlight.js/lib/core";
5
+ import gcode from "highlight.js/lib/languages/gcode";
6
+ hljs.registerLanguage("gcode", gcode);
7
+ self.onmessage = function (event) {
8
+ self.postMessage(hljs.highlight(event.data, { language: "gcode" }).value);
9
+ };
@@ -0,0 +1,5 @@
1
+ import { ReactNode } from "react";
2
+ export declare function ProgramSummaryTable(): ReactNode;
3
+ export declare function ProgramContentDialog(): ReactNode;
4
+ export declare function ProgramHistoryDialog(): ReactNode;
5
+ export declare function ProgramReportPage(): ReactNode;
@@ -0,0 +1,363 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /* Copyright (c) 2020, 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
+
12
+ * Redistributions in binary form must reproduce the above
13
+ copyright notice, this list of conditions and the following
14
+ disclaimer in the documentation and/or other materials provided
15
+ with the distribution.
16
+
17
+ * Neither the name of John Lenz, Black Maple Software, SeedTactics,
18
+ nor the names of other contributors may be used to endorse or
19
+ promote products derived from this software without specific
20
+ prior written permission.
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
+ */
34
+ import { useState, useMemo, useEffect } from "react";
35
+ import { Box, Fab, FormControl, styled } from "@mui/material";
36
+ import { CircularProgress } from "@mui/material";
37
+ import { Card } from "@mui/material";
38
+ import { CardContent } from "@mui/material";
39
+ import TimeAgo from "react-timeago";
40
+ import { Table } from "@mui/material";
41
+ import { TableHead } from "@mui/material";
42
+ import { TableCell } from "@mui/material";
43
+ import { TableRow } from "@mui/material";
44
+ import { TableSortLabel } from "@mui/material";
45
+ import { Typography } from "@mui/material";
46
+ import { Tooltip } from "@mui/material";
47
+ import { KeyboardArrowDown as KeyboardArrowDownIcon, KeyboardArrowUp as KeyboardArrowUpIcon, FirstPage as FirstPageIcon, KeyboardArrowLeft, KeyboardArrowRight, History as HistoryIcon, Refresh as RefreshIcon, Code as CodeIcon, } from "@mui/icons-material";
48
+ import { programReportRefreshTime, currentProgramReport, programToShowContent, programContent, programToShowHistory, programFilter, } from "../../data/tools-programs.js";
49
+ import { TableBody } from "@mui/material";
50
+ import { IconButton } from "@mui/material";
51
+ import { Collapse } from "@mui/material";
52
+ import { LazySeq } from "@seedtactics/immutable-collections";
53
+ import { PartIdenticon } from "../station-monitor/Material.js";
54
+ import { Dialog } from "@mui/material";
55
+ import { DialogContent } from "@mui/material";
56
+ import { DialogTitle } from "@mui/material";
57
+ import { Button } from "@mui/material";
58
+ import { DialogActions } from "@mui/material";
59
+ import { useIsDemo, useSetTitle } from "../routes.js";
60
+ import { DisplayLoadingAndError } from "../ErrorsAndLoading.js";
61
+ import { MachineBackend } from "../../network/backend.js";
62
+ import { Select } from "@mui/material";
63
+ import { MenuItem } from "@mui/material";
64
+ import { useAtom, useAtomValue, useSetAtom } from "jotai";
65
+ const ProgramTableRow = styled(TableRow)(() => ({
66
+ "& > *": {
67
+ borderBottom: "unset",
68
+ },
69
+ }));
70
+ function programFilename(program) {
71
+ if (program.length === 0)
72
+ return "";
73
+ const idx = program.lastIndexOf("\\");
74
+ if (idx >= 0 && idx < program.length - 2) {
75
+ return program.substr(idx + 1);
76
+ }
77
+ else {
78
+ return program;
79
+ }
80
+ }
81
+ const numFormat = new Intl.NumberFormat("en-US", {
82
+ maximumFractionDigits: 2,
83
+ });
84
+ function ProgramRow(props) {
85
+ const [open, setOpen] = useState(false);
86
+ const setProgramToShowContent = useSetAtom(programToShowContent);
87
+ const setProgramToShowHistory = useSetAtom(programToShowHistory);
88
+ const numCols = 8 + (props.showCellCtrlCol ? 1 : 0) + (props.showRevCol ? 1 : 0);
89
+ const toolsHaveTime = props.program.toolUse !== null &&
90
+ props.program.toolUse.tools.length > 0 &&
91
+ LazySeq.of(props.program.toolUse.tools).some((t) => t.cycleUsageMinutes > 0);
92
+ const toolsHaveCnt = props.program.toolUse !== null &&
93
+ props.program.toolUse.tools.length > 0 &&
94
+ LazySeq.of(props.program.toolUse.tools).some((t) => t.cycleUsageCnt > 0);
95
+ return (_jsxs(_Fragment, { children: [_jsxs(ProgramTableRow, { children: [_jsx(TableCell, { children: props.program.toolUse === null || props.program.toolUse.tools.length === 0 ? undefined : (_jsx(IconButton, { size: "small", onClick: () => setOpen(!open), children: open ? _jsx(KeyboardArrowUpIcon, {}) : _jsx(KeyboardArrowDownIcon, {}) })) }), _jsx(TableCell, { children: programFilename(props.program.programName) }), props.showCellCtrlCol ? _jsx(TableCell, { children: props.program.cellControllerProgramName }) : undefined, _jsx(TableCell, { children: props.program.partName !== null ? (_jsxs(Box, { sx: {
96
+ display: "flex",
97
+ alignItems: "center",
98
+ }, children: [_jsx(PartIdenticon, { part: props.program.partName, size: 20 }), _jsx("span", { children: props.program.partName })] })) : undefined }), _jsx(TableCell, { children: props.program.comment ?? "" }), props.showRevCol ? (_jsx(TableCell, { children: props.program.revision === null ? "" : props.program.revision.toFixed() })) : undefined, _jsx(TableCell, { align: "right", children: props.program.statisticalCycleTime === null
99
+ ? ""
100
+ : props.program.statisticalCycleTime.medianMinutesForSingleMat.toFixed(2) }), _jsx(TableCell, { align: "right", children: props.program.statisticalCycleTime === null
101
+ ? ""
102
+ : props.program.statisticalCycleTime.MAD_aboveMinutes.toFixed(2) }), _jsx(TableCell, { align: "right", children: props.program.statisticalCycleTime === null
103
+ ? ""
104
+ : props.program.statisticalCycleTime.MAD_belowMinutes.toFixed(2) }), _jsx(TableCell, { align: "right", children: props.program.plannedMins === null ? "" : numFormat.format(props.program.plannedMins) }), _jsxs(TableCell, { children: [_jsx(Tooltip, { title: "Load Program Content", children: _jsx(IconButton, { size: "small", onClick: () => setProgramToShowContent(props.program), children: _jsx(CodeIcon, {}) }) }), props.program.revision !== null ? (_jsx(Tooltip, { title: "Revision History", children: _jsx(IconButton, { size: "small", onClick: () => setProgramToShowHistory(props.program), children: _jsx(HistoryIcon, {}) }) })) : undefined] })] }), _jsx(TableRow, { children: _jsx(TableCell, { sx: { pb: "0", pt: "0" }, colSpan: numCols, children: _jsx(Collapse, { in: open, timeout: "auto", unmountOnExit: true, children: _jsx(Box, { sx: { mr: "1em", ml: "3em" }, children: props.program.toolUse === null || props.program.toolUse.tools.length === 0 ? undefined : (_jsxs(Table, { size: "small", sx: {
105
+ width: "auto",
106
+ ml: "10em",
107
+ mr: "1em",
108
+ }, children: [_jsx(TableHead, { children: _jsxs(TableRow, { children: [_jsx(TableCell, { children: "Tool" }), toolsHaveTime ? _jsx(TableCell, { align: "right", children: "Estimated Usage (min)" }) : undefined, toolsHaveCnt ? (_jsx(TableCell, { align: "right", children: "Estimated Usage (count)" })) : undefined] }) }), _jsx(TableBody, { children: LazySeq.of(props.program.toolUse.tools).map((t, idx) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: t.toolName }), toolsHaveTime ? (_jsx(TableCell, { align: "right", children: t.cycleUsageMinutes === 0 ? "" : t.cycleUsageMinutes.toFixed(1) })) : undefined, toolsHaveCnt ? (_jsx(TableCell, { align: "right", children: t.cycleUsageCnt === 0 ? "" : t.cycleUsageCnt.toFixed(1) })) : undefined] }, idx))) })] })) }) }) }) })] }));
109
+ }
110
+ export function ProgramSummaryTable() {
111
+ const report = useAtomValue(currentProgramReport);
112
+ const [sortCol, setSortCol] = useState("ProgramName");
113
+ const [sortDir, setSortDir] = useState("asc");
114
+ if (report === null) {
115
+ return _jsx("div", {});
116
+ }
117
+ const rows = LazySeq.of(report.programs).sortWith((a, b) => {
118
+ let c = 0;
119
+ switch (sortCol) {
120
+ case "ProgramName":
121
+ c = programFilename(a.programName).localeCompare(programFilename(b.programName));
122
+ break;
123
+ case "CellProgName":
124
+ c = a.cellControllerProgramName.localeCompare(b.cellControllerProgramName);
125
+ break;
126
+ case "Comment":
127
+ if (a.comment === null && b.comment === null) {
128
+ c = 0;
129
+ }
130
+ else if (a.comment === null) {
131
+ c = 1;
132
+ }
133
+ else if (b.comment === null) {
134
+ c = -1;
135
+ }
136
+ else {
137
+ c = a.comment.localeCompare(b.comment);
138
+ }
139
+ break;
140
+ case "Revision":
141
+ if (a.revision === null && b.revision === null) {
142
+ c = 0;
143
+ }
144
+ else if (a.revision === null) {
145
+ c = 1;
146
+ }
147
+ else if (b.revision === null) {
148
+ c = -1;
149
+ }
150
+ else {
151
+ c = a.revision - b.revision;
152
+ }
153
+ break;
154
+ case "PartName":
155
+ if (a.partName === null && b.partName === null) {
156
+ c = 0;
157
+ }
158
+ else if (a.partName === null) {
159
+ c = 1;
160
+ }
161
+ else if (b.partName === null) {
162
+ c = -1;
163
+ }
164
+ else {
165
+ c = a.partName.localeCompare(b.partName);
166
+ }
167
+ break;
168
+ case "MedianTime":
169
+ if (a.statisticalCycleTime === null && b.statisticalCycleTime === null) {
170
+ c = 0;
171
+ }
172
+ else if (a.statisticalCycleTime === null) {
173
+ c = 1;
174
+ }
175
+ else if (b.statisticalCycleTime === null) {
176
+ c = -1;
177
+ }
178
+ else {
179
+ c =
180
+ a.statisticalCycleTime.medianMinutesForSingleMat -
181
+ b.statisticalCycleTime.medianMinutesForSingleMat;
182
+ }
183
+ break;
184
+ case "DeviationAbove":
185
+ if (a.statisticalCycleTime === null && b.statisticalCycleTime === null) {
186
+ c = 0;
187
+ }
188
+ else if (a.statisticalCycleTime === null) {
189
+ c = 1;
190
+ }
191
+ else if (b.statisticalCycleTime === null) {
192
+ c = -1;
193
+ }
194
+ else {
195
+ c = a.statisticalCycleTime.MAD_aboveMinutes - b.statisticalCycleTime.MAD_aboveMinutes;
196
+ }
197
+ break;
198
+ case "DeviationBelow":
199
+ if (a.statisticalCycleTime === null && b.statisticalCycleTime === null) {
200
+ c = 0;
201
+ }
202
+ else if (a.statisticalCycleTime === null) {
203
+ c = 1;
204
+ }
205
+ else if (b.statisticalCycleTime === null) {
206
+ c = -1;
207
+ }
208
+ else {
209
+ c = a.statisticalCycleTime.MAD_belowMinutes - b.statisticalCycleTime.MAD_belowMinutes;
210
+ }
211
+ break;
212
+ case "Planned":
213
+ if (a.plannedMins === null && b.plannedMins === null) {
214
+ c = 0;
215
+ }
216
+ else if (a.plannedMins === null) {
217
+ c = 1;
218
+ }
219
+ else if (b.plannedMins === null) {
220
+ c = -1;
221
+ }
222
+ else {
223
+ c = a.plannedMins - b.plannedMins;
224
+ }
225
+ break;
226
+ }
227
+ if (c === 0) {
228
+ return 0;
229
+ }
230
+ else if ((c < 0 && sortDir === "asc") || (c > 0 && sortDir === "desc")) {
231
+ return -1;
232
+ }
233
+ else {
234
+ return 1;
235
+ }
236
+ });
237
+ function toggleSort(s) {
238
+ if (s === sortCol) {
239
+ setSortDir(sortDir === "asc" ? "desc" : "asc");
240
+ }
241
+ else {
242
+ setSortCol(s);
243
+ }
244
+ }
245
+ return (_jsxs(Table, { stickyHeader: true, children: [_jsx(TableHead, { children: _jsxs(TableRow, { children: [_jsx(TableCell, {}), _jsx(TableCell, { sortDirection: sortCol === "ProgramName" ? sortDir : false, children: _jsx(TableSortLabel, { active: sortCol === "ProgramName", direction: sortDir, onClick: () => toggleSort("ProgramName"), children: "Program Name" }) }), report.cellNameDifferentFromProgName ? (_jsx(TableCell, { sortDirection: sortCol === "CellProgName" ? sortDir : false, children: _jsx(TableSortLabel, { active: sortCol === "CellProgName", direction: sortDir, onClick: () => toggleSort("CellProgName"), children: "Cell Controller Program" }) })) : undefined, _jsx(TableCell, { sortDirection: sortCol === "PartName" ? sortDir : false, children: _jsx(TableSortLabel, { active: sortCol === "PartName", direction: sortDir, onClick: () => toggleSort("PartName"), children: "Part" }) }), _jsx(TableCell, { sortDirection: sortCol === "Comment" ? sortDir : false, children: _jsx(TableSortLabel, { active: sortCol === "Comment", direction: sortDir, onClick: () => toggleSort("Comment"), children: "Comment" }) }), report.hasRevisions ? (_jsx(TableCell, { sortDirection: sortCol === "Revision" ? sortDir : false, children: _jsx(TableSortLabel, { active: sortCol === "Revision", direction: sortDir, onClick: () => toggleSort("Revision"), children: "Revision" }) })) : undefined, _jsx(TableCell, { sortDirection: sortCol === "MedianTime" ? sortDir : false, align: "right", children: _jsx(TableSortLabel, { active: sortCol === "MedianTime", direction: sortDir, onClick: () => toggleSort("MedianTime"), children: "Median Time / Material (min)" }) }), _jsx(TableCell, { sortDirection: sortCol === "DeviationAbove" ? sortDir : false, align: "right", children: _jsx(TableSortLabel, { active: sortCol === "DeviationAbove", direction: sortDir, onClick: () => toggleSort("DeviationAbove"), children: "Deviation Above Median" }) }), _jsx(TableCell, { sortDirection: sortCol === "DeviationBelow" ? sortDir : false, align: "right", children: _jsx(TableSortLabel, { active: sortCol === "DeviationBelow", direction: sortDir, onClick: () => toggleSort("DeviationBelow"), children: "Deviation Below Median" }) }), _jsx(TableCell, { sortDirection: sortCol === "Planned" ? sortDir : false, align: "right", children: _jsx(TableSortLabel, { active: sortCol === "Planned", direction: sortDir, onClick: () => toggleSort("Planned"), children: "Planned Time (min)" }) }), _jsx(TableCell, {})] }) }), _jsx(TableBody, { children: LazySeq.of(rows).map((program, idx) => (_jsx(ProgramRow, { program: program, showCellCtrlCol: report.cellNameDifferentFromProgName, showRevCol: report.hasRevisions }, idx))) })] }));
246
+ }
247
+ function ProgramContentCode() {
248
+ const ct = useAtomValue(programContent);
249
+ const [highlighted, setHighlighted] = useState(null);
250
+ const worker = useMemo(() => new Worker(new URL("./ProgramHighlight.ts", import.meta.url), { type: "module" }), []);
251
+ useEffect(() => {
252
+ let set = (h) => setHighlighted(h);
253
+ worker.onmessage = (e) => set(e.data);
254
+ return () => {
255
+ // cleanup
256
+ set = () => null;
257
+ worker.terminate();
258
+ setHighlighted(null);
259
+ };
260
+ }, [worker]);
261
+ useEffect(() => {
262
+ if (ct && ct !== "") {
263
+ worker.postMessage(ct);
264
+ }
265
+ }, [ct, worker]);
266
+ return (_jsx("pre", { children: highlighted === null ? (_jsx("code", { className: "gcode", children: ct })) : (_jsx("code", { className: "gcode", dangerouslySetInnerHTML: { __html: highlighted } })) }));
267
+ }
268
+ export function ProgramContentDialog() {
269
+ const [program, setProgramToShowContent] = useAtom(programToShowContent);
270
+ const history = useAtomValue(programToShowHistory);
271
+ // when history is open, content is shown on the history dialog
272
+ return (_jsxs(Dialog, { open: program !== null && history === null, onClose: () => setProgramToShowContent(null), maxWidth: "lg", children: [_jsx(DialogTitle, { children: program?.partName ? (_jsxs("div", { style: { display: "flex", flexWrap: "wrap", alignItems: "center" }, children: [_jsx(PartIdenticon, { part: program.partName }), _jsxs("div", { style: { marginLeft: "10px", marginRight: "3em" }, children: [program?.programName ?? "Program", " ", program?.revision ? " rev" + program.revision.toFixed() : "", " ", _jsxs(Typography, { variant: "subtitle1", component: "span", children: ["(", program.partName, ")"] })] })] })) : (_jsxs(_Fragment, { children: [program?.programName ?? "Program", " ", program?.revision ? " rev" + program.revision.toFixed() : ""] })) }), _jsx(DialogContent, { children: program === null || history !== null ? (_jsx("div", {})) : (_jsx(DisplayLoadingAndError, { children: _jsx(ProgramContentCode, {}) })) }), _jsx(DialogActions, { children: _jsx(Button, { onClick: () => setProgramToShowContent(null), children: "Close" }) })] }));
273
+ }
274
+ const revisionsPerPage = 10;
275
+ function ProgramRevisionTable(props) {
276
+ const program = useAtomValue(programToShowHistory);
277
+ const setProgramToShowContent = useSetAtom(programToShowContent);
278
+ return (_jsxs(Table, { children: [_jsx(TableHead, { children: _jsxs(TableRow, { children: [_jsx(TableCell, { children: "Revision" }), _jsx(TableCell, { children: "Comment" }), _jsx(TableCell, { children: "Cell Controller Program" }), _jsx(TableCell, {})] }) }), _jsx(TableBody, { children: props.loading ? (_jsxs(_Fragment, { children: [_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 4, children: _jsx(CircularProgress, {}) }) }), LazySeq.ofRange(0, revisionsPerPage - 1).map((i) => (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 4 }) }, i)))] })) : (LazySeq.of(props.revisions)
279
+ .drop(props.page * revisionsPerPage)
280
+ .take(revisionsPerPage)
281
+ .map((rev) => (_jsxs(TableRow, { children: [_jsx(TableCell, { children: rev.revision }), _jsx(TableCell, { children: rev.comment ?? "" }), _jsx(TableCell, { children: rev.cellControllerProgramName ?? "" }), _jsx(TableCell, { children: _jsx(Tooltip, { title: "Load Program Content", children: _jsx(IconButton, { size: "small", onClick: () => setProgramToShowContent({
282
+ ...rev,
283
+ partName: program?.partName ?? null,
284
+ }), children: _jsx(CodeIcon, {}) }) }) })] }, rev.revision)))) })] }));
285
+ }
286
+ export function ProgramHistoryDialog() {
287
+ const [program, setProgram] = useAtom(programToShowHistory);
288
+ const [programForContent, setProgramForContent] = useAtom(programToShowContent);
289
+ // TODO: switch to persistent list
290
+ const [revisions, setRevisions] = useState(null);
291
+ const [lastLoadedPage, setLastLoadedPage] = useState({ page: 0, hasMore: false });
292
+ const [page, setPage] = useState(0);
293
+ const [loading, setLoading] = useState(false);
294
+ const [error, setError] = useState(null);
295
+ useEffect(() => {
296
+ if (program === null) {
297
+ setRevisions(null);
298
+ setPage(0);
299
+ setLastLoadedPage({ page: 0, hasMore: false });
300
+ }
301
+ else if (program !== null && revisions === null) {
302
+ // load initial
303
+ setLoading(true);
304
+ setError(null);
305
+ MachineBackend.getProgramRevisionsInDescendingOrderOfRevision(program.programName, revisionsPerPage, undefined)
306
+ .then((revs) => {
307
+ setRevisions(revs);
308
+ setLastLoadedPage({ page: 0, hasMore: revs.length === revisionsPerPage });
309
+ })
310
+ .catch(setError)
311
+ .finally(() => setLoading(false));
312
+ }
313
+ }, [program, revisions]);
314
+ function advancePage() {
315
+ if (page < lastLoadedPage.page) {
316
+ setPage(page + 1);
317
+ }
318
+ else if (lastLoadedPage.hasMore && program !== null && revisions !== null && revisions.length > 0) {
319
+ setLoading(true);
320
+ setError(null);
321
+ const rev = revisions[revisions.length - 1];
322
+ MachineBackend.getProgramRevisionsInDescendingOrderOfRevision(program.programName, revisionsPerPage, rev ? rev.revision - 1 : undefined)
323
+ .then((revs) => {
324
+ setRevisions((oldRevs) => (oldRevs === null ? revs : oldRevs.concat(revs)));
325
+ setLastLoadedPage({ page: page + 1, hasMore: revs.length === revisionsPerPage });
326
+ setPage(page + 1);
327
+ })
328
+ .catch(setError)
329
+ .finally(() => setLoading(false));
330
+ }
331
+ }
332
+ return (_jsxs(Dialog, { open: program !== null, onClose: () => setProgram(null), maxWidth: "lg", children: [_jsx(DialogTitle, { children: program?.partName ? (_jsxs("div", { style: { display: "flex", flexWrap: "wrap", alignItems: "center" }, children: [_jsx(PartIdenticon, { part: program.partName }), _jsxs("div", { style: { marginLeft: "10px", marginRight: "3em" }, children: [program.programName ?? "Program", " ", _jsxs(Typography, { variant: "subtitle1", component: "span", children: ["(", program.partName, ")"] })] })] })) : (_jsx(_Fragment, { children: program?.programName ?? "Program" })) }), _jsxs(DialogContent, { children: [error !== null ? (_jsx(Card, { children: _jsx(CardContent, { children: typeof error === "string" ? error : error.message }) })) : undefined, programForContent !== null ? (_jsx(DisplayLoadingAndError, { children: _jsx(ProgramContentCode, {}) })) : revisions !== null ? (_jsx(ProgramRevisionTable, { page: page, revisions: revisions, loading: loading })) : loading ? (_jsx(CircularProgress, {})) : undefined] }), _jsx(DialogActions, { children: _jsxs("div", { style: { display: "flex", alignItems: "center", width: "100%" }, children: [programForContent === null ? (_jsxs(_Fragment, { children: [_jsx(Tooltip, { title: "Latest Revisions", children: _jsx("span", { children: _jsx(IconButton, { onClick: () => setPage(0), disabled: loading || page === 0, size: "large", children: _jsx(FirstPageIcon, {}) }) }) }), _jsx(Tooltip, { title: "Previous Page", children: _jsx("span", { children: _jsx(IconButton, { onClick: () => setPage(page - 1), disabled: loading || page === 0, size: "large", children: _jsx(KeyboardArrowLeft, {}) }) }) }), _jsx(Tooltip, { title: "Next Page", children: _jsx("span", { children: _jsx(IconButton, { onClick: () => advancePage(), disabled: loading || (page === lastLoadedPage.page && !lastLoadedPage.hasMore), size: "large", children: _jsx(KeyboardArrowRight, {}) }) }) })] })) : undefined, _jsx("div", { style: { flexGrow: 1 } }), programForContent !== null ? (_jsx(Button, { onClick: () => setProgramForContent(null), children: "Back to History" })) : undefined, _jsx(Button, { onClick: () => setProgram(null), children: "Close" })] }) })] }));
333
+ }
334
+ function ProgNavHeader() {
335
+ const [reloadTime, refreshPrograms] = useAtom(programReportRefreshTime);
336
+ const [loading, setLoading] = useState(false);
337
+ const demo = useIsDemo();
338
+ const [filter, setFilter] = useAtom(programFilter);
339
+ function refresh() {
340
+ setLoading(true);
341
+ refreshPrograms(new Date())
342
+ .catch(console.log)
343
+ .finally(() => setLoading(false));
344
+ }
345
+ if (demo) {
346
+ return _jsx("div", {});
347
+ }
348
+ else if (reloadTime === null) {
349
+ return (_jsx("main", { style: { margin: "2em", display: "flex", justifyContent: "center" }, children: _jsx(Fab, { color: "secondary", size: "large", variant: "extended", style: { margin: "2em" }, onClick: refresh, disabled: loading, children: _jsxs(_Fragment, { children: [loading ? (_jsx(CircularProgress, { size: 10, style: { marginRight: "1em" } })) : (_jsx(RefreshIcon, { fontSize: "inherit", style: { marginRight: "1em" } })), "Load Programs"] }) }) }));
350
+ }
351
+ else {
352
+ return (_jsxs(Box, { component: "nav", sx: {
353
+ display: "flex",
354
+ minHeight: "2.5em",
355
+ alignItems: "center",
356
+ maxWidth: "calc(100vw - 24px - 24px)",
357
+ }, children: [_jsx(Tooltip, { title: "Refresh Programs", children: _jsx("div", { children: _jsx(IconButton, { onClick: refresh, disabled: loading, size: "small", children: loading ? _jsx(CircularProgress, { size: 10 }) : _jsx(RefreshIcon, { fontSize: "inherit" }) }) }) }), _jsxs("span", { style: { marginLeft: "1em" }, children: ["Programs from ", _jsx(TimeAgo, { date: reloadTime })] }), _jsx("div", { style: { flexGrow: 1 } }), _jsx(FormControl, { size: "small", children: _jsxs(Select, { autoWidth: true, value: filter, onChange: (e) => setFilter(e.target.value), children: [_jsx(MenuItem, { value: "AllPrograms", children: "All Programs" }, "AllPrograms"), _jsx(MenuItem, { value: "ActivePrograms", children: "Active Programs" }, "ActivePrograms")] }) })] }));
358
+ }
359
+ }
360
+ export function ProgramReportPage() {
361
+ useSetTitle("Programs");
362
+ return (_jsxs(Box, { paddingLeft: "24px", paddingRight: "24px", paddingTop: "10px", children: [_jsx(ProgNavHeader, {}), _jsx("main", { children: _jsx(DisplayLoadingAndError, { children: _jsx(ProgramSummaryTable, {}) }) }), _jsx(ProgramContentDialog, {}), _jsx(ProgramHistoryDialog, {})] }));
363
+ }
@@ -0,0 +1 @@
1
+ export declare function RebookingsPage(): import("react/jsx-runtime").JSX.Element;