@naisys/erp 3.0.2 → 3.0.3

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 (32) hide show
  1. package/README.md +60 -0
  2. package/client-dist/assets/{index-D5R6NBeW.js → index-CiuQ3CYv.js} +192 -87
  3. package/client-dist/index.html +1 -1
  4. package/dist/database/dbConfig.js +1 -1
  5. package/dist/erpServer.js +2 -3
  6. package/dist/generated/prisma/internal/class.js +4 -4
  7. package/dist/generated/prisma/internal/prismaNamespace.js +1 -0
  8. package/dist/middleware/auth-middleware.js +39 -7
  9. package/dist/route-helpers.js +4 -2
  10. package/dist/routes/operations/operation-dependencies.js +1 -0
  11. package/dist/routes/operations/operation-field-refs.js +1 -0
  12. package/dist/routes/operations/operation-run-comments.js +1 -0
  13. package/dist/routes/operations/operation-runs.js +3 -0
  14. package/dist/routes/production/dispatch.js +15 -9
  15. package/dist/routes/production/labor-tickets.js +1 -0
  16. package/dist/routes/production/work-centers.js +2 -0
  17. package/dist/routes/users/auth.js +4 -1
  18. package/dist/routes/users/users.js +28 -16
  19. package/dist/services/operations/operation-dependency-service.js +1 -1
  20. package/dist/services/operations/operation-run-comment-service.js +1 -1
  21. package/dist/services/operations/operation-run-service.js +6 -6
  22. package/dist/services/operations/step-run-service.js +4 -4
  23. package/dist/services/orders/order-run-service.js +2 -2
  24. package/dist/services/production/field-ref-service.js +1 -1
  25. package/dist/services/production/labor-ticket-service.js +3 -3
  26. package/dist/services/production/work-center-service.js +2 -2
  27. package/dist/services/user-service.js +58 -9
  28. package/npm-shrinkwrap.json +28 -28
  29. package/package.json +11 -6
  30. package/prisma/migrations/20260528000000_add_user_title/migration.sql +1 -0
  31. package/prisma/schema.prisma +1 -0
  32. package/dist/services/production/labor-ticket-backfill.js +0 -67
@@ -650,6 +650,12 @@ function useAuth() {
650
650
  return ctx;
651
651
  }
652
652
  //#endregion
653
+ //#region src/lib/userLabel.ts
654
+ /** Format a user as "Title (username)" — falls back to just `username` when no title. */
655
+ function formatUserLabel(username, title) {
656
+ return title ? `${title} (${username})` : username;
657
+ }
658
+ //#endregion
653
659
  //#region src/components/error/RouteErrorPage.tsx
654
660
  var RouteErrorPage = ({ error }) => {
655
661
  const navigate = useNavigate();
@@ -1326,8 +1332,10 @@ var StepRunSchema = object({
1326
1332
  fieldValues: array(FieldValueEntrySchema).optional(),
1327
1333
  createdAt: datetime(),
1328
1334
  createdBy: string(),
1335
+ createdByTitle: string(),
1329
1336
  updatedAt: datetime(),
1330
1337
  updatedBy: string(),
1338
+ updatedByTitle: string(),
1331
1339
  _links: array(HateoasLinkSchema).optional(),
1332
1340
  _actions: array(HateoasActionSchema).optional(),
1333
1341
  _actionTemplates: array(HateoasActionTemplateSchema).optional()
@@ -1361,6 +1369,7 @@ object({
1361
1369
  note: string().nullable(),
1362
1370
  updatedAt: datetime(),
1363
1371
  updatedBy: string(),
1372
+ updatedByTitle: string(),
1364
1373
  _actions: array(HateoasActionSchema).optional(),
1365
1374
  _actionTemplates: array(HateoasActionTemplateSchema).optional()
1366
1375
  });
@@ -1383,8 +1392,10 @@ var ItemInstanceSchema = object({
1383
1392
  quantity: number().nullable(),
1384
1393
  fieldValues: array(FieldValueEntrySchema),
1385
1394
  createdBy: string(),
1395
+ createdByTitle: string(),
1386
1396
  createdAt: datetime(),
1387
1397
  updatedBy: string(),
1398
+ updatedByTitle: string(),
1388
1399
  updatedAt: datetime(),
1389
1400
  _links: array(HateoasLinkSchema).optional(),
1390
1401
  _actions: array(HateoasActionSchema).optional(),
@@ -1435,8 +1446,10 @@ var FieldSchema = object({
1435
1446
  required: boolean(),
1436
1447
  createdAt: datetime(),
1437
1448
  createdBy: string(),
1449
+ createdByTitle: string(),
1438
1450
  updatedAt: datetime(),
1439
1451
  updatedBy: string(),
1452
+ updatedByTitle: string(),
1440
1453
  _links: array(HateoasLinkSchema).optional(),
1441
1454
  _actions: array(HateoasActionSchema).optional()
1442
1455
  });
@@ -1471,8 +1484,10 @@ var ItemSchema = object({
1471
1484
  description: string(),
1472
1485
  fields: FieldListResponseSchema,
1473
1486
  createdBy: string(),
1487
+ createdByTitle: string(),
1474
1488
  createdAt: datetime(),
1475
1489
  updatedBy: string(),
1490
+ updatedByTitle: string(),
1476
1491
  updatedAt: datetime(),
1477
1492
  _links: array(HateoasLinkSchema).optional(),
1478
1493
  _actions: array(HateoasActionSchema).optional()
@@ -1516,6 +1531,7 @@ var FieldRefSchema = object({
1516
1531
  fields: array(FieldRefFieldSchema),
1517
1532
  createdAt: datetime(),
1518
1533
  createdBy: string(),
1534
+ createdByTitle: string(),
1519
1535
  _links: array(HateoasLinkSchema).optional(),
1520
1536
  _actions: array(HateoasActionSchema).optional()
1521
1537
  });
@@ -1565,8 +1581,10 @@ var OperationSchema = object({
1565
1581
  predecessors: array(OperationPredecessorSchema).optional(),
1566
1582
  createdAt: datetime(),
1567
1583
  createdBy: string(),
1584
+ createdByTitle: string(),
1568
1585
  updatedAt: datetime(),
1569
1586
  updatedBy: string(),
1587
+ updatedByTitle: string(),
1570
1588
  _links: array(HateoasLinkSchema).optional(),
1571
1589
  _actions: array(HateoasActionSchema).optional()
1572
1590
  });
@@ -1621,6 +1639,7 @@ var OperationRunSchema = object({
1621
1639
  predecessors: array(OperationPredecessorSchema).optional(),
1622
1640
  status: OperationRunStatusEnum,
1623
1641
  assignedTo: string().nullable(),
1642
+ assignedToTitle: string().nullable(),
1624
1643
  cost: number().nullable(),
1625
1644
  tokens: number().nullable(),
1626
1645
  note: string().nullable(),
@@ -1629,8 +1648,10 @@ var OperationRunSchema = object({
1629
1648
  fieldRefSummary: array(FieldRefValueSummarySchema).optional(),
1630
1649
  createdAt: datetime(),
1631
1650
  createdBy: string(),
1651
+ createdByTitle: string(),
1632
1652
  updatedAt: datetime(),
1633
1653
  updatedBy: string(),
1654
+ updatedByTitle: string(),
1634
1655
  _links: array(HateoasLinkSchema).optional(),
1635
1656
  _actions: array(HateoasActionSchema).optional()
1636
1657
  });
@@ -1644,12 +1665,14 @@ object({
1644
1665
  id: number(),
1645
1666
  status: OperationRunStatusEnum,
1646
1667
  assignedTo: string().nullable(),
1668
+ assignedToTitle: string().nullable(),
1647
1669
  cost: number().nullable(),
1648
1670
  tokens: number().nullable(),
1649
1671
  note: string().nullable(),
1650
1672
  completedAt: datetime().nullable(),
1651
1673
  updatedAt: datetime(),
1652
1674
  updatedBy: string(),
1675
+ updatedByTitle: string(),
1653
1676
  _actions: array(HateoasActionSchema).optional()
1654
1677
  });
1655
1678
  object({
@@ -1682,8 +1705,10 @@ var OrderRevisionSchema = object({
1682
1705
  operationSummary: array(RevisionOperationSummarySchema).optional(),
1683
1706
  createdAt: datetime(),
1684
1707
  createdBy: string(),
1708
+ createdByTitle: string(),
1685
1709
  updatedAt: datetime(),
1686
1710
  updatedBy: string(),
1711
+ updatedByTitle: string(),
1687
1712
  _links: array(HateoasLinkSchema).optional(),
1688
1713
  _actions: array(HateoasActionSchema).optional()
1689
1714
  });
@@ -1748,8 +1773,10 @@ var OrderRunSchema = object({
1748
1773
  operationSummary: array(OperationRunSummarySchema).optional(),
1749
1774
  createdAt: datetime(),
1750
1775
  createdBy: string(),
1776
+ createdByTitle: string(),
1751
1777
  updatedAt: datetime(),
1752
1778
  updatedBy: string(),
1779
+ updatedByTitle: string(),
1753
1780
  _links: array(HateoasLinkSchema).optional(),
1754
1781
  _actions: array(HateoasActionSchema).optional()
1755
1782
  });
@@ -1791,7 +1818,7 @@ object({
1791
1818
  object({
1792
1819
  ...paginationQuery(),
1793
1820
  status: OperationRunStatusEnum.optional(),
1794
- priority: OrderRunPriorityEnum.optional(),
1821
+ workCenter: string().optional(),
1795
1822
  search: string().optional(),
1796
1823
  viewAs: string().optional(),
1797
1824
  canWork: union([literal("true"), literal("false")]).transform((v) => v === "true").optional(),
@@ -1808,8 +1835,8 @@ object({
1808
1835
  workCenterKey: string().nullable(),
1809
1836
  canWork: boolean(),
1810
1837
  status: OperationRunStatusEnum,
1811
- priority: OrderRunPriorityEnum,
1812
1838
  assignedTo: string().nullable(),
1839
+ assignedToTitle: string().nullable(),
1813
1840
  dueAt: string().nullable(),
1814
1841
  createdAt: datetime()
1815
1842
  })),
@@ -1908,7 +1935,8 @@ var OperationDependencySchema = object({
1908
1935
  predecessorSeqNo: number(),
1909
1936
  predecessorTitle: string(),
1910
1937
  createdAt: datetime(),
1911
- createdBy: string()
1938
+ createdBy: string(),
1939
+ createdByTitle: string()
1912
1940
  });
1913
1941
  var CreateOperationDependencySchema = object({ predecessorSeqNo: number().int().min(1) }).strict();
1914
1942
  object({
@@ -1933,6 +1961,7 @@ var OperationRunCommentSchema = object({
1933
1961
  body: string(),
1934
1962
  createdAt: datetime(),
1935
1963
  createdBy: string(),
1964
+ createdByTitle: string(),
1936
1965
  _links: array(HateoasLinkSchema).optional()
1937
1966
  });
1938
1967
  object({
@@ -1958,8 +1987,10 @@ var OrderSchema = object({
1958
1987
  itemKey: string().nullable(),
1959
1988
  latestApprovedRevNo: number().int().nullable().optional(),
1960
1989
  createdBy: string(),
1990
+ createdByTitle: string(),
1961
1991
  createdAt: datetime(),
1962
1992
  updatedBy: string(),
1993
+ updatedByTitle: string(),
1963
1994
  updatedAt: datetime(),
1964
1995
  _links: array(HateoasLinkSchema).optional(),
1965
1996
  _actions: array(HateoasActionSchema).optional()
@@ -1994,8 +2025,10 @@ object({
1994
2025
  var WorkCenterUserSchema = object({
1995
2026
  userId: number(),
1996
2027
  username: string(),
2028
+ userTitle: string(),
1997
2029
  createdAt: string(),
1998
2030
  createdBy: string().nullable(),
2031
+ createdByTitle: string().nullable(),
1999
2032
  _actions: array(HateoasActionSchema).optional()
2000
2033
  });
2001
2034
  object({
@@ -2005,8 +2038,10 @@ object({
2005
2038
  userAssignments: array(WorkCenterUserSchema),
2006
2039
  createdAt: datetime(),
2007
2040
  createdBy: string(),
2041
+ createdByTitle: string(),
2008
2042
  updatedAt: datetime(),
2009
2043
  updatedBy: string(),
2044
+ updatedByTitle: string(),
2010
2045
  _links: array(HateoasLinkSchema),
2011
2046
  _actions: array(HateoasActionSchema).optional()
2012
2047
  });
@@ -2031,8 +2066,10 @@ object({
2031
2066
  userCount: number(),
2032
2067
  createdAt: datetime(),
2033
2068
  createdBy: string(),
2069
+ createdByTitle: string(),
2034
2070
  updatedAt: datetime(),
2035
- updatedBy: string()
2071
+ updatedBy: string(),
2072
+ updatedByTitle: string()
2036
2073
  })),
2037
2074
  total: number(),
2038
2075
  page: number(),
@@ -2111,6 +2148,7 @@ var LaborTicketSchema = object({
2111
2148
  operationRunId: number(),
2112
2149
  userId: number(),
2113
2150
  username: string(),
2151
+ userTitle: string(),
2114
2152
  runId: number().nullable(),
2115
2153
  clockIn: datetime(),
2116
2154
  clockOut: datetime().nullable(),
@@ -2118,8 +2156,10 @@ var LaborTicketSchema = object({
2118
2156
  tokens: number().nullable(),
2119
2157
  createdAt: datetime(),
2120
2158
  createdBy: string(),
2159
+ createdByTitle: string(),
2121
2160
  updatedAt: datetime(),
2122
2161
  updatedBy: string(),
2162
+ updatedByTitle: string(),
2123
2163
  _links: array(HateoasLinkSchema).optional()
2124
2164
  });
2125
2165
  object({
@@ -2146,8 +2186,10 @@ var StepSchema = object({
2146
2186
  fieldCount: number().optional(),
2147
2187
  createdAt: datetime(),
2148
2188
  createdBy: string(),
2189
+ createdByTitle: string(),
2149
2190
  updatedAt: datetime(),
2150
2191
  updatedBy: string(),
2192
+ updatedByTitle: string(),
2151
2193
  fields: FieldListResponseSchema,
2152
2194
  _links: array(HateoasLinkSchema).optional(),
2153
2195
  _actions: array(HateoasActionSchema).optional()
@@ -2182,6 +2224,7 @@ var LoginRequestSchema = object({
2182
2224
  object({ user: object({
2183
2225
  id: number(),
2184
2226
  username: string(),
2227
+ title: string(),
2185
2228
  permissions: array(string()).optional()
2186
2229
  }) });
2187
2230
  //#endregion
@@ -2201,7 +2244,8 @@ object({
2201
2244
  }).strict();
2202
2245
  object({
2203
2246
  username: urlSafeUsername.optional(),
2204
- password: string().min(6).optional()
2247
+ password: string().min(6).optional(),
2248
+ title: string().max(255).optional()
2205
2249
  }).strict();
2206
2250
  object({ permission: ErpPermissionEnum }).strict();
2207
2251
  object({ agentId: number().int() }).strict();
@@ -2215,6 +2259,7 @@ var UserPermissionSchema = object({
2215
2259
  object({
2216
2260
  id: number(),
2217
2261
  username: string(),
2262
+ title: string(),
2218
2263
  isAgent: boolean(),
2219
2264
  createdAt: string(),
2220
2265
  updatedAt: string(),
@@ -2227,6 +2272,7 @@ object({
2227
2272
  items: array(object({
2228
2273
  id: number(),
2229
2274
  username: string(),
2275
+ title: string(),
2230
2276
  isAgent: boolean(),
2231
2277
  createdAt: string(),
2232
2278
  permissionCount: number()
@@ -2497,7 +2543,7 @@ var AppLayout = ({ supervisorAuth }) => {
2497
2543
  size: "xs",
2498
2544
  color: "gray",
2499
2545
  style: { flexShrink: 0 },
2500
- children: user.username
2546
+ children: formatUserLabel(user.username, user.title)
2501
2547
  }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Menu.Dropdown, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Menu.Item, {
2502
2548
  leftSection: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconUser, { size: "0.9rem" }),
2503
2549
  onClick: () => navigate(`/users/${user.username}`),
@@ -2738,7 +2784,8 @@ var UserAutocomplete = ({ value, onChange, onUserSelect, ...rest }) => {
2738
2784
  if (search) params.set("search", search);
2739
2785
  setOptions((await api.get(`${apiEndpoints.users}?${params}`)).items.map((u) => ({
2740
2786
  id: u.id,
2741
- username: u.username
2787
+ username: u.username,
2788
+ title: u.title
2742
2789
  })));
2743
2790
  } catch {
2744
2791
  setOptions([]);
@@ -2748,7 +2795,10 @@ var UserAutocomplete = ({ value, onChange, onUserSelect, ...rest }) => {
2748
2795
  fetchOptions(debouncedValue);
2749
2796
  }, [debouncedValue, fetchOptions]);
2750
2797
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Autocomplete, {
2751
- data: options.map((o) => o.username),
2798
+ data: options.map((o) => ({
2799
+ value: o.username,
2800
+ label: formatUserLabel(o.username, o.title)
2801
+ })),
2752
2802
  value,
2753
2803
  onChange,
2754
2804
  onOptionSubmit: (val) => {
@@ -2760,6 +2810,31 @@ var UserAutocomplete = ({ value, onChange, onUserSelect, ...rest }) => {
2760
2810
  });
2761
2811
  };
2762
2812
  //#endregion
2813
+ //#region src/components/WorkCenterAutocomplete.tsx
2814
+ var WorkCenterAutocomplete = ({ value, onChange, ...rest }) => {
2815
+ const [debouncedValue] = useDebouncedValue(value, 300);
2816
+ const [options, setOptions] = (0, import_react.useState)([]);
2817
+ const fetchOptions = (0, import_react.useCallback)(async (search) => {
2818
+ try {
2819
+ const params = new URLSearchParams();
2820
+ params.set("pageSize", "10");
2821
+ if (search) params.set("search", search);
2822
+ setOptions((await api.get(`${apiEndpoints.workCenters}?${params}`)).items.map((wc) => wc.key));
2823
+ } catch {
2824
+ setOptions([]);
2825
+ }
2826
+ }, []);
2827
+ (0, import_react.useEffect)(() => {
2828
+ fetchOptions(debouncedValue);
2829
+ }, [debouncedValue, fetchOptions]);
2830
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Autocomplete, {
2831
+ data: options,
2832
+ value,
2833
+ onChange,
2834
+ ...rest
2835
+ });
2836
+ };
2837
+ //#endregion
2763
2838
  //#region src/lib/tableStyles.ts
2764
2839
  /** Style for a <Link> that fills an entire table cell, replacing the cell's own padding. Use with `<Table.Td style={{ padding: 0 }}>`. */
2765
2840
  var cellLinkStyle = {
@@ -2778,12 +2853,6 @@ var STATUS_COLORS$7 = {
2778
2853
  [OperationRunStatus.skipped]: "gray",
2779
2854
  [OperationRunStatus.failed]: "red"
2780
2855
  };
2781
- var PRIORITY_COLORS$4 = {
2782
- low: "gray",
2783
- medium: "blue",
2784
- high: "orange",
2785
- critical: "red"
2786
- };
2787
2856
  var STATUS_OPTIONS = [
2788
2857
  {
2789
2858
  value: OperationRunStatus.pending,
@@ -2803,13 +2872,14 @@ var DispatchList = () => {
2803
2872
  const [searchParams, setSearchParams] = useSearchParams();
2804
2873
  const page = Number(searchParams.get("page")) || 1;
2805
2874
  const status = searchParams.get("status") || void 0;
2806
- const priority = searchParams.get("priority") || void 0;
2875
+ const workCenter = searchParams.get("workCenter") || "";
2807
2876
  const search = searchParams.get("search") || "";
2808
2877
  const viewAs = searchParams.get("viewAs") || "";
2809
2878
  const canWork = searchParams.get("canWork") === "true";
2810
2879
  const clockedIn = searchParams.get("clockedIn") === "true";
2811
2880
  const [searchInput, setSearchInput] = (0, import_react.useState)(search);
2812
2881
  const [viewAsInput, setViewAsInput] = (0, import_react.useState)(viewAs);
2882
+ const [workCenterInput, setWorkCenterInput] = (0, import_react.useState)(workCenter);
2813
2883
  const [debouncedSearch] = useDebouncedValue(searchInput, 300);
2814
2884
  const isFirstRender = (0, import_react.useRef)(true);
2815
2885
  (0, import_react.useEffect)(() => {
@@ -2823,7 +2893,7 @@ var DispatchList = () => {
2823
2893
  prev.set("page", "1");
2824
2894
  return prev;
2825
2895
  });
2826
- }, [debouncedSearch, setSearchParams]);
2896
+ }, [debouncedSearch]);
2827
2897
  const [data, setData] = (0, import_react.useState)(null);
2828
2898
  const [loading, setLoading] = (0, import_react.useState)(true);
2829
2899
  const fetchData = (0, import_react.useCallback)(async () => {
@@ -2833,7 +2903,7 @@ var DispatchList = () => {
2833
2903
  params.set("page", String(page));
2834
2904
  params.set("pageSize", "20");
2835
2905
  if (status) params.set("status", status);
2836
- if (priority) params.set("priority", priority);
2906
+ if (workCenter) params.set("workCenter", workCenter);
2837
2907
  if (search) params.set("search", search);
2838
2908
  if (viewAs) params.set("viewAs", viewAs);
2839
2909
  if (canWork) params.set("canWork", "true");
@@ -2847,7 +2917,7 @@ var DispatchList = () => {
2847
2917
  }, [
2848
2918
  page,
2849
2919
  status,
2850
- priority,
2920
+ workCenter,
2851
2921
  search,
2852
2922
  viewAs,
2853
2923
  canWork,
@@ -2906,22 +2976,26 @@ var DispatchList = () => {
2906
2976
  },
2907
2977
  clearable: true
2908
2978
  }),
2909
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Select, {
2910
- placeholder: "All priorities",
2911
- data: OrderRunPriorityEnum.options.map((v) => ({
2912
- value: v,
2913
- label: v.charAt(0).toUpperCase() + v.slice(1)
2914
- })),
2915
- value: priority ?? null,
2979
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(WorkCenterAutocomplete, {
2980
+ placeholder: "Work center...",
2981
+ value: workCenterInput,
2916
2982
  onChange: (val) => {
2983
+ setWorkCenterInput(val);
2984
+ if (!val) setSearchParams((prev) => {
2985
+ prev.delete("workCenter");
2986
+ prev.set("page", "1");
2987
+ return prev;
2988
+ });
2989
+ },
2990
+ onOptionSubmit: (val) => {
2991
+ setWorkCenterInput(val);
2917
2992
  setSearchParams((prev) => {
2918
- if (val) prev.set("priority", val);
2919
- else prev.delete("priority");
2993
+ prev.set("workCenter", val);
2920
2994
  prev.set("page", "1");
2921
2995
  return prev;
2922
2996
  });
2923
2997
  },
2924
- clearable: true
2998
+ w: 180
2925
2999
  }),
2926
3000
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserAutocomplete, {
2927
3001
  placeholder: "View as user...",
@@ -2983,7 +3057,7 @@ var DispatchList = () => {
2983
3057
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Operation" }),
2984
3058
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Can Work" }),
2985
3059
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Status" }),
2986
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Priority" }),
3060
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Work Center" }),
2987
3061
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Assigned To" }),
2988
3062
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Due" })
2989
3063
  ] }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Tbody, { children: data.items.map((item) => {
@@ -3068,11 +3142,11 @@ var DispatchList = () => {
3068
3142
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
3069
3143
  to: opRunLink,
3070
3144
  style: cellLinkStyle,
3071
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
3072
- color: PRIORITY_COLORS$4[item.priority] ?? "gray",
3073
- variant: "light",
3074
- children: item.priority
3075
- })
3145
+ children: item.workCenterKey ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
3146
+ size: "sm",
3147
+ ff: "monospace",
3148
+ children: item.workCenterKey
3149
+ }) : "—"
3076
3150
  })
3077
3151
  }),
3078
3152
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, {
@@ -3080,7 +3154,7 @@ var DispatchList = () => {
3080
3154
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
3081
3155
  to: opRunLink,
3082
3156
  style: cellLinkStyle,
3083
- children: item.assignedTo ?? "—"
3157
+ children: item.assignedTo ? formatUserLabel(item.assignedTo, item.assignedToTitle) : "—"
3084
3158
  })
3085
3159
  }),
3086
3160
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, {
@@ -3142,7 +3216,7 @@ var DispatchReadyToClose = () => {
3142
3216
  prev.set("page", "1");
3143
3217
  return prev;
3144
3218
  });
3145
- }, [debouncedSearch, setSearchParams]);
3219
+ }, [debouncedSearch]);
3146
3220
  const [data, setData] = (0, import_react.useState)(null);
3147
3221
  const [loading, setLoading] = (0, import_react.useState)(true);
3148
3222
  const fetchData = (0, import_react.useCallback)(async () => {
@@ -3365,7 +3439,7 @@ var InventoryList = () => {
3365
3439
  prev.set("page", "1");
3366
3440
  return prev;
3367
3441
  });
3368
- }, [debouncedSearch, setSearchParams]);
3442
+ }, [debouncedSearch]);
3369
3443
  const [data, setData] = (0, import_react.useState)(null);
3370
3444
  const [loading, setLoading] = (0, import_react.useState)(true);
3371
3445
  const fetchData = (0, import_react.useCallback)(async () => {
@@ -3565,7 +3639,7 @@ var ItemCreate = () => {
3565
3639
  };
3566
3640
  //#endregion
3567
3641
  //#region src/components/MetadataTooltip.tsx
3568
- var MetadataTooltip = ({ createdBy, createdAt, updatedBy, updatedAt }) => {
3642
+ var MetadataTooltip = ({ createdBy, createdByTitle, createdAt, updatedBy, updatedByTitle, updatedAt }) => {
3569
3643
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, {
3570
3644
  label: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Stack, {
3571
3645
  gap: 4,
@@ -3573,7 +3647,7 @@ var MetadataTooltip = ({ createdBy, createdAt, updatedBy, updatedAt }) => {
3573
3647
  size: "xs",
3574
3648
  children: [
3575
3649
  "Created",
3576
- createdBy ? ` by ${createdBy}` : "",
3650
+ createdBy ? ` by ${formatUserLabel(createdBy, createdByTitle)}` : "",
3577
3651
  ",",
3578
3652
  " ",
3579
3653
  new Date(createdAt).toLocaleString()
@@ -3582,7 +3656,7 @@ var MetadataTooltip = ({ createdBy, createdAt, updatedBy, updatedAt }) => {
3582
3656
  size: "xs",
3583
3657
  children: [
3584
3658
  "Modified",
3585
- updatedBy ? ` by ${updatedBy}` : "",
3659
+ updatedBy ? ` by ${formatUserLabel(updatedBy, updatedByTitle)}` : "",
3586
3660
  ",",
3587
3661
  " ",
3588
3662
  new Date(updatedAt).toLocaleString()
@@ -3812,8 +3886,10 @@ var FieldDefList = ({ fieldsEndpoint, fieldEndpoint, initialData }) => {
3812
3886
  children: [
3813
3887
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetadataTooltip, {
3814
3888
  createdBy: field.createdBy,
3889
+ createdByTitle: field.createdByTitle,
3815
3890
  createdAt: field.createdAt,
3816
3891
  updatedBy: field.updatedBy,
3892
+ updatedByTitle: field.updatedByTitle,
3817
3893
  updatedAt: field.updatedAt
3818
3894
  }),
3819
3895
  hasAction(field._actions, "update") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
@@ -3974,8 +4050,10 @@ var ItemDetail = () => {
3974
4050
  children: item.key
3975
4051
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetadataTooltip, {
3976
4052
  createdBy: item.createdBy,
4053
+ createdByTitle: item.createdByTitle,
3977
4054
  createdAt: item.createdAt,
3978
4055
  updatedBy: item.updatedBy,
4056
+ updatedByTitle: item.updatedByTitle,
3979
4057
  updatedAt: item.updatedAt
3980
4058
  })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Group, { children: [
3981
4059
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
@@ -4669,8 +4747,10 @@ var ItemInstanceDetail = () => {
4669
4747
  children: instance.key
4670
4748
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetadataTooltip, {
4671
4749
  createdBy: instance.createdBy,
4750
+ createdByTitle: instance.createdByTitle,
4672
4751
  createdAt: instance.createdAt,
4673
4752
  updatedBy: instance.updatedBy,
4753
+ updatedByTitle: instance.updatedByTitle,
4674
4754
  updatedAt: instance.updatedAt
4675
4755
  })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Group, { children: [
4676
4756
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
@@ -5644,8 +5724,10 @@ var OrderDetail = () => {
5644
5724
  }),
5645
5725
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetadataTooltip, {
5646
5726
  createdBy: order.createdBy,
5727
+ createdByTitle: order.createdByTitle,
5647
5728
  createdAt: order.createdAt,
5648
5729
  updatedBy: order.updatedBy,
5730
+ updatedByTitle: order.updatedByTitle,
5649
5731
  updatedAt: order.updatedAt
5650
5732
  }),
5651
5733
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
@@ -5858,31 +5940,6 @@ var OrderList = () => {
5858
5940
  });
5859
5941
  };
5860
5942
  //#endregion
5861
- //#region src/components/WorkCenterAutocomplete.tsx
5862
- var WorkCenterAutocomplete = ({ value, onChange, ...rest }) => {
5863
- const [debouncedValue] = useDebouncedValue(value, 300);
5864
- const [options, setOptions] = (0, import_react.useState)([]);
5865
- const fetchOptions = (0, import_react.useCallback)(async (search) => {
5866
- try {
5867
- const params = new URLSearchParams();
5868
- params.set("pageSize", "10");
5869
- if (search) params.set("search", search);
5870
- setOptions((await api.get(`${apiEndpoints.workCenters}?${params}`)).items.map((wc) => wc.key));
5871
- } catch {
5872
- setOptions([]);
5873
- }
5874
- }, []);
5875
- (0, import_react.useEffect)(() => {
5876
- fetchOptions(debouncedValue);
5877
- }, [debouncedValue, fetchOptions]);
5878
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Autocomplete, {
5879
- data: options,
5880
- value,
5881
- onChange,
5882
- ...rest
5883
- });
5884
- };
5885
- //#endregion
5886
5943
  //#region src/pages/orders/revs/lists/DependencyList.tsx
5887
5944
  var DependencyList = ({ orderKey, revNo, opSeqNo, showTitle = true }) => {
5888
5945
  const [deps, setDeps] = (0, import_react.useState)(null);
@@ -6488,8 +6545,10 @@ var StepList = ({ orderKey, revNo, opSeqNo }) => {
6488
6545
  children: [
6489
6546
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetadataTooltip, {
6490
6547
  createdBy: step.createdBy,
6548
+ createdByTitle: step.createdByTitle,
6491
6549
  createdAt: step.createdAt,
6492
6550
  updatedBy: step.updatedBy,
6551
+ updatedByTitle: step.updatedByTitle,
6493
6552
  updatedAt: step.updatedAt
6494
6553
  }),
6495
6554
  hasAction(step._actions, "update") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
@@ -6687,8 +6746,10 @@ var OperationDetail = () => {
6687
6746
  }),
6688
6747
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetadataTooltip, {
6689
6748
  createdBy: operation.createdBy,
6749
+ createdByTitle: operation.createdByTitle,
6690
6750
  createdAt: operation.createdAt,
6691
6751
  updatedBy: operation.updatedBy,
6752
+ updatedByTitle: operation.updatedByTitle,
6692
6753
  updatedAt: operation.updatedAt
6693
6754
  })
6694
6755
  ]
@@ -6783,7 +6844,7 @@ var OperationDetail = () => {
6783
6844
  };
6784
6845
  //#endregion
6785
6846
  //#region src/components/lists/OperationSummaryTable.tsx
6786
- var OperationSummaryTable = ({ items, loading, linkBuilder }) => {
6847
+ var OperationSummaryTable = ({ items, loading, linkBuilder, showRunMetrics = false }) => {
6787
6848
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
6788
6849
  fw: 600,
6789
6850
  children: "OPERATIONS"
@@ -6802,9 +6863,8 @@ var OperationSummaryTable = ({ items, loading, linkBuilder }) => {
6802
6863
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Seq" }),
6803
6864
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Title" }),
6804
6865
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Prerequisites" }),
6805
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Steps" }),
6806
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Cost" }),
6807
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Tokens" })
6866
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Work Center" }),
6867
+ showRunMetrics && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Cost" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Tokens" })] })
6808
6868
  ] }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Tbody, { children: items.map((op) => {
6809
6869
  const opLink = linkBuilder(op.seqNo);
6810
6870
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Table.Tr, {
@@ -6854,25 +6914,24 @@ var OperationSummaryTable = ({ items, loading, linkBuilder }) => {
6854
6914
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
6855
6915
  to: opLink,
6856
6916
  style: cellLinkStyle,
6857
- children: op.stepCount ?? 0
6917
+ children: op.workCenterKey ?? "—"
6858
6918
  })
6859
6919
  }),
6860
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, {
6920
+ showRunMetrics && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, {
6861
6921
  style: { padding: 0 },
6862
6922
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
6863
6923
  to: opLink,
6864
6924
  style: cellLinkStyle,
6865
6925
  children: op.cost ? `$${op.cost.toFixed(2)}` : "—"
6866
6926
  })
6867
- }),
6868
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, {
6927
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, {
6869
6928
  style: { padding: 0 },
6870
6929
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
6871
6930
  to: opLink,
6872
6931
  style: cellLinkStyle,
6873
6932
  children: op.tokens ? formatTokens(op.tokens) : "—"
6874
6933
  })
6875
- })
6934
+ })] })
6876
6935
  ]
6877
6936
  }, op.id);
6878
6937
  }) })] })
@@ -6967,8 +7026,10 @@ var HeaderDetail = () => {
6967
7026
  children: "HEADER"
6968
7027
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetadataTooltip, {
6969
7028
  createdBy: revision.createdBy,
7029
+ createdByTitle: revision.createdByTitle,
6970
7030
  createdAt: revision.createdAt,
6971
7031
  updatedBy: revision.updatedBy,
7032
+ updatedByTitle: revision.updatedByTitle,
6972
7033
  updatedAt: revision.updatedAt
6973
7034
  })]
6974
7035
  }), canEdit && !editing && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
@@ -7752,7 +7813,7 @@ var RevisionLayout = () => {
7752
7813
  display: "flex",
7753
7814
  flexDirection: "column",
7754
7815
  overflowY: "auto",
7755
- padding: "0 var(--mantine-spacing-md)"
7816
+ padding: "0 var(--mantine-spacing-md) var(--mantine-spacing-xs)"
7756
7817
  },
7757
7818
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Group, {
7758
7819
  justify: "flex-end",
@@ -7942,8 +8003,10 @@ var HeaderRunDetail = () => {
7942
8003
  children: "HEADER"
7943
8004
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetadataTooltip, {
7944
8005
  createdBy: orderRun.createdBy,
8006
+ createdByTitle: orderRun.createdByTitle,
7945
8007
  createdAt: orderRun.createdAt,
7946
8008
  updatedBy: orderRun.updatedBy,
8009
+ updatedByTitle: orderRun.updatedByTitle,
7947
8010
  updatedAt: orderRun.updatedAt
7948
8011
  })]
7949
8012
  }), canEdit && !editing && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
@@ -8025,7 +8088,8 @@ var HeaderRunDetail = () => {
8025
8088
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OperationSummaryTable, {
8026
8089
  items: operations?.items ?? null,
8027
8090
  loading: opsLoading,
8028
- linkBuilder: (seqNo) => `/orders/${orderKey}/runs/${runNo}/ops/${seqNo}`
8091
+ linkBuilder: (seqNo) => `/orders/${orderKey}/runs/${runNo}/ops/${seqNo}`,
8092
+ showRunMetrics: true
8029
8093
  })
8030
8094
  ]
8031
8095
  })
@@ -8112,7 +8176,7 @@ var CommentList = ({ orderKey, runNo, seqNo, refreshKey, onCountChange }) => {
8112
8176
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
8113
8177
  size: "sm",
8114
8178
  fw: 600,
8115
- children: comment.createdBy
8179
+ children: formatUserLabel(comment.createdBy, comment.createdByTitle)
8116
8180
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
8117
8181
  color: TYPE_COLORS[comment.type] ?? "gray",
8118
8182
  variant: "light",
@@ -8252,7 +8316,7 @@ var LaborTicketList = ({ orderKey, runNo, seqNo, refreshKey, showTitle = true, o
8252
8316
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Tokens" }),
8253
8317
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, {})
8254
8318
  ] }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Tbody, { children: data.items.map((ticket) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Table.Tr, { children: [
8255
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, { children: ticket.username }),
8319
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, { children: formatUserLabel(ticket.username, ticket.userTitle) }),
8256
8320
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, { children: ticket.runId != null ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Anchor, {
8257
8321
  size: "sm",
8258
8322
  href: `/supervisor/agents/${ticket.username}/runs/${ticket.runId}-1`,
@@ -8451,7 +8515,7 @@ var StepRunList = ({ orderKey, runNo, seqNo, refreshKey, onStepUpdate, onCountCh
8451
8515
  c: "green",
8452
8516
  children: [
8453
8517
  "Completed by ",
8454
- step.updatedBy,
8518
+ formatUserLabel(step.updatedBy, step.updatedByTitle),
8455
8519
  " on",
8456
8520
  " ",
8457
8521
  new Date(step.updatedAt).toLocaleString()
@@ -8482,7 +8546,7 @@ var StepRunList = ({ orderKey, runNo, seqNo, refreshKey, onStepUpdate, onCountCh
8482
8546
  c: "green",
8483
8547
  children: [
8484
8548
  "Completed by ",
8485
- step.updatedBy,
8549
+ formatUserLabel(step.updatedBy, step.updatedByTitle),
8486
8550
  " on",
8487
8551
  " ",
8488
8552
  new Date(step.updatedAt).toLocaleString()
@@ -8744,8 +8808,10 @@ var OperationRunDetail = () => {
8744
8808
  }),
8745
8809
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetadataTooltip, {
8746
8810
  createdBy: opRun.createdBy,
8811
+ createdByTitle: opRun.createdByTitle,
8747
8812
  createdAt: opRun.createdAt,
8748
8813
  updatedBy: opRun.updatedBy,
8814
+ updatedByTitle: opRun.updatedByTitle,
8749
8815
  updatedAt: opRun.updatedAt
8750
8816
  }),
8751
8817
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
@@ -8759,7 +8825,11 @@ var OperationRunDetail = () => {
8759
8825
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
8760
8826
  size: "sm",
8761
8827
  c: "dimmed",
8762
- children: ["assigned to ", opRun.assignedTo]
8828
+ children: [
8829
+ "assigned to",
8830
+ " ",
8831
+ formatUserLabel(opRun.assignedTo, opRun.assignedToTitle)
8832
+ ]
8763
8833
  }), hasAction(opRun._actions, "assign") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ActionIcon, {
8764
8834
  size: "xs",
8765
8835
  variant: "subtle",
@@ -8898,8 +8968,9 @@ var OperationRunDetail = () => {
8898
8968
  c: color,
8899
8969
  children: [
8900
8970
  label,
8901
- " by ",
8902
- opRun.updatedBy,
8971
+ " by",
8972
+ " ",
8973
+ formatUserLabel(opRun.updatedBy, opRun.updatedByTitle),
8903
8974
  " on",
8904
8975
  " ",
8905
8976
  new Date(opRun.updatedAt).toLocaleString(),
@@ -9978,6 +10049,7 @@ var UserDetail = () => {
9978
10049
  const [loading, setLoading] = (0, import_react.useState)(true);
9979
10050
  const [editOpened, { open: openEdit, close: closeEdit }] = useDisclosure();
9980
10051
  const [editUsername, setEditUsername] = (0, import_react.useState)("");
10052
+ const [editTitle, setEditTitle] = (0, import_react.useState)("");
9981
10053
  const [saving, setSaving] = (0, import_react.useState)(false);
9982
10054
  const [editError, setEditError] = (0, import_react.useState)("");
9983
10055
  const [grantPerm, setGrantPerm] = (0, import_react.useState)(null);
@@ -10010,11 +10082,13 @@ var UserDetail = () => {
10010
10082
  }
10011
10083
  };
10012
10084
  const handleUpdate = async () => {
10013
- if (!routeUsername || !editUsername) return;
10085
+ if (!routeUsername || !editUsername || !user) return;
10014
10086
  setSaving(true);
10015
10087
  setEditError("");
10016
10088
  try {
10017
- await api.put(apiEndpoints.user(routeUsername), { username: editUsername });
10089
+ const body = { username: editUsername };
10090
+ if (titleEditable) body.title = editTitle;
10091
+ await api.put(apiEndpoints.user(routeUsername), body);
10018
10092
  closeEdit();
10019
10093
  if (editUsername !== routeUsername) navigate(`/users/${editUsername}`, { replace: true });
10020
10094
  else fetchUser();
@@ -10088,6 +10162,7 @@ var UserDetail = () => {
10088
10162
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: "User not found." })
10089
10163
  });
10090
10164
  const grantablePermissions = ErpPermissionEnum.options.filter((p) => !user.permissions?.some((up) => up.permission === p));
10165
+ const titleEditable = !user.isAgent || !supervisorAuth;
10091
10166
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Container, {
10092
10167
  size: "md",
10093
10168
  py: "xl",
@@ -10119,6 +10194,7 @@ var UserDetail = () => {
10119
10194
  hasAction(user._actions, "update") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
10120
10195
  onClick: () => {
10121
10196
  setEditUsername(user.username);
10197
+ setEditTitle(user.title);
10122
10198
  setEditError("");
10123
10199
  openEdit();
10124
10200
  },
@@ -10164,6 +10240,15 @@ var UserDetail = () => {
10164
10240
  ff: "monospace",
10165
10241
  children: user.username
10166
10242
  })] }),
10243
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Group, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
10244
+ fw: 600,
10245
+ w: 120,
10246
+ children: "Title:"
10247
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: user.title || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
10248
+ c: "dimmed",
10249
+ span: true,
10250
+ children: "—"
10251
+ }) })] }),
10167
10252
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Group, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
10168
10253
  fw: 600,
10169
10254
  w: 120,
@@ -10252,6 +10337,11 @@ var UserDetail = () => {
10252
10337
  value: editUsername,
10253
10338
  onChange: (e) => setEditUsername(e.currentTarget.value)
10254
10339
  }),
10340
+ titleEditable && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextInput, {
10341
+ label: "Title",
10342
+ value: editTitle,
10343
+ onChange: (e) => setEditTitle(e.currentTarget.value)
10344
+ }),
10255
10345
  editError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
10256
10346
  c: "red",
10257
10347
  size: "sm",
@@ -10441,6 +10531,7 @@ var UserList = () => {
10441
10531
  highlightOnHover: true,
10442
10532
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Thead, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Table.Tr, { children: [
10443
10533
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Username" }),
10534
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Title" }),
10444
10535
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Type" }),
10445
10536
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Permissions" }),
10446
10537
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Th, { children: "Created" })
@@ -10463,6 +10554,18 @@ var UserList = () => {
10463
10554
  })
10464
10555
  })
10465
10556
  }),
10557
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, {
10558
+ style: { padding: 0 },
10559
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
10560
+ to: `/users/${item.username}`,
10561
+ style: cellLinkStyle,
10562
+ children: item.title || /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
10563
+ c: "dimmed",
10564
+ span: true,
10565
+ children: "—"
10566
+ })
10567
+ })
10568
+ }),
10466
10569
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, {
10467
10570
  style: { padding: 0 },
10468
10571
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
@@ -10774,8 +10877,10 @@ var WorkCenterDetail = () => {
10774
10877
  children: wc.key
10775
10878
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MetadataTooltip, {
10776
10879
  createdBy: wc.createdBy,
10880
+ createdByTitle: wc.createdByTitle,
10777
10881
  createdAt: wc.createdAt,
10778
10882
  updatedBy: wc.updatedBy,
10883
+ updatedByTitle: wc.updatedByTitle,
10779
10884
  updatedAt: wc.updatedAt
10780
10885
  })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Group, { children: [
10781
10886
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button, {
@@ -10836,7 +10941,7 @@ var WorkCenterDetail = () => {
10836
10941
  ] }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Tbody, { children: wc.userAssignments.map((a) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Table.Tr, { children: [
10837
10942
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
10838
10943
  size: "sm",
10839
- children: a.username
10944
+ children: formatUserLabel(a.username, a.userTitle)
10840
10945
  }) }),
10841
10946
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
10842
10947
  size: "sm",
@@ -10844,7 +10949,7 @@ var WorkCenterDetail = () => {
10844
10949
  }) }),
10845
10950
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
10846
10951
  size: "sm",
10847
- children: a.createdBy ?? "—"
10952
+ children: a.createdBy ? formatUserLabel(a.createdBy, a.createdByTitle) : "—"
10848
10953
  }) }),
10849
10954
  canAssign && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Table.Td, { children: hasAction(a._actions, "remove") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ActionIcon, {
10850
10955
  color: "red",