@hotmeshio/long-tail 0.30.4 → 0.31.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.
- package/build/api/escalations/index.d.ts +1 -0
- package/build/api/escalations/index.js +5 -2
- package/build/api/escalations/roster-action.d.ts +11 -0
- package/build/api/escalations/roster-action.js +47 -30
- package/build/api/escalations/roster-scan.d.ts +26 -0
- package/build/api/escalations/roster-scan.js +114 -0
- package/build/api/labels/errors.d.ts +3 -0
- package/build/api/labels/errors.js +15 -0
- package/build/api/labels/index.d.ts +2 -0
- package/build/api/labels/index.js +17 -0
- package/build/api/labels/issue.d.ts +54 -0
- package/build/api/labels/issue.js +144 -0
- package/build/api/labels/templates.d.ts +29 -0
- package/build/api/labels/templates.js +98 -0
- package/build/api/scan-codes/context.d.ts +9 -1
- package/build/api/scan-codes/context.js +16 -1
- package/build/api/scan-codes/execute.js +6 -1
- package/build/api/scan-codes/fill-labels.d.ts +8 -0
- package/build/api/scan-codes/fill-labels.js +23 -2
- package/build/api/scan-codes/hold.js +2 -0
- package/build/api/scan-codes/located.d.ts +10 -0
- package/build/api/scan-codes/located.js +74 -0
- package/build/api/scan-codes/open.d.ts +9 -0
- package/build/api/scan-codes/open.js +99 -0
- package/build/api/scan-codes/present.js +1 -0
- package/build/api/scan-codes/verb-fill.js +1 -1
- package/build/api/users.d.ts +8 -4
- package/build/api/users.js +51 -13
- package/build/index.d.ts +1 -0
- package/build/index.js +4 -2
- package/build/lib/db/schemas/044_label_sheets.sql +65 -0
- package/build/lib/db/schemas/045_label_job_delivery.sql +14 -0
- package/build/lib/labels/transports.d.ts +23 -0
- package/build/lib/labels/transports.js +39 -0
- package/build/modules/auth.d.ts +2 -0
- package/build/modules/auth.js +3 -1
- package/build/modules/capabilities.d.ts +5 -1
- package/build/modules/capabilities.js +38 -8
- package/build/modules/config.d.ts +10 -0
- package/build/modules/config.js +10 -0
- package/build/routes/escalations/resolve.js +18 -0
- package/build/routes/index.js +2 -0
- package/build/routes/labels.d.ts +2 -0
- package/build/routes/labels.js +135 -0
- package/build/routes/users.js +1 -1
- package/build/services/labels/content.d.ts +13 -0
- package/build/services/labels/content.js +81 -0
- package/build/services/labels/errors.d.ts +5 -0
- package/build/services/labels/errors.js +12 -0
- package/build/services/labels/index.d.ts +11 -0
- package/build/services/labels/index.js +52 -0
- package/build/services/labels/issue.d.ts +38 -0
- package/build/services/labels/issue.js +181 -0
- package/build/services/labels/jobs.d.ts +37 -0
- package/build/services/labels/jobs.js +75 -0
- package/build/services/labels/media.d.ts +11 -0
- package/build/services/labels/media.js +44 -0
- package/build/services/labels/reissue.d.ts +13 -0
- package/build/services/labels/reissue.js +65 -0
- package/build/services/labels/render-pdf.d.ts +11 -0
- package/build/services/labels/render-pdf.js +138 -0
- package/build/services/labels/targets.d.ts +18 -0
- package/build/services/labels/targets.js +216 -0
- package/build/services/labels/templates/index.d.ts +3 -0
- package/build/services/labels/templates/index.js +18 -0
- package/build/services/labels/templates/read.d.ts +4 -0
- package/build/services/labels/templates/read.js +36 -0
- package/build/services/labels/templates/sql.d.ts +8 -0
- package/build/services/labels/templates/sql.js +50 -0
- package/build/services/labels/templates/validate.d.ts +19 -0
- package/build/services/labels/templates/validate.js +93 -0
- package/build/services/labels/templates/write.d.ts +16 -0
- package/build/services/labels/templates/write.js +75 -0
- package/build/services/labels/token.d.ts +9 -0
- package/build/services/labels/token.js +28 -0
- package/build/services/labels/verify.d.ts +4 -0
- package/build/services/labels/verify.js +38 -0
- package/build/services/role/index.d.ts +2 -0
- package/build/services/role/index.js +7 -0
- package/build/services/role/scan-done.js +4 -1
- package/build/services/role/sql.d.ts +1 -0
- package/build/services/role/sql.js +3 -1
- package/build/services/role/types.d.ts +2 -0
- package/build/services/scan-code/index.d.ts +1 -1
- package/build/services/scan-code/index.js +2 -1
- package/build/services/scan-code/parse.d.ts +5 -1
- package/build/services/scan-code/parse.js +8 -2
- package/build/services/scan-code/validate-station.d.ts +13 -0
- package/build/services/scan-code/validate-station.js +81 -0
- package/build/services/scan-code/validate-subject.js +33 -6
- package/build/services/scan-code/validate.d.ts +3 -0
- package/build/services/scan-code/validate.js +22 -18
- package/build/services/user/crud.d.ts +13 -1
- package/build/services/user/crud.js +42 -11
- package/build/services/user/index.d.ts +3 -2
- package/build/services/user/index.js +7 -1
- package/build/services/user/redact.d.ts +17 -0
- package/build/services/user/redact.js +32 -0
- package/build/services/user/sql.d.ts +8 -15
- package/build/services/user/sql.js +27 -3
- package/build/services/user/types.d.ts +21 -1
- package/build/shared/labels/compose.d.ts +12 -0
- package/build/shared/labels/compose.js +43 -0
- package/build/shared/labels/index.d.ts +9 -0
- package/build/shared/labels/index.js +54 -0
- package/build/shared/labels/label-content.d.ts +17 -0
- package/build/shared/labels/label-content.js +137 -0
- package/build/shared/labels/layout.d.ts +23 -0
- package/build/shared/labels/layout.js +81 -0
- package/build/shared/labels/media.d.ts +22 -0
- package/build/shared/labels/media.js +116 -0
- package/build/shared/labels/render-svg.d.ts +10 -0
- package/build/shared/labels/render-svg.js +58 -0
- package/build/shared/labels/render-zpl.d.ts +9 -0
- package/build/shared/labels/render-zpl.js +63 -0
- package/build/shared/labels/symbol.d.ts +18 -0
- package/build/shared/labels/symbol.js +74 -0
- package/build/shared/labels/tokens.d.ts +18 -0
- package/build/shared/labels/tokens.js +43 -0
- package/build/shared/labels/types.d.ts +105 -0
- package/build/shared/labels/types.js +11 -0
- package/build/start/adapters.js +16 -0
- package/build/start/workers.js +18 -2
- package/build/system/mcp-servers/admin/index.js +2 -0
- package/build/system/mcp-servers/admin/labels-schemas.d.ts +192 -0
- package/build/system/mcp-servers/admin/labels-schemas.js +46 -0
- package/build/system/mcp-servers/admin/labels.d.ts +9 -0
- package/build/system/mcp-servers/admin/labels.js +101 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +491 -24
- package/build/system/mcp-servers/admin/schemas.js +32 -4
- package/build/system/mcp-servers/admin/users.js +1 -1
- package/build/system/seed/tool-manifests-admin.js +5 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/capability.d.ts +2 -1
- package/build/types/index.d.ts +3 -2
- package/build/types/labels/index.d.ts +4 -0
- package/build/types/labels/index.js +2 -0
- package/build/types/labels/job.d.ts +51 -0
- package/build/types/labels/job.js +2 -0
- package/build/types/labels/source.d.ts +44 -0
- package/build/types/labels/source.js +2 -0
- package/build/types/labels/template.d.ts +46 -0
- package/build/types/labels/template.js +2 -0
- package/build/types/labels/transport.d.ts +24 -0
- package/build/types/labels/transport.js +2 -0
- package/build/types/scan-choice.d.ts +2 -4
- package/build/types/scan-code/constants.d.ts +1 -0
- package/build/types/scan-code/constants.js +1 -0
- package/build/types/scan-code/response.d.ts +22 -4
- package/build/types/scan-code/rule.d.ts +66 -3
- package/build/types/startup.d.ts +37 -0
- package/build/types/user.d.ts +2 -0
- package/dashboard/dist/assets/{AdminDashboard-VQ1fhhJP.js → AdminDashboard-BafKaq50.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-VQ1fhhJP.js.map → AdminDashboard-BafKaq50.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-BOe_W2Ij.js → AgentConfigPage-CFHf31DT.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-BOe_W2Ij.js.map → AgentConfigPage-CFHf31DT.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-5ov5D9V2.js → AgentDetailPage-CEvz5rJr.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-5ov5D9V2.js.map → AgentDetailPage-CEvz5rJr.js.map} +1 -1
- package/dashboard/dist/assets/{AgentsPage-DDFMKHhI.js → AgentsPage-DjQaio0O.js} +2 -2
- package/dashboard/dist/assets/{AgentsPage-DDFMKHhI.js.map → AgentsPage-DjQaio0O.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-UB03VTJx.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-UB03VTJx.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-Dqpo36dM.js → BotPicker-C7MNWOF7.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-Dqpo36dM.js.map → BotPicker-C7MNWOF7.js.map} +1 -1
- package/dashboard/dist/assets/BulkAssignModal-h5fX-_cV.js +2 -0
- package/dashboard/dist/assets/{BulkAssignModal-CmLVxkz-.js.map → BulkAssignModal-h5fX-_cV.js.map} +1 -1
- package/dashboard/dist/assets/{CapabilitiesPage-Dfkip6_b.js → CapabilitiesPage-BIzDl-ZT.js} +2 -2
- package/dashboard/dist/assets/{CapabilitiesPage-Dfkip6_b.js.map → CapabilitiesPage-BIzDl-ZT.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-CYNYMYSa.js → CollapsibleSection-B5TivtEg.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-CYNYMYSa.js.map → CollapsibleSection-B5TivtEg.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-CpJNP-8w.js → ConfirmDeleteModal-CB4nKePb.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-CpJNP-8w.js.map → ConfirmDeleteModal-CB4nKePb.js.map} +1 -1
- package/dashboard/dist/assets/{ConnectedAppsPage-DXIp2Dpl.js → ConnectedAppsPage-B3S5gVWw.js} +2 -2
- package/dashboard/dist/assets/{ConnectedAppsPage-DXIp2Dpl.js.map → ConnectedAppsPage-B3S5gVWw.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-CuPY7zkb.js → CountdownTimer-BHVIq3kA.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-CuPY7zkb.js.map → CountdownTimer-BHVIq3kA.js.map} +1 -1
- package/dashboard/dist/assets/CredentialConfirmModal-w0AGmCIe.js +2 -0
- package/dashboard/dist/assets/CredentialConfirmModal-w0AGmCIe.js.map +1 -0
- package/dashboard/dist/assets/{CredentialsPage-CtrnkHcj.js → CredentialsPage-BtCGBJrT.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CtrnkHcj.js.map → CredentialsPage-BtCGBJrT.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-DVjTw5Ri.js → CronLabel-BG1rZK-5.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-DVjTw5Ri.js.map → CronLabel-BG1rZK-5.js.map} +1 -1
- package/dashboard/dist/assets/{DropZone-DefYTYQy.js → DropZone-D8ZVdEb5.js} +2 -2
- package/dashboard/dist/assets/{DropZone-DefYTYQy.js.map → DropZone-D8ZVdEb5.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-gY_mGMTF.js → ElapsedCell-l4m8Yvfv.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-gY_mGMTF.js.map → ElapsedCell-l4m8Yvfv.js.map} +1 -1
- package/dashboard/dist/assets/{EntityTimelinePanel-DJN_ZEQa.js → EntityTimelinePanel-BOHlIaxF.js} +2 -2
- package/dashboard/dist/assets/{EntityTimelinePanel-DJN_ZEQa.js.map → EntityTimelinePanel-BOHlIaxF.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-A4KpTdJA.js → EscalationListSchemaPage-BotlwlX3.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-A4KpTdJA.js.map → EscalationListSchemaPage-BotlwlX3.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationSchemaPage-nfCn42hT.js → EscalationSchemaPage-CfZSVOSD.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-nfCn42hT.js.map → EscalationSchemaPage-CfZSVOSD.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTimeline-CLvSr1SD.js → EscalationTimeline-CCKpuRBU.js} +2 -2
- package/dashboard/dist/assets/{EscalationTimeline-CLvSr1SD.js.map → EscalationTimeline-CCKpuRBU.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationTitleSelect-CT7mYHkb.js → EscalationTitleSelect-cpTzPHiW.js} +2 -2
- package/dashboard/dist/assets/{EscalationTitleSelect-CT7mYHkb.js.map → EscalationTitleSelect-cpTzPHiW.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationsOverview-CKaGRh-E.js → EscalationsOverview-DS-nK0qV.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-CKaGRh-E.js.map → EscalationsOverview-DS-nK0qV.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-2ywJsOLy.js → EventTable-UfebhJf0.js} +2 -2
- package/dashboard/dist/assets/{EventTable-2ywJsOLy.js.map → EventTable-UfebhJf0.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-Dy0b7wwf.js → FilterBar-newA5l-X.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-Dy0b7wwf.js.map → FilterBar-newA5l-X.js.map} +1 -1
- package/dashboard/dist/assets/{GraphInvokePage-yOVpraAy.js → GraphInvokePage-6SCDyQcK.js} +2 -2
- package/dashboard/dist/assets/{GraphInvokePage-yOVpraAy.js.map → GraphInvokePage-6SCDyQcK.js.map} +1 -1
- package/dashboard/dist/assets/HomePage-BEc-XdKj.js +2 -0
- package/dashboard/dist/assets/{HomePage-67xXjKjN.js.map → HomePage-BEc-XdKj.js.map} +1 -1
- package/dashboard/dist/assets/LabelJobsPage-BO50zXT5.js +2 -0
- package/dashboard/dist/assets/LabelJobsPage-BO50zXT5.js.map +1 -0
- package/dashboard/dist/assets/{LinePage-CMsYtukW.js → LinePage-NYxJQ-ex.js} +3 -3
- package/dashboard/dist/assets/{LinePage-CMsYtukW.js.map → LinePage-NYxJQ-ex.js.map} +1 -1
- package/dashboard/dist/assets/{LinesPage-pwL46mOS.js → LinesPage-RbWTaQRh.js} +3 -3
- package/dashboard/dist/assets/{LinesPage-pwL46mOS.js.map → LinesPage-RbWTaQRh.js.map} +1 -1
- package/dashboard/dist/assets/{ListToolbar-CJmvGy2B.js → ListToolbar-B-E9-toh.js} +2 -2
- package/dashboard/dist/assets/{ListToolbar-CJmvGy2B.js.map → ListToolbar-B-E9-toh.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-DA9LLvNG.js → McpOverview-Shcf9QhZ.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-DA9LLvNG.js.map → McpOverview-Shcf9QhZ.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-N7qLmfE8.js → McpQueryDetailPage-D8kmjy2v.js} +3 -3
- package/dashboard/dist/assets/{McpQueryDetailPage-N7qLmfE8.js.map → McpQueryDetailPage-D8kmjy2v.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryPage-CpsP3w7x.js → McpQueryPage-ck-o5m8A.js} +2 -2
- package/dashboard/dist/assets/{McpQueryPage-CpsP3w7x.js.map → McpQueryPage-ck-o5m8A.js.map} +1 -1
- package/dashboard/dist/assets/McpRunDetailPage-BJKkM9-3.js +2 -0
- package/dashboard/dist/assets/{McpRunDetailPage-qHRQ1pEY.js.map → McpRunDetailPage-BJKkM9-3.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunsPage-BRDDYpTM.js → McpRunsPage-DqhHfD5G.js} +2 -2
- package/dashboard/dist/assets/{McpRunsPage-BRDDYpTM.js.map → McpRunsPage-DqhHfD5G.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-CeSfHH-j.js → NamespacePill--uIaGtrN.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-CeSfHH-j.js.map → NamespacePill--uIaGtrN.js.map} +1 -1
- package/dashboard/dist/assets/{OperationsPage-zUaab-CL.js → OperationsPage-D6B9Vv__.js} +3 -3
- package/dashboard/dist/assets/{OperationsPage-zUaab-CL.js.map → OperationsPage-D6B9Vv__.js.map} +1 -1
- package/dashboard/dist/assets/OperatorDashboard-CIH1cxjQ.js +2 -0
- package/dashboard/dist/assets/{OperatorDashboard-el5BquXN.js.map → OperatorDashboard-CIH1cxjQ.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-DiGWAQlR.js → PageHeader-DClJ33fV.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-DiGWAQlR.js.map → PageHeader-DClJ33fV.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-DwnKQ06j.js → PageHeaderWithStats-C-TrbKQL.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-DwnKQ06j.js.map → PageHeaderWithStats-C-TrbKQL.js.map} +1 -1
- package/dashboard/dist/assets/PersonaDetailPage-DjvfyIph.js +2 -0
- package/dashboard/dist/assets/{PersonaDetailPage-B_tb8gfl.js.map → PersonaDetailPage-DjvfyIph.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-BPI7mqM8.js → PersonasPage-D7ryA8Vc.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-BPI7mqM8.js.map → PersonasPage-D7ryA8Vc.js.map} +1 -1
- package/dashboard/dist/assets/{PortalPage-e_rBb1do.js → PortalPage-D3ybr0mo.js} +2 -2
- package/dashboard/dist/assets/{PortalPage-e_rBb1do.js.map → PortalPage-D3ybr0mo.js.map} +1 -1
- package/dashboard/dist/assets/PrintLabelsPanel-D0HF5x8b.js +2 -0
- package/dashboard/dist/assets/PrintLabelsPanel-D0HF5x8b.js.map +1 -0
- package/dashboard/dist/assets/{ProcessDetailPage-D35RX1bB.js → ProcessDetailPage-0xS9EdHe.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-D35RX1bB.js.map → ProcessDetailPage-0xS9EdHe.js.map} +1 -1
- package/dashboard/dist/assets/{ProcessesListPage-CT81miI5.js → ProcessesListPage-93SMj1Fd.js} +2 -2
- package/dashboard/dist/assets/{ProcessesListPage-CT81miI5.js.map → ProcessesListPage-93SMj1Fd.js.map} +1 -1
- package/dashboard/dist/assets/{ResolverForm-BxJkoKAO.js → ResolverForm-DfogHDzl.js} +5 -5
- package/dashboard/dist/assets/{ResolverForm-BxJkoKAO.js.map → ResolverForm-DfogHDzl.js.map} +1 -1
- package/dashboard/dist/assets/RoleDetailPage-DlUOJWSB.js +8 -0
- package/dashboard/dist/assets/{RoleDetailPage-DtU7vsJm.js.map → RoleDetailPage-DlUOJWSB.js.map} +1 -1
- package/dashboard/dist/assets/{RolePill-D3hkAdKf.js → RolePill-BjD1Qw5y.js} +2 -2
- package/dashboard/dist/assets/{RolePill-D3hkAdKf.js.map → RolePill-BjD1Qw5y.js.map} +1 -1
- package/dashboard/dist/assets/RolesPage-DqhHSvaw.js +2 -0
- package/dashboard/dist/assets/{RolesPage-BE7RWt9q.js.map → RolesPage-DqhHSvaw.js.map} +1 -1
- package/dashboard/dist/assets/{RosterWidget-BJMx0a8Z.js → RosterWidget-BrIq61HR.js} +2 -2
- package/dashboard/dist/assets/RosterWidget-BrIq61HR.js.map +1 -0
- package/dashboard/dist/assets/RunAsSelector-D6zQrCNr.js +2 -0
- package/dashboard/dist/assets/{RunAsSelector-Co6s9bqA.js.map → RunAsSelector-D6zQrCNr.js.map} +1 -1
- package/dashboard/dist/assets/ScanCodesPage-B2S9DR2f.js +2 -0
- package/dashboard/dist/assets/{ScanCodesPage-C2TETaj5.js.map → ScanCodesPage-B2S9DR2f.js.map} +1 -1
- package/dashboard/dist/assets/ScanSchemeDetailPage-gpxKN-pL.js +5 -0
- package/dashboard/dist/assets/ScanSchemeDetailPage-gpxKN-pL.js.map +1 -0
- package/dashboard/dist/assets/ScanStationPage-B-UTgXsG.js +2 -0
- package/dashboard/dist/assets/ScanStationPage-B-UTgXsG.js.map +1 -0
- package/dashboard/dist/assets/{SchemeMatchFields-9H7SmbED.js → SchemeMatchFields-BK24aa7K.js} +2 -2
- package/dashboard/dist/assets/{SchemeMatchFields-9H7SmbED.js.map → SchemeMatchFields-BK24aa7K.js.map} +1 -1
- package/dashboard/dist/assets/{ScopeBadge-DGz79rmG.js → ScopeBadge-ofLQ6HW-.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-DGz79rmG.js.map → ScopeBadge-ofLQ6HW-.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-miUdVAKw.js → StickyPagination-CgVv7vc_.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-miUdVAKw.js.map → StickyPagination-CgVv7vc_.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-D5Rk7pn7.js → StreamMessageDetail-B9sxDVw4.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-D5Rk7pn7.js.map → StreamMessageDetail-B9sxDVw4.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-B1QY1ZzH.js → SwimlaneTimeline-DQc0CYSL.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-B1QY1ZzH.js.map → SwimlaneTimeline-DQc0CYSL.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-DaIdhv3h.js → TagInput-47qVYzke.js} +2 -2
- package/dashboard/dist/assets/{TagInput-DaIdhv3h.js.map → TagInput-47qVYzke.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-DKUM37o8.js → TaskDetailPage-D6VOsA1f.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-DKUM37o8.js.map → TaskDetailPage-D6VOsA1f.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-sUA1nZe-.js → TaskQueuePill-C5KmdXAl.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-sUA1nZe-.js.map → TaskQueuePill-C5KmdXAl.js.map} +1 -1
- package/dashboard/dist/assets/{TasksListPage-CUulwvm-.js → TasksListPage-DG8hvO8G.js} +2 -2
- package/dashboard/dist/assets/{TasksListPage-CUulwvm-.js.map → TasksListPage-DG8hvO8G.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-CHTelacB.js → TimeAgo-CL02EhFi.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-CHTelacB.js.map → TimeAgo-CL02EhFi.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-NanLWLKo.js → TimestampCell-BE7oKVJg.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-NanLWLKo.js.map → TimestampCell-BE7oKVJg.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-CpBAFdEX.js → ToolPill-Cp9Drk1s.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-CpBAFdEX.js.map → ToolPill-Cp9Drk1s.js.map} +1 -1
- package/dashboard/dist/assets/{ToolTestPanel-CF1CHzgz.js → ToolTestPanel-CRecLh6S.js} +2 -2
- package/dashboard/dist/assets/{ToolTestPanel-CF1CHzgz.js.map → ToolTestPanel-CRecLh6S.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-CGO8XV_a.js → TopicDetailPage-QzkinTfN.js} +3 -3
- package/dashboard/dist/assets/{TopicDetailPage-CGO8XV_a.js.map → TopicDetailPage-QzkinTfN.js.map} +1 -1
- package/dashboard/dist/assets/{TopicsPage-Bt8gOKYr.js → TopicsPage-D8dW6J65.js} +2 -2
- package/dashboard/dist/assets/{TopicsPage-Bt8gOKYr.js.map → TopicsPage-D8dW6J65.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-DKXnK7DD.js → UserName-Dw3R_zrl.js} +2 -2
- package/dashboard/dist/assets/{UserName-DKXnK7DD.js.map → UserName-Dw3R_zrl.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-BTocv8or.js +2 -0
- package/dashboard/dist/assets/{WorkflowExecutionPage-Crf7AIFc.js.map → WorkflowExecutionPage-BTocv8or.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill-CKHip3hH.js → WorkflowPill-BiLYq__w.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill-CKHip3hH.js.map → WorkflowPill-BiLYq__w.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowsDashboard-CIPEt3et.js +2 -0
- package/dashboard/dist/assets/{WorkflowsDashboard--isjt06C.js.map → WorkflowsDashboard-CIPEt3et.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-D7Oqf4-V.js → WorkflowsOverview-Bj4MJIE-.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-D7Oqf4-V.js.map → WorkflowsOverview-Bj4MJIE-.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-B0wxgrGP.js → YamlWorkflowDetailPage-DMEk5k9-.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-B0wxgrGP.js.map → YamlWorkflowDetailPage-DMEk5k9-.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-BVdLnm6K.js → YamlWorkflowsPage-F2yyyoiB.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-BVdLnm6K.js.map → YamlWorkflowsPage-F2yyyoiB.js.map} +1 -1
- package/dashboard/dist/assets/{agents-CHjbjHXA.js → agents-mSgxEPpI.js} +2 -2
- package/dashboard/dist/assets/{agents-CHjbjHXA.js.map → agents-mSgxEPpI.js.map} +1 -1
- package/dashboard/dist/assets/{bots-WrUhEPWs.js → bots-p4Hp0CV6.js} +2 -2
- package/dashboard/dist/assets/{bots-WrUhEPWs.js.map → bots-p4Hp0CV6.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-CunMmkj8.js → capabilities-D_-I_SXR.js} +2 -2
- package/dashboard/dist/assets/{capabilities-CunMmkj8.js.map → capabilities-D_-I_SXR.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-D6IZIZoh.js → controlplane-DjdoQnRU.js} +2 -2
- package/dashboard/dist/assets/{controlplane-D6IZIZoh.js.map → controlplane-DjdoQnRU.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-columns-Bvo6JI4Z.js → escalation-columns-R_IEVQjQ.js} +2 -2
- package/dashboard/dist/assets/{escalation-columns-Bvo6JI4Z.js.map → escalation-columns-R_IEVQjQ.js.map} +1 -1
- package/dashboard/dist/assets/{escalation-items-DFGRwo49.js → escalation-items-BGZlJMpk.js} +2 -2
- package/dashboard/dist/assets/{escalation-items-DFGRwo49.js.map → escalation-items-BGZlJMpk.js.map} +1 -1
- package/dashboard/dist/assets/{index-OuKQ_0eB.js → index-BEMdD58x.js} +2 -2
- package/dashboard/dist/assets/{index-OuKQ_0eB.js.map → index-BEMdD58x.js.map} +1 -1
- package/dashboard/dist/assets/index-BUmz0NMg.css +1 -0
- package/dashboard/dist/assets/{index-C7EIu1mG.js → index-BuCEhhnl.js} +2 -2
- package/dashboard/dist/assets/{index-C7EIu1mG.js.map → index-BuCEhhnl.js.map} +1 -1
- package/dashboard/dist/assets/{index-Bo8QU31k.js → index-BxbQmeqh.js} +2 -2
- package/dashboard/dist/assets/{index-Bo8QU31k.js.map → index-BxbQmeqh.js.map} +1 -1
- package/dashboard/dist/assets/index-C5osluV3.js +2 -0
- package/dashboard/dist/assets/{index-DRK7M1_9.js.map → index-C5osluV3.js.map} +1 -1
- package/dashboard/dist/assets/{index-ygxyAKcc.js → index-C_dAJUzh.js} +27 -27
- package/dashboard/dist/assets/index-C_dAJUzh.js.map +1 -0
- package/dashboard/dist/assets/{index-DRw0FXdX.js → index-D-FYj9jT.js} +2 -2
- package/dashboard/dist/assets/{index-DRw0FXdX.js.map → index-D-FYj9jT.js.map} +1 -1
- package/dashboard/dist/assets/{index-B8qrHwp9.js → index-D6K_IgCz.js} +2 -2
- package/dashboard/dist/assets/{index-B8qrHwp9.js.map → index-D6K_IgCz.js.map} +1 -1
- package/dashboard/dist/assets/index-D7L_VoBD.js +2 -0
- package/dashboard/dist/assets/index-D7L_VoBD.js.map +1 -0
- package/dashboard/dist/assets/{index-BZFSXEkr.js → index-D9RAN9sA.js} +2 -2
- package/dashboard/dist/assets/{index-BZFSXEkr.js.map → index-D9RAN9sA.js.map} +1 -1
- package/dashboard/dist/assets/{index-DCJ483vt.js → index-DUYAGxwc.js} +2 -2
- package/dashboard/dist/assets/{index-DCJ483vt.js.map → index-DUYAGxwc.js.map} +1 -1
- package/dashboard/dist/assets/{index-boT612Jo.js → index-Dk2KKo0z.js} +2 -2
- package/dashboard/dist/assets/{index-boT612Jo.js.map → index-Dk2KKo0z.js.map} +1 -1
- package/dashboard/dist/assets/{index-CpCchhQv.js → index-DlJkZ12b.js} +2 -2
- package/dashboard/dist/assets/{index-CpCchhQv.js.map → index-DlJkZ12b.js.map} +1 -1
- package/dashboard/dist/assets/index-FiNThtNU.js +3 -0
- package/dashboard/dist/assets/index-FiNThtNU.js.map +1 -0
- package/dashboard/dist/assets/{knowledge-BubJBTwg.js → knowledge-DSsPTqkK.js} +2 -2
- package/dashboard/dist/assets/{knowledge-BubJBTwg.js.map → knowledge-DSsPTqkK.js.map} +1 -1
- package/dashboard/dist/assets/{machines-DSm5NFgs.js → machines-DSgGtqqr.js} +2 -2
- package/dashboard/dist/assets/{machines-DSm5NFgs.js.map → machines-DSgGtqqr.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-D6MckqOV.js → mcp-Cg-_uLw8.js} +2 -2
- package/dashboard/dist/assets/{mcp-D6MckqOV.js.map → mcp-Cg-_uLw8.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-VyCdOag6.js → mcp-query-DQombEK_.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-VyCdOag6.js.map → mcp-query-DQombEK_.js.map} +1 -1
- package/dashboard/dist/assets/{personas-CyJc10xe.js → personas-DYrcoVBu.js} +2 -2
- package/dashboard/dist/assets/{personas-CyJc10xe.js.map → personas-DYrcoVBu.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-B2inDtx3.js → pipelines-wdb4xsey.js} +2 -2
- package/dashboard/dist/assets/{pipelines-B2inDtx3.js.map → pipelines-wdb4xsey.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-DOP4d3M6.js → tasks-Bil7gvm9.js} +2 -2
- package/dashboard/dist/assets/{tasks-DOP4d3M6.js.map → tasks-Bil7gvm9.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CNOjSWpX.js → topics-wBqaVhRR.js} +2 -2
- package/dashboard/dist/assets/{topics-CNOjSWpX.js.map → topics-wBqaVhRR.js.map} +1 -1
- package/dashboard/dist/assets/{useDebouncedValue-CgO0TGMd.js → useDebouncedValue-CwrY8TpV.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-CgO0TGMd.js.map → useDebouncedValue-CwrY8TpV.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-BWHvUKtK.js → useNamespace-Sod_xApz.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-BWHvUKtK.js.map → useNamespace-Sod_xApz.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-BZQ__ZGD.js → useYamlActivityEvents-CKLInV3C.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-BZQ__ZGD.js.map → useYamlActivityEvents-CKLInV3C.js.map} +1 -1
- package/dashboard/dist/assets/{validate-CAin6WM_.js → validate-CYhW1xMJ.js} +2 -2
- package/dashboard/dist/assets/{validate-CAin6WM_.js.map → validate-CYhW1xMJ.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-en0_uSRD.js → vendor-icons-ed7mYQw4.js} +2 -2
- package/dashboard/dist/assets/{vendor-icons-en0_uSRD.js.map → vendor-icons-ed7mYQw4.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-Dyln3od-.js → yaml-workflows-C20qHo3L.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-Dyln3od-.js.map → yaml-workflows-C20qHo3L.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/api/http/escalations.md +15 -0
- package/docs/api/http/labels.md +115 -0
- package/docs/api/http/users.md +2 -0
- package/docs/api/mcp/admin.md +76 -1
- package/docs/code-owned-configuration.md +1 -1
- package/docs/dashboard.md +2 -2
- package/docs/hitl/x-lt-roster.md +2 -0
- package/docs/hitl/x-lt-scan.md +12 -0
- package/docs/iam.md +12 -0
- package/docs/label-sheets.md +267 -0
- package/docs/scan-codes.md +93 -9
- package/package.json +4 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-GFn8Sgg1.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-GFn8Sgg1.js.map +0 -1
- package/dashboard/dist/assets/BulkAssignModal-CmLVxkz-.js +0 -2
- package/dashboard/dist/assets/HomePage-67xXjKjN.js +0 -2
- package/dashboard/dist/assets/McpRunDetailPage-qHRQ1pEY.js +0 -2
- package/dashboard/dist/assets/OperatorDashboard-el5BquXN.js +0 -2
- package/dashboard/dist/assets/PersonaDetailPage-B_tb8gfl.js +0 -2
- package/dashboard/dist/assets/RoleDetailPage-DtU7vsJm.js +0 -8
- package/dashboard/dist/assets/RolesPage-BE7RWt9q.js +0 -2
- package/dashboard/dist/assets/RosterWidget-BJMx0a8Z.js.map +0 -1
- package/dashboard/dist/assets/RunAsSelector-Co6s9bqA.js +0 -2
- package/dashboard/dist/assets/ScanCodesPage-C2TETaj5.js +0 -2
- package/dashboard/dist/assets/ScanSchemeDetailPage-C2UgU8l-.js +0 -5
- package/dashboard/dist/assets/ScanSchemeDetailPage-C2UgU8l-.js.map +0 -1
- package/dashboard/dist/assets/ScanStationPage-nWYz-OD3.js +0 -2
- package/dashboard/dist/assets/ScanStationPage-nWYz-OD3.js.map +0 -1
- package/dashboard/dist/assets/WorkflowExecutionPage-Crf7AIFc.js +0 -2
- package/dashboard/dist/assets/WorkflowsDashboard--isjt06C.js +0 -2
- package/dashboard/dist/assets/index-B95LbYhW.js +0 -2
- package/dashboard/dist/assets/index-B95LbYhW.js.map +0 -1
- package/dashboard/dist/assets/index-BmzscsXK.css +0 -1
- package/dashboard/dist/assets/index-DRK7M1_9.js +0 -2
- package/dashboard/dist/assets/index-P-DlgAWj.js +0 -3
- package/dashboard/dist/assets/index-P-DlgAWj.js.map +0 -1
- package/dashboard/dist/assets/index-ygxyAKcc.js.map +0 -1
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# Label Sheets
|
|
2
|
+
|
|
3
|
+
Every physical thing a floor acts on carries a printed scan code: locations,
|
|
4
|
+
containers, stations, machines, and the badges people scan to act. Label sheets print
|
|
5
|
+
those codes from the scan schemes that read them, on office printers (A4 and
|
|
6
|
+
Letter label stock, ID card stock) and thermal printers (ZPL).
|
|
7
|
+
|
|
8
|
+
A label is a heading, up to two lines of text, and one to four codes for one
|
|
9
|
+
target, each printed beside the act it names. A container label can print
|
|
10
|
+
**Check in** and **Check out** side by side; the person scanning chooses the
|
|
11
|
+
act by choosing which code to scan. The text is whatever the target's facts
|
|
12
|
+
say: the platform has no notion of what a target is.
|
|
13
|
+
|
|
14
|
+
## Contents
|
|
15
|
+
|
|
16
|
+
- [Templates](#templates)
|
|
17
|
+
- [Targets](#targets)
|
|
18
|
+
- [Media and layout](#media-and-layout)
|
|
19
|
+
- [Output](#output)
|
|
20
|
+
- [Checking codes before printing](#checking-codes-before-printing)
|
|
21
|
+
- [Badges are credentials](#badges-are-credentials)
|
|
22
|
+
- [Who may print](#who-may-print)
|
|
23
|
+
- [The label ledger](#the-label-ledger)
|
|
24
|
+
- [Printer transports](#printer-transports)
|
|
25
|
+
- [Declaring templates in code](#declaring-templates-in-code)
|
|
26
|
+
- [Agents](#agents)
|
|
27
|
+
|
|
28
|
+
## Templates
|
|
29
|
+
|
|
30
|
+
A template says what one label shows, for one scan scheme. Templates print
|
|
31
|
+
codes the platform mints: schemes with `fixed` or `delimited` encoding.
|
|
32
|
+
|
|
33
|
+
| Field | Meaning |
|
|
34
|
+
|---|---|
|
|
35
|
+
| `codes` | 1 to 4 of the scheme's rules, in print order. Each has a `caption` (default: the rule's name) and a `tone`: `solid` (white text on a black band), `outline`, or `plain`. Tones tell neighbouring codes apart on black-only stock. |
|
|
36
|
+
| `text.title`, `text.lines` | A heading and up to two lines, written in label tokens. |
|
|
37
|
+
| `symbology` | `code128` (default; shelves scanned from a distance), `qrcode`, or `datamatrix` (small labels). |
|
|
38
|
+
| `human_readable` | Print the code as text under its symbol. |
|
|
39
|
+
| `media` | The default media preset for this template. |
|
|
40
|
+
| `sensitive` | Printing confirms first and records who and what the labels name. Always true on an identity scheme. |
|
|
41
|
+
|
|
42
|
+
Label tokens:
|
|
43
|
+
|
|
44
|
+
| Token | Value |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `{target}` | The code's target (action schemes). |
|
|
47
|
+
| `{item.<facet>}` | A facet of the row the target came from, or a column of a pasted list. |
|
|
48
|
+
| `{user.display_name}`, `{user.name}`, `{user.email}`, `{user.roles}`, `{user.<property>}` | The badge holder (identity schemes). |
|
|
49
|
+
| `{scheme.name}` | The scheme's name. |
|
|
50
|
+
|
|
51
|
+
A token with no value prints empty, and the preview warns about it
|
|
52
|
+
(`missing_token`, naming the facts the label does have). Captions take tokens
|
|
53
|
+
too; a caption left blank prints the rule's name as written. Identity
|
|
54
|
+
credentials never print as text:
|
|
55
|
+
`{target}` and `{user.<identity key>}` are refused on identity templates.
|
|
56
|
+
|
|
57
|
+
Manage templates on **Admin → Scan Codes → (scheme) → Labels**, through
|
|
58
|
+
`PUT /api/labels/templates/:name`, or with the `upsert_label_template` MCP
|
|
59
|
+
tool. Every write bumps the template's `revision`; an edit that names
|
|
60
|
+
`expected_revision` is refused when someone else saved first.
|
|
61
|
+
|
|
62
|
+
## Targets
|
|
63
|
+
|
|
64
|
+
A print job is a template plus a source of targets:
|
|
65
|
+
|
|
66
|
+
| Source | Targets |
|
|
67
|
+
|---|---|
|
|
68
|
+
| `{ kind: 'range', prefix, from, to, pad, suffix }` | A numbered run: `A-01` to `A-40`. Targets can be printed before anything else is known about them. |
|
|
69
|
+
| `{ kind: 'list', text }` | One target per line. A header row starting with `target` names the other columns, which fill `{item.<column>}`. |
|
|
70
|
+
| `{ kind: 'escalations', ids }` | Rows selected in a list. Each row is read as the caller; its metadata fills `{item.*}`. |
|
|
71
|
+
| `{ kind: 'facets', query }` | Every row a faceted search returns, searched as the caller. The newest row per target wins. |
|
|
72
|
+
| `{ kind: 'users', userIds, role }` | Users carrying the identity scheme's key: the ids given, everyone in `role`, or with neither, every badge holder. The only source an identity template accepts. On **Accounts**, **Print badges** prints the selected users, or with none selected, everyone or everyone in a role. |
|
|
73
|
+
|
|
74
|
+
A job holds at most `LT_LABELS_MAX_PER_JOB` labels (default 1000) and at most
|
|
75
|
+
`LT_LABELS_MAX_CREDENTIALS_PER_JOB` badges (default 200).
|
|
76
|
+
|
|
77
|
+
## Media and layout
|
|
78
|
+
|
|
79
|
+
Shipped presets (`GET /api/labels/media`):
|
|
80
|
+
|
|
81
|
+
| Family | Presets |
|
|
82
|
+
|---|---|
|
|
83
|
+
| A4 | `a4-l7160` (21 per sheet), `a4-l7163` (14), `a4-l7165` (8), `a4-l7173` (10), `a4-l7651` (65), `a4-a6` (4), `a4-placard` (1), `a4-cr80` (10 ID cards) |
|
|
84
|
+
| Letter | `letter-5160` (30), `letter-5163` (10), `letter-22805` (24 squares), `letter-placard` (1), `letter-cr80` (8 ID cards) |
|
|
85
|
+
| Thermal | `thermal-4x6`, `thermal-4x2`, `thermal-2x1` at 203 dpi |
|
|
86
|
+
|
|
87
|
+
A job prints on the media it names, then the template's media, then the
|
|
88
|
+
deployment default (`LT_LABELS_DEFAULT_MEDIA`, `a4-l7160` unless set). A job
|
|
89
|
+
can also pass a custom grid: page size, rows and columns, label size,
|
|
90
|
+
margins and gutters, all in millimetres.
|
|
91
|
+
|
|
92
|
+
Per job:
|
|
93
|
+
|
|
94
|
+
- `startPosition` skips used labels on the first sheet (counted from 1).
|
|
95
|
+
- `copies` prints each label several times, together.
|
|
96
|
+
- `onePerPage` puts each label on its own page (placards).
|
|
97
|
+
- `cutMarks` prints trim marks for card stock.
|
|
98
|
+
|
|
99
|
+
Labels lay out to fit their box. When a code would print below the stock's
|
|
100
|
+
minimum bar width (`minModuleMm`, 0.25 mm on the presets) or without its blank
|
|
101
|
+
margin, the job reports a `scale` or `quiet_zone` warning.
|
|
102
|
+
|
|
103
|
+
## Output
|
|
104
|
+
|
|
105
|
+
`POST /api/labels/issue` delivers a job as:
|
|
106
|
+
|
|
107
|
+
| `output` | Result |
|
|
108
|
+
|---|---|
|
|
109
|
+
| `sheet` | The laid-out sheet as JSON. The dashboard prints it through the browser at exact size. |
|
|
110
|
+
| `pdf` | A PDF at the media's exact page size. |
|
|
111
|
+
| `zpl` | ZPL for thermal media, using the printer's own barcode commands. |
|
|
112
|
+
| `transport:<name>` | Sent through a registered [printer transport](#printer-transports). |
|
|
113
|
+
|
|
114
|
+
PDF text uses Helvetica, which covers Latin names with accents. A deployment
|
|
115
|
+
that prints names in other scripts registers a font with
|
|
116
|
+
`start({ labels: { font: { regular, bold } } })`.
|
|
117
|
+
|
|
118
|
+
## Checking codes before printing
|
|
119
|
+
|
|
120
|
+
A preview (`POST /api/labels/preview`) lays out the job without printing or
|
|
121
|
+
recording it, and lists a warning for every label that would fail on the floor:
|
|
122
|
+
|
|
123
|
+
- `unparseable`: the code does not read back as its scheme, or the scheme is disabled.
|
|
124
|
+
- `rule_disabled`: the code's rule is disabled; scanning it does nothing.
|
|
125
|
+
- `unresolved`: the target names no row today, or the badge holder is not an active user.
|
|
126
|
+
- `missing_token`: the heading, a line or a caption reads `{item.<facet>}` or `{user.<key>}`, and the label's data has no such value.
|
|
127
|
+
- `scale`, `quiet_zone`, `overflow`, `unencodable`: the code or text does not fit the label.
|
|
128
|
+
|
|
129
|
+
The dashboard prints only after a preview of the same choice. In Chrome, the
|
|
130
|
+
preview can also decode every code on screen and report any it cannot read
|
|
131
|
+
back.
|
|
132
|
+
|
|
133
|
+
## Badges are credentials
|
|
134
|
+
|
|
135
|
+
An identity scheme's code acts as a person, so printing one follows its own
|
|
136
|
+
rules:
|
|
137
|
+
|
|
138
|
+
- Only a credential issuer may print or reissue a badge (see [Who may print](#who-may-print)).
|
|
139
|
+
- A badge preview is masked: it shows where each code goes, never the code.
|
|
140
|
+
- Printing asks for confirmation (`confirm: true`), and the ledger row naming the requester and every holder is written before any code is composed.
|
|
141
|
+
- Badge codes travel in response bodies with `Cache-Control: no-store`, never in URLs, and never in logs or the ledger.
|
|
142
|
+
- User reads (`GET /api/users`, `GET /api/users/:id`, user writes' responses) leave identity keys out of `metadata` and list them in `identity_bound`.
|
|
143
|
+
- Setting or removing an identity key by hand (`PATCH /api/users/:id/properties`) needs the same access and is recorded as a `bind`.
|
|
144
|
+
- Badge scans are unchanged: a scanned token resolves against `lt_users.metadata` on the server, as before.
|
|
145
|
+
|
|
146
|
+
The user API protections (the last two points, and the refusal of identity keys
|
|
147
|
+
in wholesale `metadata` writes) are on by default.
|
|
148
|
+
`start({ labels: { protectIdentityKeys: false } })` or
|
|
149
|
+
`LT_PROTECT_IDENTITY_KEYS=false` keeps the earlier users API behavior; badge
|
|
150
|
+
printing and reissue still need `credentialIssuer`. Either way, a `metadata`
|
|
151
|
+
replace keeps the identity keys it leaves out.
|
|
152
|
+
|
|
153
|
+
**Reissue** (`POST /api/labels/badges/reissue`) mints a new credential that
|
|
154
|
+
fits the scheme's encoding, writes it and its ledger row in one statement, and
|
|
155
|
+
prints the new badge. On a delimited identity scheme the credential is
|
|
156
|
+
`target_length` random characters (8 to 64, default 10; **Badge length** on
|
|
157
|
+
the scheme page), and the badge encodes it with its prefix, for example
|
|
158
|
+
`14:0:7KQ2M9XW4H`. On a fixed scheme it is `target_length` digits. Badges of
|
|
159
|
+
any length keep scanning; the length only shapes new ones. Ten characters keep
|
|
160
|
+
a Code 128 badge on an ID card comfortably above the minimum bar width. The old code resolves to no one from that moment. An
|
|
161
|
+
acting grant minted from the old badge before the reissue lasts until its
|
|
162
|
+
`grant_ttl_seconds` runs out.
|
|
163
|
+
|
|
164
|
+
## Who may print
|
|
165
|
+
|
|
166
|
+
| Labels | Access |
|
|
167
|
+
|---|---|
|
|
168
|
+
| Item labels (action schemes) | Admin access or role management (admin, superadmin, the `engineer` role). |
|
|
169
|
+
| Badges (identity schemes) | The `credentialIssuer` capability: superadmin, or a holder of the `credential-issuer` role. Admin type alone does not grant it. |
|
|
170
|
+
| Templates | Role management to write; any signed-in user to read. |
|
|
171
|
+
|
|
172
|
+
## The label ledger
|
|
173
|
+
|
|
174
|
+
Every print, reissue and binding is a row in `lt_label_jobs`: who asked, when,
|
|
175
|
+
the template and its revision (with a snapshot), the media and output, and
|
|
176
|
+
what the labels name: targets for item labels, user ids for badges. Rows are
|
|
177
|
+
never deleted by the platform; the only columns it updates are the delivery
|
|
178
|
+
stamps of a transport job.
|
|
179
|
+
|
|
180
|
+
**Admin → Label History** (`GET /api/labels/jobs`) lists the ledger.
|
|
181
|
+
Credential issuers see every row; other readers see item jobs and their own.
|
|
182
|
+
**Print again** (`POST /api/labels/jobs/:id/reprint`) prints a job, or chosen
|
|
183
|
+
labels of it, again from its source with the template as it is now, and
|
|
184
|
+
records a new job. A badge reprint confirms again.
|
|
185
|
+
|
|
186
|
+
An `idempotencyKey` on an issue request makes it safe to repeat, which is what
|
|
187
|
+
a workflow activity retry does. The repeat records nothing new and prints only
|
|
188
|
+
the labels the first request recorded:
|
|
189
|
+
|
|
190
|
+
- A sheet, PDF or ZPL output renders those labels again.
|
|
191
|
+
- A transport output is sent under a delivery lease. Claiming the lease is one
|
|
192
|
+
statement, so concurrent repeats send once. A job already delivered is not
|
|
193
|
+
sent again. A job whose send failed, or whose sender stopped before the
|
|
194
|
+
transport accepted, is sent by the next repeat once its lease
|
|
195
|
+
(`LT_LABELS_DELIVERY_LEASE_SECONDS`, default 120) lapses.
|
|
196
|
+
- A key used before for a different template or output answers `409`.
|
|
197
|
+
|
|
198
|
+
Workflow activities pass their workflow id as the key.
|
|
199
|
+
|
|
200
|
+
## Printer transports
|
|
201
|
+
|
|
202
|
+
A transport routes issued labels to a printer: a thermal printer on the
|
|
203
|
+
network, a print server, a watched folder. Hosts register transports by name:
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
import type { LTLabelTransport } from '@hotmeshio/long-tail';
|
|
207
|
+
|
|
208
|
+
const thermal: LTLabelTransport = {
|
|
209
|
+
formats: ['zpl'],
|
|
210
|
+
async send({ jobId, payload, destination }) {
|
|
211
|
+
await sendToPrinter(destination, payload as string);
|
|
212
|
+
return { accepted: true, detail: jobId };
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
start({ labels: { transports: { thermal }, defaultMedia: 'a4-l7160' } });
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
A job sends with `output: 'transport:thermal'`; `destination` on the request
|
|
220
|
+
passes through to `send` as given, and the transport decides what it names. A name with no registered transport is refused
|
|
221
|
+
before anything is recorded. `GET /api/labels/transports` lists the registered
|
|
222
|
+
names, and the dashboard offers **Send** when one accepts the job's format.
|
|
223
|
+
|
|
224
|
+
The examples register `storage-drop`, which writes each job to file storage at
|
|
225
|
+
`labels/<jobId>.<format>`.
|
|
226
|
+
|
|
227
|
+
## Declaring templates in code
|
|
228
|
+
|
|
229
|
+
Templates declare with their scheme and follow the
|
|
230
|
+
[code-owned configuration](code-owned-configuration.md) contract as one unit
|
|
231
|
+
with it:
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
scanSchemes: [
|
|
235
|
+
{
|
|
236
|
+
version: 14,
|
|
237
|
+
name: 'Container',
|
|
238
|
+
target_facet: 'containerId',
|
|
239
|
+
encoding: 'delimited',
|
|
240
|
+
rules: [
|
|
241
|
+
{ category: '0', name: 'Check in', steps: [/* … */] },
|
|
242
|
+
{ category: '1', name: 'Check out', steps: [/* … */] },
|
|
243
|
+
],
|
|
244
|
+
labels: [
|
|
245
|
+
{
|
|
246
|
+
name: 'container',
|
|
247
|
+
title: 'Container',
|
|
248
|
+
codes: [{ category: '0', tone: 'solid' }, { category: '1', tone: 'outline' }],
|
|
249
|
+
text: { title: '{target}', lines: ['{item.subtitle}'] },
|
|
250
|
+
media: 'a4-l7160',
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Agents
|
|
258
|
+
|
|
259
|
+
The admin MCP server carries `list_label_templates`, `upsert_label_template`,
|
|
260
|
+
`delete_label_template`, and `render_label_sheet`. `render_label_sheet` issues
|
|
261
|
+
item labels as the caller, stores the PDF or ZPL in file storage, and returns
|
|
262
|
+
the job id, the file ref, a link valid for ten minutes, and the warnings.
|
|
263
|
+
It refuses sensitive and identity templates: people print badges.
|
|
264
|
+
|
|
265
|
+
The `relabel` example workflow shows labels printed from a workflow: it asks a
|
|
266
|
+
person for a label's second line, then prints the label with it through a
|
|
267
|
+
transport, keyed by its workflow id.
|
package/docs/scan-codes.md
CHANGED
|
@@ -31,6 +31,7 @@ canonical action surface. A scan is an **ECA rule** over that surface:
|
|
|
31
31
|
- [Capture on the dashboard](#capture-on-the-dashboard)
|
|
32
32
|
- [Scanner setup](#scanner-setup)
|
|
33
33
|
- [Admin configuration](#admin-configuration)
|
|
34
|
+
- [Printing labels](label-sheets.md)
|
|
34
35
|
- [The printer demo](#the-printer-demo)
|
|
35
36
|
- [The bag and bin demo](#the-bag-and-bin-demo)
|
|
36
37
|
|
|
@@ -273,6 +274,10 @@ receives the raw value and renders it with the list's formatter, so an ISO
|
|
|
273
274
|
instant in metadata reads the same on the station as in a list column (and
|
|
274
275
|
in the deployment's display time zone, when one is set).
|
|
275
276
|
|
|
277
|
+
`show` names a [roster](hitl/x-lt-roster.md) field of the row's form, rendered
|
|
278
|
+
above the choices as a hold renders it: an arrival screen lists what came in
|
|
279
|
+
the container before the person taps Arrive.
|
|
280
|
+
|
|
276
281
|
Without `facts`, the station lists the row's metadata, leaving out the
|
|
277
282
|
bookkeeping a bench never acts on: scan provenance (`scannedAt`,
|
|
278
283
|
`scanScheme`, `scanCategory`, `scanStation`, `scanActionName`),
|
|
@@ -358,7 +363,10 @@ set one ("Take the new label from the printer and stick it on C-12").
|
|
|
358
363
|
Any step that writes may carry `done: { markdown }`: the copy the station shows,
|
|
359
364
|
large, once the write lands and until the next scan ("Place it in
|
|
360
365
|
**{container.containerCode}**. All good."). It reads the same bags its refusal copy
|
|
361
|
-
reads.
|
|
366
|
+
reads. `done.afterSeconds` (0-60) sets how long this act's copy stays up before
|
|
367
|
+
the station returns, over the role's `scan_done.after_seconds`, and
|
|
368
|
+
`done.nextPrompt` replaces the "Scan the next item" line under it when the next
|
|
369
|
+
act is not a scan ("Set the bag in tub **{container.tubCode}**"). A fill or an into-subject add that leaves slots open shows its done
|
|
362
370
|
copy under the hold; without done copy the station shows the count ("2 of 5
|
|
363
371
|
checked off" for a fill, "2 of 5 added" for an add).
|
|
364
372
|
|
|
@@ -375,6 +383,22 @@ unchanged.
|
|
|
375
383
|
"show": "shoes" } }
|
|
376
384
|
```
|
|
377
385
|
|
|
386
|
+
**Ending the hold.** The hold card's button lets go of the item. By default it
|
|
387
|
+
reads "Put it down" and the station stays where it is. `hold.release` names it
|
|
388
|
+
for the bench: `label`, `tone: "accent"` to draw it as the screen's primary act,
|
|
389
|
+
and `return` (`home` or a dashboard route) for where the station goes once
|
|
390
|
+
released. Releasing writes nothing: items not yet scanned simply wait for the
|
|
391
|
+
next trip. With `hold.show`, `hold.whenAllIn` ends the hold on its own once
|
|
392
|
+
every entry on the roster is in. The station shows its done copy
|
|
393
|
+
(`markdown`, `afterSeconds`, `nextPrompt`, rendered against the held row), then
|
|
394
|
+
returns as after a completed act.
|
|
395
|
+
|
|
396
|
+
```jsonc
|
|
397
|
+
"params": { "hold": { "label": "{item.tubCode}", "show": "bags",
|
|
398
|
+
"release": { "label": "I'm done", "tone": "accent", "return": "home" },
|
|
399
|
+
"whenAllIn": { "markdown": "Every bag is in **{item.tubCode}**.", "afterSeconds": 5 } } }
|
|
400
|
+
```
|
|
401
|
+
|
|
378
402
|
The server trusts nothing about the subject. Each request re-parses its
|
|
379
403
|
code, re-reads the row under the station's read scope, requires the row to
|
|
380
404
|
still carry the code's target and to be pending. A subject that fails is
|
|
@@ -418,6 +442,19 @@ printed code. With them, `{fill.pending}` lists the open entries by label,
|
|
|
418
442
|
refusal's `expected` reads the labels. An entry the map does not name reads as
|
|
419
443
|
its code; without `fill.labels`, both tokens read codes.
|
|
420
444
|
|
|
445
|
+
**Which key a fill takes.** A scan fills the first open key for its code, in
|
|
446
|
+
the row's order. When the same code is expected under several keys that each
|
|
447
|
+
belong to something the station can hold (two boxes of one item arriving in
|
|
448
|
+
two parcels), `fill.prefer` names a per-key map on the batch row naming the
|
|
449
|
+
value each key belongs to. Open keys whose value equals the held subject's
|
|
450
|
+
target (or, for a list value, contains it) fill first; the rest follow as
|
|
451
|
+
before. Held by parcel `P2`, scanning the item fills the key mapped to `P2`.
|
|
452
|
+
|
|
453
|
+
```jsonc
|
|
454
|
+
"params": { "fill": { "into": "subject", "prefer": "envelope.key_parcels" } }
|
|
455
|
+
// the row's envelope: { "key_parcels": { "<code>#1": "P1", "<code>#2": "P2" } }
|
|
456
|
+
```
|
|
457
|
+
|
|
421
458
|
```jsonc
|
|
422
459
|
"refuse": { "markdown": "Not one of this order's shoes. Still to match: {fill.pending}." },
|
|
423
460
|
"done": { "markdown": "Matched. Next: {fill.next}" },
|
|
@@ -443,6 +480,14 @@ declares `refuse.conflict` also clears the subject so the next item scan
|
|
|
443
480
|
reads fresh state. Exactly one of two racing acts wins whenever both name
|
|
444
481
|
the same row: the reciprocal statement writes both rows or neither.
|
|
445
482
|
|
|
483
|
+
**Where the scanned item is now.** Refusal and done copy may read
|
|
484
|
+
`{located.<facet>}`: the scanned code's own pending row, the newest one in any
|
|
485
|
+
role the reader may read (the held row excepted). Besides the row's facets it
|
|
486
|
+
carries `id`, `role` and `roleTitle` (the role's title, else its name), so a
|
|
487
|
+
refusal can say where the item belongs: "This bag is at
|
|
488
|
+
**{located.roleTitle}**." The row is read only for a step whose copy or Open
|
|
489
|
+
names it; with no such row the token renders empty.
|
|
490
|
+
|
|
446
491
|
**The item's own row on an into-subject add.** A held container that collects
|
|
447
492
|
item codes (a box being packed from a bin) often has items that each wait on
|
|
448
493
|
their own row. `accumulate.item` locates that row and writes it as the
|
|
@@ -633,6 +678,30 @@ Pair kiosk with `x-lt-transition-done` on the role's form schema
|
|
|
633
678
|
resolve lands back on the list rather than walking browser history — see
|
|
634
679
|
[x-lt-transition](./hitl/x-lt-transition.md).
|
|
635
680
|
|
|
681
|
+
### Open: from a scan result into its row
|
|
682
|
+
|
|
683
|
+
The station's answer stays light (right container or wrong one), but the moment
|
|
684
|
+
something is off the person needs the full form. A step's `open` puts an
|
|
685
|
+
**Open** button on the hold card, the done screen or the refusal it answers with:
|
|
686
|
+
|
|
687
|
+
```jsonc
|
|
688
|
+
"open": { "target": "subject", "claim": true }
|
|
689
|
+
"open": { "target": "row", "label": "Open the bin", "list": { "facets": ["binCode"], "role": "binning" } }
|
|
690
|
+
"open": { "target": "located", "label": "Where it is" }
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
`target` is the row the step acted on or located (`row`), the held row
|
|
694
|
+
(`subject`, on a hold the row just held), or the scanned code's own pending row
|
|
695
|
+
(`located`). Open lands on that row's detail page, in the app. With `list`, it
|
|
696
|
+
lands on the faceted list of rows sharing those facets with the target, the
|
|
697
|
+
values read from the target row on the server. With `claim`, the row is claimed
|
|
698
|
+
first as the person acting (the badge rides the claim) and opens claimed in
|
|
699
|
+
their name; a claim the server refuses (no badge, a scope that does not cover
|
|
700
|
+
it, someone else's claim) still opens the row, read-only, where the detail page
|
|
701
|
+
offers its own Claim. Opening from a hold lets go of the item. A target with no
|
|
702
|
+
row, or a list facet the row does not carry, offers no button. Every decision
|
|
703
|
+
(reject, missing, done) stays on the detail form.
|
|
704
|
+
|
|
636
705
|
### After a scan completes: the return
|
|
637
706
|
|
|
638
707
|
A station works in one rhythm: badge, item, destination, done, back to the
|
|
@@ -644,7 +713,9 @@ list. A role names the last step in `properties.scan_done`:
|
|
|
644
713
|
|
|
645
714
|
`return` is `home` (the role's kiosk home: its first portal, else its list) or
|
|
646
715
|
a dashboard-relative route; `after_seconds` (0-60, default 2) is how long the
|
|
647
|
-
done copy stays up first
|
|
716
|
+
done copy stays up first, and a step's `done.afterSeconds` sets it for one act.
|
|
717
|
+
The done screen counts the seconds down. `button` (e.g. `"Done"`) adds a button
|
|
718
|
+
that returns at once. The station returns once a scan act completes its
|
|
648
719
|
row: the last fill of a batch, an executed choice with done copy, any write
|
|
649
720
|
that clears the subject. A fill that leaves entries pending stays on the hold
|
|
650
721
|
card, a refusal never returns, and a `follow` runs first. A station holding
|
|
@@ -687,6 +758,11 @@ submit for ten minutes. A grant bound to a scanned subject (`grant_scope:
|
|
|
687
758
|
locally, so the identity gate sits at the one place a record actually
|
|
688
759
|
changes, once per change.
|
|
689
760
|
|
|
761
|
+
Claiming at a station works the same way. On a read-only station login, the
|
|
762
|
+
detail page's Claim asks for a badge and claims as whoever badges in; the badge
|
|
763
|
+
then stays primed for the work on the row, bounded by its grant's own uses and
|
|
764
|
+
lifetime. A claim the server refuses says why on the claim bar.
|
|
765
|
+
|
|
690
766
|
Mutations attribute to the badged person (`assigned_to`, `resolved_by`)
|
|
691
767
|
with the device recorded beside them (`scanStation` in the scan
|
|
692
768
|
provenance) — every action individually owned and geographically placed.
|
|
@@ -708,12 +784,19 @@ A field can take a scan while the form is open: with
|
|
|
708
784
|
[`x-lt-scan`](hitl/x-lt-scan.md), scanning a container into a claimed form
|
|
709
785
|
fills its container field (checked against what the record expects), and
|
|
710
786
|
`x-lt-scan-submit` submits once the scan fields are filled, which raises the
|
|
711
|
-
badge prompt. A
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
787
|
+
badge prompt. A batch [roster](hitl/x-lt-roster.md) that declares `x-lt-scan`
|
|
788
|
+
checks its entries off the same way: a scan of an accepted scheme, with nothing
|
|
789
|
+
focused, fills the row's first open entry for that code on the server, as the
|
|
790
|
+
person acting. A scan no field accepts runs globally as usual.
|
|
791
|
+
|
|
792
|
+
Badge tokens are printed credentials: bind them server-side
|
|
793
|
+
(`lt_users.metadata`) as random strings (generated badges are `target_length`
|
|
794
|
+
characters, default 10), and treat badge possession with
|
|
795
|
+
the same physical policy as any badge system. User reads leave identity keys
|
|
796
|
+
out of `metadata` and list them in `identity_bound`. Printing, reissuing and
|
|
797
|
+
binding a badge needs the `credentialIssuer` capability and is recorded in
|
|
798
|
+
the label ledger; see [label-sheets.md](label-sheets.md#badges-are-credentials).
|
|
799
|
+
Unknown badges answer `identity_unknown`.
|
|
717
800
|
|
|
718
801
|
## The fallback screen
|
|
719
802
|
|
|
@@ -839,7 +922,8 @@ UPC-A where numeric-only labels are already in circulation.
|
|
|
839
922
|
at a target facet — its two-digit index is assigned for you. A scheme's detail
|
|
840
923
|
page lists its actions; **Add an action** opens the rule editor:
|
|
841
924
|
|
|
842
|
-
1. **Name it** — the friendly label printed beside the physical code.
|
|
925
|
+
1. **Name it** — the friendly label printed beside the physical code. Label
|
|
926
|
+
templates print it there; see [label-sheets.md](label-sheets.md).
|
|
843
927
|
2. **Order the conditions** — each step picks a queue, a held-by filter,
|
|
844
928
|
and its action; steps reorder with arrows. First match wins.
|
|
845
929
|
3. **Set the fallback** — markdown for the no-match screen.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hotmeshio/long-tail",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"description": "Long Tail Workflows — Durable AI workflows with human-in-the-loop escalation. Powered by PostgreSQL.",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"types": "./build/index.d.ts",
|
|
@@ -87,9 +87,11 @@
|
|
|
87
87
|
"@opentelemetry/resources": "^2.5.1",
|
|
88
88
|
"@opentelemetry/sdk-node": "^0.218.0",
|
|
89
89
|
"@opentelemetry/semantic-conventions": "^1.39.0",
|
|
90
|
+
"@pdf-lib/fontkit": "^1.1.1",
|
|
90
91
|
"ajv": "^8.20.0",
|
|
91
92
|
"arctic": "^3.7.0",
|
|
92
93
|
"bcryptjs": "^2.4.3",
|
|
94
|
+
"bwip-js": "^4.11.4",
|
|
93
95
|
"commander": "^14.0.3",
|
|
94
96
|
"express": "^5.1.0",
|
|
95
97
|
"hono": "^4.12.23",
|
|
@@ -97,6 +99,7 @@
|
|
|
97
99
|
"nats": "^2.28.0",
|
|
98
100
|
"openai": "^5.9.0",
|
|
99
101
|
"ora": "^9.4.0",
|
|
102
|
+
"pdf-lib": "^1.17.1",
|
|
100
103
|
"pg": "^8.13.0",
|
|
101
104
|
"picocolors": "^1.1.1",
|
|
102
105
|
"pino": "^9.6.0",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{a as m,j as e}from"./vendor-query-DvWWuNIB.js";import{w as ut,x as mt,c as xt,y as ht,M as Se,z as gt,A as ft,B as pt,E as bt,G as yt,H as jt,I as vt,K as Ct,L as kt,O as Nt,Q as wt,r as Pt,R as St,T as Rt,U as Et,V as Tt,W as At,X as Bt,Y as Ot,Z as Lt,_ as Mt,$ as Ft,a0 as zt,a1 as It,a2 as Ut,a3 as Vt,a4 as $t,a5 as _t,a6 as qt}from"./index-ygxyAKcc.js";import{a as Re,u as Ee,f as Ht}from"./vendor-react-_9U4mKFr.js";import{i as Kt}from"./task-queues-7-sHKPsN.js";import{X as re,al as Dt,z as Gt,am as Qt,an as Wt,a0 as Yt,j as Xt,ao as Jt,P as Zt,ap as es}from"./vendor-icons-en0_uSRD.js";import{u as Te,C as ts,r as ss,B as as,a as ns}from"./BulkAssignModal-CmLVxkz-.js";import{E as is}from"./EscalationTitleSelect-CT7mYHkb.js";import{u as ls,E as rs,a as os,t as cs}from"./EscalationTimeline-CLvSr1SD.js";import{m as ds,E as us,a as ms}from"./escalation-columns-Bvo6JI4Z.js";import{u as xs}from"./useFilterParams-DBRw1Hcv.js";import{u as hs}from"./useDebouncedValue-CgO0TGMd.js";import{D as gs}from"./DataTable-FjFhx0SE.js";import{S as fs}from"./StickyPagination-miUdVAKw.js";import{P as ps}from"./constants-CeBBTzf5.js";import{R as bs,a as ys}from"./RowActions-Bdd7z4eB.js";import{i as js}from"./validate-CAin6WM_.js";import"./escalation-items-DFGRwo49.js";import"./UserName-DKXnK7DD.js";import"./EntityTimelinePanel-DJN_ZEQa.js";import"./FilterBar-Dy0b7wwf.js";import"./PriorityBadge-r33mpDju.js";import"./RolePill-D3hkAdKf.js";import"./WorkflowPill-CKHip3hH.js";import"./CountdownTimer-CuPY7zkb.js";import"./EmptyState-DgC_6njU.js";import"./useContainerWidth-DSLp1gEm.js";import"./StatusBadge-DHVwxre2.js";function vs(){const{pathname:t,search:n}=Re(),u=Ee(),{resolveUrl:l}=ut();m.useEffect(()=>{const g=t+n;if(mt(g).length===0)return;const p=l(g);p!==g&&u(p,{replace:!0})},[t,n,l,u])}const Cs=["<","<=",">",">=","="],ks=["priority","created_at","updated_at","status","role"],O="input text-xs py-1",Ne="select text-xs py-1",H="text-text-tertiary hover:text-text-primary transition-colors";function we(t){return t==="true"?!0:t==="false"?!1:t.trim()!==""&&!Number.isNaN(Number(t))?Number(t):t}const Ns=t=>Object.entries(t??{}).map(([n,u])=>({key:n,value:String(u)})),ws=t=>(t??[]).map(n=>{const[u,l]=Object.entries(n)[0]??["",""];return{key:u,value:String(l)}});function A({title:t,hint:n,children:u}){return e.jsxs("div",{className:"border-t border-surface-border/50 py-3 first:border-t-0 first:pt-1",children:[e.jsxs("div",{className:"mb-1.5 flex items-baseline justify-between",children:[e.jsx("span",{className:"text-2xs font-medium uppercase tracking-wide text-text-tertiary",children:t}),n&&e.jsx("span",{className:"text-2xs font-mono text-text-tertiary/70",children:n})]}),u]})}function K({value:t,onChange:n,placeholder:u}){return e.jsx("input",{list:"lt-facet-keys",className:`${O} w-40`,placeholder:u,value:t,onChange:l=>n(l.target.value)})}function Ps({value:t,onChange:n,facetKeys:u=[],search:l="",onSearchChange:g}){const p=Ns(t.facets),b=ws(t.block),f=t.range??[],r=t.exists??[],k=t.orderBy??[],P=a=>{const o={};for(const c of a)c.key&&(o[c.key]=we(c.value));n({...t,facets:Object.keys(o).length?o:void 0})},E=a=>{const o=a.filter(c=>c.key).map(c=>({[c.key]:we(c.value)}));n({...t,block:o.length?o:void 0})},T=a=>n({...t,range:a.length?a:void 0}),y=a=>n({...t,exists:a.length?a:void 0}),v=a=>n({...t,orderBy:a.length?a:void 0});return e.jsxs("div",{className:"text-xs",children:[e.jsx("datalist",{id:"lt-facet-keys",children:u.map(a=>e.jsx("option",{value:a},a))}),e.jsxs("datalist",{id:"lt-sort-fields",children:[ks.map(a=>e.jsx("option",{value:a},a)),u.map(a=>e.jsx("option",{value:`metadata.${a}`},a))]}),g&&e.jsx(A,{title:"Match id",hint:"id · workflow · origin",children:e.jsx("input",{className:`${O} w-full`,placeholder:"Exact escalation, workflow, or origin id…",value:l,onChange:a=>g(a.target.value)})}),e.jsx(A,{title:"Has facet",hint:"metadata @>",children:[...p,{key:"",value:""}].map((a,o)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx(K,{value:a.key,placeholder:"key",onChange:c=>{const i=[...p];i[o]={...a,key:c},P(i)}}),e.jsx("span",{className:"text-text-tertiary",children:"="}),e.jsx("input",{className:`${O} w-40`,placeholder:"value",value:a.value,onChange:c=>{const i=[...p];i[o]={...a,value:c.target.value},P(i)}}),o<p.length&&e.jsx("button",{className:H,onClick:()=>P(p.filter((c,i)=>i!==o)),children:"×"})]},o))}),e.jsx(A,{title:"Range",hint:"numeric",children:[...f,{facet:"",op:"<=",value:0}].map((a,o)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx(K,{value:a.facet,placeholder:"numeric facet",onChange:c=>{const i=[...f];i[o]={...a,facet:c},T(i.filter(j=>j.facet))}}),e.jsx("select",{className:Ne,value:a.op,onChange:c=>{const i=[...f];i[o]={...a,op:c.target.value},T(i.filter(j=>j.facet))},children:Cs.map(c=>e.jsx("option",{value:c,children:c},c))}),e.jsx("input",{type:"number",className:`${O} w-24`,value:a.value,onChange:c=>{const i=[...f];i[o]={...a,value:Number(c.target.value)},T(i.filter(j=>j.facet))}}),o<f.length&&e.jsx("button",{className:H,onClick:()=>T(f.filter((c,i)=>i!==o)),children:"×"})]},o))}),e.jsx(A,{title:"Has key",hint:"metadata ? key",children:e.jsxs("div",{className:"flex flex-wrap items-center gap-1",children:[r.map(a=>e.jsxs("span",{className:"flex items-center gap-1 rounded bg-accent/15 px-1.5 py-0.5 text-accent",children:[a,e.jsx("button",{className:"text-accent/70 hover:text-accent",onClick:()=>y(r.filter(o=>o!==a)),children:"×"})]},a)),e.jsx(K,{value:"",placeholder:"+ key",onChange:a=>{a&&!r.includes(a)&&y([...r,a])}})]})}),e.jsx(A,{title:"Exclude",hint:"NOT @>",children:[...b,{key:"",value:""}].map((a,o)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx(K,{value:a.key,placeholder:"key",onChange:c=>{const i=[...b];i[o]={...a,key:c},E(i)}}),e.jsx("span",{className:"text-text-tertiary",children:"="}),e.jsx("input",{className:`${O} w-40`,placeholder:"value",value:a.value,onChange:c=>{const i=[...b];i[o]={...a,value:c.target.value},E(i)}}),o<b.length&&e.jsx("button",{className:H,onClick:()=>E(b.filter((c,i)=>i!==o)),children:"×"})]},o))}),e.jsx(A,{title:"Sort by",children:[...k,{field:"",direction:"asc"}].map((a,o)=>e.jsxs("div",{className:"mb-1 flex items-center gap-1",children:[e.jsx("input",{list:"lt-sort-fields",className:`${O} w-44`,placeholder:"column or metadata.key",value:a.field,onChange:c=>{const i=[...k];i[o]={...a,field:c.target.value},v(i.filter(j=>j.field))}}),e.jsxs("select",{className:Ne,value:a.direction??"asc",onChange:c=>{const i=[...k];i[o]={...a,direction:c.target.value},v(i.filter(j=>j.field))},children:[e.jsx("option",{value:"asc",children:"asc"}),e.jsx("option",{value:"desc",children:"desc"})]}),e.jsxs("label",{className:"flex items-center gap-1 text-text-tertiary",children:[e.jsx("input",{type:"checkbox",checked:!!a.numeric,onChange:c=>{const i=[...k];i[o]={...a,numeric:c.target.checked},v(i.filter(j=>j.field))}}),"num"]}),o<k.length&&e.jsx("button",{className:H,onClick:()=>v(k.filter((c,i)=>i!==o)),children:"×"})]},o))})]})}function Ss({value:t,onChange:n,facetKeys:u,search:l,onSearchChange:g,activeFacetCount:p,onClear:b,onClose:f}){return e.jsxs("div",{className:"h-full overflow-y-auto",children:[e.jsxs("div",{className:"sticky top-0 z-10 flex items-center justify-between px-4 py-3 bg-surface-raised border-b border-surface-border/50",children:[e.jsx("span",{className:"text-xs font-semibold text-text-primary",children:"Faceted query"}),e.jsxs("div",{className:"flex items-center gap-2",children:[p>0&&e.jsx("button",{onClick:b,className:"text-2xs text-text-tertiary hover:text-text-primary transition-colors",children:"Clear"}),e.jsx("button",{onClick:f,className:"p-1 rounded hover:bg-surface-hover text-text-tertiary hover:text-text-primary transition-colors",title:"Close",children:e.jsx(re,{className:"w-4 h-4"})})]})]}),e.jsxs("div",{className:"px-4 py-2",children:[e.jsxs("p",{className:"mb-2 text-2xs leading-snug text-text-tertiary",children:["Precise metadata facets plus exact correlation-id lookup — they compose in one SQL query. Facet keys are the ones that actually exist in your visible escalations. Set status to ",e.jsx("span",{className:"font-medium",children:"All"})," to find an order across every status; the whole query is shareable via the URL."]}),e.jsx(Ps,{value:t,onChange:n,facetKeys:u,search:l,onSearchChange:g})]})]})}const Rs=t=>t.isPriorityPending||t.isClaimPending||t.isAssignPending||t.isUnassignPending||t.isTriagePending||t.isCancelPending,D="inline-flex items-center h-7 px-2.5 text-2xs font-medium text-text-secondary bg-surface border border-surface-border rounded-[4px] hover:border-accent/50 hover:text-text-primary transition-colors disabled:opacity-50 disabled:hover:border-surface-border",Pe=`${D} appearance-none cursor-pointer`,Es="inline-flex items-center h-7 px-2.5 text-2xs font-medium text-status-error bg-surface border border-status-error/30 rounded-[4px] hover:border-status-error hover:bg-status-error/5 transition-colors disabled:opacity-50";function Ts(t){var f;const n=Rs(t),u=Te(),{data:l}=xt(),g=ht(),p=g!==null?g:((f=l==null?void 0:l.ai)==null?void 0:f.enabled)===!0,b=t.selectedCount>0;return e.jsx("div",{className:`grid transition-all duration-200 ease-in-out ${b?"grid-rows-[1fr] opacity-100":"grid-rows-[0fr] opacity-0 pointer-events-none"}`,children:e.jsx("div",{className:"overflow-hidden",children:e.jsxs("div",{className:"flex flex-wrap items-center gap-2 py-2.5 pl-3 pr-2 mt-4 mb-3 bg-surface-sunken/60 border-l-2 border-l-accent",children:[e.jsxs("span",{className:"text-2xs font-semibold uppercase tracking-wider text-accent tabular-nums",children:[t.selectedCount," selected"]}),e.jsx("div",{className:"mx-1 h-4 w-px bg-surface-border"}),e.jsxs("select",{onChange:r=>{r.target.value&&(t.onSetPriority(parseInt(r.target.value)),r.target.value="")},disabled:n,className:Pe,defaultValue:"",children:[e.jsx("option",{value:"",disabled:!0,children:"Priority…"}),ps.map(r=>e.jsx("option",{value:r.value,children:r.label},r.value))]}),e.jsxs("select",{onChange:r=>{r.target.value&&(t.onClaim(parseInt(r.target.value)),r.target.value="")},disabled:n,className:Pe,defaultValue:"",children:[e.jsx("option",{value:"",disabled:!0,children:"Claim for…"}),u.map(r=>e.jsx("option",{value:r.value,children:r.label},r.value))]}),e.jsx("button",{onClick:t.onAssign,disabled:n,className:D,children:t.isAssignPending?"Assigning…":"Assign to…"}),e.jsx("button",{onClick:t.onUnassign,disabled:n,className:D,children:t.isUnassignPending?"Unassigning…":"Unassign"}),p&&e.jsx("button",{onClick:t.onTriage,disabled:n,className:D,children:t.isTriagePending?"Triaging…":"Triage"}),t.cancelLabel!==!1&&e.jsx("button",{onClick:t.onCancel,disabled:n,className:Es,children:t.isCancelPending?t.cancelLabel?`${t.cancelLabel}…`:"Cancelling…":t.cancelLabel||"Cancel"}),e.jsx("div",{className:"flex-1"}),n&&e.jsx("span",{className:"text-2xs text-text-tertiary animate-pulse",children:"Processing…"}),e.jsx("button",{onClick:t.onClearSelection,className:"px-1 text-2xs font-medium text-text-tertiary hover:text-text-primary transition-colors",children:"Clear"})]})})})}function As({open:t,onClose:n,selectedCount:u,onSubmit:l,isPending:g}){const[p,b]=m.useState(""),f=()=>{l(p||void 0)};return e.jsx(Se,{open:t,onClose:n,title:"Submit for AI Triage",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("p",{className:"text-sm text-text-secondary",children:["Submit ",e.jsx("span",{className:"font-medium text-text-primary",children:u})," escalation(s) for AI triage? The triage orchestrator will take over resolution."]}),e.jsxs("div",{children:[e.jsxs("label",{className:"text-xs font-medium text-text-secondary block mb-1",children:["Triage hint ",e.jsx("span",{className:"text-text-tertiary",children:"(optional)"})]}),e.jsx("input",{type:"text",value:p,onChange:r=>b(r.target.value),placeholder:"e.g., image_orientation",className:"input text-xs font-mono w-full"}),e.jsx("p",{className:"text-2xs text-text-tertiary mt-1",children:"Guides the triage workflow on what remediation to apply"})]}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx("button",{onClick:n,className:"btn-secondary text-xs",children:"Cancel"}),e.jsx("button",{onClick:f,disabled:g,className:"btn-primary text-xs",children:g?"Submitting...":"Submit for Triage"})]})]})})}function B(t,n,u){return l=>{t.mutate(l,{onSuccess:()=>{n(),u==null||u()}})}}function Bs(t){const n=()=>[...t.selectedIds];return{handleSetPriority:r=>{B(t.setPriority,t.clearSelection)({ids:n(),priority:r})},handleBulkClaim:r=>{B(t.bulkClaim,t.clearSelection)({ids:n(),durationMinutes:r})},handleBulkTriage:r=>{B(t.bulkTriage,t.clearSelection,t.closeTriageModal)({ids:n(),hint:r})},handleBulkAssign:(r,k,P)=>{B(t.bulkAssign,t.clearSelection,t.closeAssignModal)({ids:n(),targetUserId:r,durationMinutes:k,reassign:P})},handleBulkUnassign:()=>{B(t.bulkUnassign,t.clearSelection)({ids:n()})},handleBulkCancel:()=>{B(t.bulkCancel,t.clearSelection,t.closeCancelModal)({ids:n()})}}}function Os({claimTarget:t,onClose:n,claimDuration:u,onDurationChange:l,claimDurations:g,onCustomClaimChange:p,onClaim:b,isPending:f}){return e.jsx(Se,{open:!!t,onClose:n,title:"Claim Escalation",children:e.jsxs("div",{className:"space-y-4",children:[e.jsxs("p",{className:"text-sm text-text-secondary",children:["Claim ",e.jsx("span",{className:"font-medium text-text-primary",children:t==null?void 0:t.type})," for:"]}),e.jsxs("select",{value:u,onChange:r=>{l(r.target.value)},className:"select w-full text-sm",children:[g.map(r=>e.jsx("option",{value:r.value,children:r.label},r.value)),e.jsx("option",{value:"custom",children:"Other..."})]}),u==="custom"&&e.jsx(ts,{onChange:p,autoFocus:!0}),e.jsxs("div",{className:"flex justify-end gap-3 pt-2",children:[e.jsx("button",{onClick:n,className:"btn-secondary text-xs",children:"Cancel"}),e.jsx("button",{onClick:b,className:"btn-primary text-xs",disabled:f,children:f?"Claiming...":"Claim"})]})]})})}function ra(){var ke;vs();const t=Ee(),{filters:n,setFilter:u,pagination:l}=xs({filters:{role:"",type:"",subtype:"",priority:"",status:"available",search:""}});gt({role:n.role||null,verbs:["created","claimed","updated"]});const g=hs(n.search),p=Te(),[b,f]=m.useState(null),[r,k]=m.useState("30"),[P,E]=m.useState(0),T=m.useCallback(s=>E(s),[]),[y,v]=m.useState(new Set),a=m.useRef(null),o=m.useRef(null),c=m.useCallback(s=>{var x;if((x=o.current)==null||x.disconnect(),o.current=null,!s||typeof ResizeObserver>"u")return;const d=new ResizeObserver(()=>{var q;(q=a.current)==null||q.style.setProperty("--lt-sticky-top",`${s.offsetHeight-1}px`)});d.observe(s),o.current=d},[]),[i,j]=m.useState(!1),[L,M]=Ht(),h=m.useMemo(()=>ft(L),[L]),N=m.useCallback(s=>{M(d=>{const x=new URLSearchParams(d);return pt(x,s),x.delete("page"),x})},[M]),{data:F}=bt(i),z=yt(h)+(n.search?1:0),G="facet-query",{setPanel:oe,closePanel:ce,open:Ae,ownerKey:Be}=jt();m.useEffect(()=>{if(!i){ce(G);return}oe(e.jsx(Ss,{value:h,onChange:N,facetKeys:(F==null?void 0:F.keys)??[],search:n.search??"",onSearchChange:s=>u("search",s),activeFacetCount:z,onClear:()=>{N({}),u("search","")},onClose:()=>j(!1)}),{width:420,key:G})},[i,h,N,F,n.search,u,z,oe,ce]);const de=Ae&&Be===G,Q=m.useRef(!1);m.useEffect(()=>{if(de){Q.current=!0;return}Q.current&&(Q.current=!1,j(!1))},[de]);const[Oe,W]=m.useState(!1),[Le,Y]=m.useState(!1),[Me,X]=m.useState(!1),Fe=m.useCallback(s=>N({...h,orderBy:s}),[h,N]),I=Re(),{data:U}=vt(),ue=Ct(),ze=m.useCallback(()=>{var x;const s=window.prompt("Pin label:");if(!(s!=null&&s.trim()))return;const d=((x=U==null?void 0:U.preferences)==null?void 0:x.pinnedViews)??[];ue.mutate({pinnedViews:[...d,{id:kt(),label:s.trim(),url:I.pathname+I.search,badge:!0}]})},[I.pathname,I.search,U,ue]),{canBulk:Ie}=Nt(),{kiosk:J}=wt(),me=h.facets?Object.keys(h.facets):[],Ue=L.get("view"),Ve=m.useCallback(s=>{M(d=>{const x=new URLSearchParams(d);return s?x.set("view",s):x.delete("view"),x},{replace:!0})},[M]),Z=Ue==="timeline",$e=m.useCallback(s=>{const{[s]:d,...x}=h.facets??{};N({...h,facets:Object.keys(x).length>0?x:void 0})},[h,N]),xe=Pt(),he=St(),ge=Rt(),ee=Et(),fe=Tt(),te=At(),V=Bt(),{data:se}=Ot(),{data:S}=Lt(),{data:ae}=Mt(),{user:$,isSuperAdmin:_e,hasRoleType:qe}=Ft(),pe=_e||qe("admin"),be=m.useMemo(()=>new Set((($==null?void 0:$.roles)??[]).map(s=>s.role)),[$]),He=m.useMemo(()=>{const s=(S==null?void 0:S.roles)??[];return(pe?s:s.filter(x=>be.has(x.role)&&!Kt(x.role))).map(x=>({value:x.role,label:zt(x)})).sort((x,q)=>x.label.localeCompare(q.label))},[S,pe,be]);m.useEffect(()=>{v(new Set)},[n.role,n.type,n.subtype,n.priority,n.status,g,l.page,l.pageSize]);const ne=m.useMemo(()=>({...It(L,_t.AVAILABLE),search:g||void 0}),[L,g]),ye=100,{escalations:C,total:w,groups:Ke,listSchema:De,listSchemaVersion:Ge,singleRole:R,hasRichView:je,isLoading:Qe,isFetching:ve,error:_,refetch:We}=ls(ne,{limit:Z?ye:l.pageSize,offset:l.offset}),Ye=Ut(R??"",void 0,!!R),ie=R?ss((ke=Ye.data)==null?void 0:ke.form_schema).cancel:void 0,le=Vt(ne.view,je),Xe=le===qt.RICH,Ce=m.useMemo(()=>{if(!h.jeopardy||!R)return null;const s=((S==null?void 0:S.roles)??[]).find(x=>x.role===R),d=(s==null?void 0:s.priority_threshold_minutes)??(s==null?void 0:s.sla_minutes)??null;return d!=null?$t(d*6e4):null},[h.jeopardy,R,S]),Je=m.useMemo(()=>{const s=new Set;for(const d of C)y.has(d.id)&&s.add(d.role);return[...s]},[C,y]),Ze=m.useMemo(()=>C.filter(s=>y.has(s.id)&&js(s)).length,[C,y]),et=m.useCallback(()=>v(new Set),[]),tt=()=>{if(!b)return;const s=r==="custom"?P:parseInt(r);!s||s<=0||xe.mutate({id:b.id,durationMinutes:s},{onSuccess:()=>{f(null),t(`/escalations/detail/${b.id}`)}})},{handleSetPriority:st,handleBulkClaim:at,handleBulkTriage:nt,handleBulkAssign:it,handleBulkUnassign:lt,handleBulkCancel:rt}=Bs({selectedIds:y,clearSelection:et,setPriority:he,bulkClaim:ge,bulkTriage:te,bulkAssign:ee,bulkUnassign:fe,bulkCancel:V,closeTriageModal:()=>W(!1),closeAssignModal:()=>Y(!1),closeCancelModal:()=>X(!1)}),ot=s=>{const d=new Set(y);d.has(s)?d.delete(s):d.add(s),v(d)},ct=()=>{y.size===C.length?v(new Set):v(new Set(C.map(s=>s.id)))},dt=[Ie?{key:"select",label:e.jsx("input",{type:"checkbox",checked:C.length>0&&y.size===C.length,onChange:ct,className:"rounded"}),render:s=>e.jsx("input",{type:"checkbox",checked:y.has(s.id),onChange:d=>{d.stopPropagation(),ot(s.id)},onClick:d=>d.stopPropagation(),className:"rounded"}),className:"w-10",priority:1}:{key:"spacer",label:"",render:()=>null,className:"w-10",priority:3},...ds({highlightKeys:me}),{key:"actions",label:"",render:s=>e.jsx(bs,{children:e.jsx(ys,{icon:Dt,title:"Claim escalation",onClick:()=>f(s),alwaysVisible:!0,colorClass:"text-accent/40 hover:text-accent",size:"sm"})}),className:"w-10 text-right"}];return e.jsxs("div",{ref:a,children:[e.jsxs("div",{className:"flex items-center gap-2 mb-10 min-w-0",children:[e.jsx(is,{role:n.role,options:He,onChange:s=>u("role",s),locked:J}),!J&&e.jsx("button",{onClick:()=>{window.location.hash="#docs:dashboard.md:all-escalations"},className:"text-text-quaternary hover:text-accent transition-colors mt-1 shrink-0",title:"Open docs for this page",children:e.jsx(Gt,{className:"w-4 h-4",strokeWidth:1.5})})]}),e.jsxs("div",{ref:c,className:"sticky top-0 z-20 bg-surface",children:[e.jsx(us,{filters:n,setFilter:u,roles:(se==null?void 0:se.roles)??[],types:(ae==null?void 0:ae.types)??[],showStatus:!0,showSearch:!1,showRole:!J,actions:e.jsxs(e.Fragment,{children:[Z&&e.jsxs("span",{className:"text-2xs text-text-tertiary whitespace-nowrap",children:[w>100&&e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"font-medium text-text-secondary",children:[(l.page-1)*100+1,"–",Math.min(l.page*100,w)]})," of "]}),e.jsx("span",{className:"font-medium text-text-secondary",children:w})," ",w===1?"escalation":"escalations"]}),e.jsx(rs,{orderBy:h.orderBy,onChange:Fe}),e.jsx("div",{role:"radiogroup","aria-label":"List view",className:"flex items-center rounded overflow-hidden border border-surface-border",children:[{key:"table",title:"Table view",Icon:Qt},{key:"rich",title:"Rich view",Icon:Wt},{key:"timeline",title:"Timeline view",Icon:Yt}].filter(s=>s.key!=="rich"||je).map(({key:s,title:d,Icon:x})=>e.jsx("button",{role:"radio","aria-checked":le===s,onClick:()=>Ve(s),className:`px-1.5 py-1 transition-colors ${le===s?"bg-accent text-text-inverse":"icon-link hover:bg-surface-hover"}`,title:d,children:e.jsx(x,{className:"w-3.5 h-3.5"})},s))}),e.jsxs("button",{onClick:()=>j(s=>!s),"aria-pressed":i,className:`relative rounded border border-surface-border px-1.5 py-1 transition-colors ${i?"bg-accent text-text-inverse":"icon-link hover:bg-surface-hover"}`,title:"Faceted query",children:[e.jsx(Xt,{className:"w-3.5 h-3.5"}),z>0&&e.jsx("span",{className:"absolute -right-1 -top-1 flex h-3.5 min-w-[14px] items-center justify-center rounded-full bg-accent px-0.5 text-2xs font-medium text-text-inverse",children:z})]}),e.jsxs("div",{className:"flex items-center gap-0.5",children:[e.jsx("button",{onClick:()=>We(),disabled:ve,className:"inline-flex h-7 w-7 items-center justify-center rounded icon-link hover:bg-surface-hover disabled:opacity-50",title:"Refresh",children:e.jsx(Jt,{className:`w-4 h-4 ${ve?"animate-spin":""}`})}),e.jsx("button",{onClick:ze,className:"inline-flex h-7 w-7 items-center justify-center rounded icon-link hover:bg-surface-hover",title:"Pin this view — save the current filters to your Pinned section","data-testid":"pin-current-view",children:e.jsx(Zt,{className:"w-4 h-4"})})]})]})}),e.jsx(Ts,{selectedCount:y.size,onClearSelection:()=>v(new Set),onSetPriority:st,onClaim:at,onAssign:()=>Y(!0),onUnassign:lt,onTriage:()=>W(!0),onCancel:()=>X(!0),isPriorityPending:he.isPending,isClaimPending:ge.isPending,isAssignPending:ee.isPending,isUnassignPending:fe.isPending,isTriagePending:te.isPending,isCancelPending:V.isPending,cancelLabel:ie}),(h.facets&&Object.keys(h.facets).length>0||h.jeopardy)&&e.jsxs("div",{className:"bg-surface/98 backdrop-blur-sm border-b border-surface-border/30 -mx-page-x px-page-x py-2 flex items-center gap-1.5 flex-wrap",children:[h.jeopardy&&e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full bg-status-error px-2.5 py-0.5 text-2xs font-semibold text-text-inverse",children:[e.jsx(es,{className:"w-2.5 h-2.5",strokeWidth:2.5}),"in jeopardy",Ce&&e.jsxs("span",{className:"font-mono font-normal opacity-90",children:["> ",Ce]}),e.jsx("button",{onClick:()=>N({...h,jeopardy:void 0}),className:"ml-0.5 -mr-0.5 flex items-center text-text-inverse/70 hover:text-text-inverse transition-colors","aria-label":"Clear jeopardy filter",children:e.jsx(re,{className:"w-2.5 h-2.5"})})]}),Object.entries(h.facets??{}).map(([s,d])=>e.jsxs("span",{className:"inline-flex items-center gap-1 rounded-full border border-accent/25 bg-accent/8 px-2.5 py-0.5 text-2xs font-medium text-accent/90",children:[e.jsx("span",{className:"font-mono text-text-tertiary",children:s}),e.jsx("span",{className:"text-text-quaternary",children:"="}),e.jsx("span",{className:"font-mono max-w-[160px] truncate",title:String(d),children:String(d)}),e.jsx("button",{onClick:()=>$e(s),className:"ml-0.5 -mr-0.5 flex items-center text-text-quaternary hover:text-status-error transition-colors","aria-label":`Remove ${s} filter`,children:e.jsx(re,{className:"w-2.5 h-2.5"})})]},s)),Object.keys(h.facets??{}).length>1&&e.jsx("button",{onClick:()=>N({...h,facets:void 0}),className:"text-2xs text-text-quaternary hover:text-text-secondary transition-colors px-1",children:"clear all"})]})]}),_&&e.jsx("div",{className:"mb-4 px-4 py-3 rounded-md bg-status-error/10 border border-status-error/20 text-xs text-status-error",children:_.message==="Session expired"?"Your session has expired. Please log in again.":`Failed to load escalations: ${_.message}`}),Z?e.jsx(os,{escalations:C,highlightKeys:me,onRowClick:s=>t(`/escalations/detail/${s.id}`,{state:{from:"/escalations/available"}}),total:w,page:l.page,totalPages:Math.ceil(w/ye),onPageChange:l.setPage}):Xe?e.jsx(ms,{role:R,listSchema:De,listSchemaVersion:Ge,activeEscalations:C,groups:Ke,onRowClick:s=>t(`/escalations/detail/${s.id}`,{state:{from:"/escalations/available"}}),onOpenGroup:s=>t(s),onAddFacet:(s,d)=>N({...h,facets:{...h.facets??{},[s]:typeof d=="object"&&d!==null?JSON.stringify(d):d}}),total:w,page:l.page,totalPages:l.totalPages(w),pageSize:l.pageSize,onPageChange:l.setPage,onPageSizeChange:l.setPageSize}):e.jsxs(e.Fragment,{children:[e.jsx(gs,{columns:dt,data:C,layout:"fixed",...cs(ne.layout),keyFn:s=>s.id,onRowClick:s=>t(`/escalations/detail/${s.id}`,{state:{from:"/escalations/available"}}),isLoading:Qe,emptyMessage:_?"Unable to load data":"No escalations"}),e.jsx(fs,{page:l.page,totalPages:l.totalPages(w),onPageChange:l.setPage,total:w,pageSize:l.pageSize,onPageSizeChange:l.setPageSize})]}),e.jsx(Os,{claimTarget:b,onClose:()=>f(null),claimDuration:r,onDurationChange:s=>{k(s),E(0)},claimDurations:p,customClaimMinutes:P,onCustomClaimChange:T,onClaim:tt,isPending:xe.isPending}),e.jsx(As,{open:Oe,onClose:()=>W(!1),selectedCount:y.size,onSubmit:nt,isPending:te.isPending}),e.jsx(as,{open:Le,onClose:()=>Y(!1),selectedCount:y.size,selectedRoles:Je,claimedCount:Ze,onSubmit:it,isPending:ee.isPending}),e.jsx(ns,{open:Me,onClose:()=>X(!1),onConfirm:rt,selectedCount:y.size,isPending:V.isPending,error:V.error,actionLabel:typeof ie=="string"?ie:void 0})]})}export{ra as AvailableEscalationsPage};
|
|
2
|
-
//# sourceMappingURL=AvailableEscalationsPage-GFn8Sgg1.js.map
|