@open-mercato/core 0.6.4-develop.4217.1.c9aa050183 → 0.6.4-develop.4239.1.4a264a5828
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/.turbo/turbo-build.log +2 -2
- package/dist/generated/entities/staff_time_entry/index.js +37 -0
- package/dist/generated/entities/staff_time_entry/index.js.map +7 -0
- package/dist/generated/entities/staff_time_entry_segment/index.js +23 -0
- package/dist/generated/entities/staff_time_entry_segment/index.js.map +7 -0
- package/dist/generated/entities/staff_time_project/index.js +35 -0
- package/dist/generated/entities/staff_time_project/index.js.map +7 -0
- package/dist/generated/entities/staff_time_project_member/index.js +29 -0
- package/dist/generated/entities/staff_time_project_member/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +5 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +64 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/helpers/integration/timesheetFixtures.js +50 -0
- package/dist/helpers/integration/timesheetFixtures.js.map +7 -0
- package/dist/modules/attachments/api/library/[id]/route.js +20 -16
- package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
- package/dist/modules/attachments/api/route.js +18 -14
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/auth/api/roles/acl/route.js +10 -4
- package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
- package/dist/modules/auth/api/sidebar/preferences/route.js +27 -20
- package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
- package/dist/modules/auth/api/users/acl/route.js +16 -11
- package/dist/modules/auth/api/users/acl/route.js.map +2 -2
- package/dist/modules/auth/commands/users.js +87 -71
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/services/sidebarPreferencesService.js +39 -30
- package/dist/modules/auth/services/sidebarPreferencesService.js.map +2 -2
- package/dist/modules/business_rules/backend/logs/[id]/page.js +24 -5
- package/dist/modules/business_rules/backend/logs/[id]/page.js.map +2 -2
- package/dist/modules/catalog/api/offers/route.js +15 -5
- package/dist/modules/catalog/api/offers/route.js.map +2 -2
- package/dist/modules/catalog/commands/categories.js +61 -12
- package/dist/modules/catalog/commands/categories.js.map +2 -2
- package/dist/modules/catalog/commands/products.js +79 -54
- package/dist/modules/catalog/commands/products.js.map +2 -2
- package/dist/modules/catalog/commands/variants.js +29 -16
- package/dist/modules/catalog/commands/variants.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/[id]/page.js +19 -2
- package/dist/modules/currencies/backend/currencies/[id]/page.js.map +2 -2
- package/dist/modules/currencies/commands/currencies.js +15 -8
- package/dist/modules/currencies/commands/currencies.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/users.js +27 -26
- package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
- package/dist/modules/customer_accounts/api/password/reset-confirm.js +5 -5
- package/dist/modules/customer_accounts/api/password/reset-confirm.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js +11 -10
- package/dist/modules/customer_accounts/api/portal/users/[id]/roles.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js +27 -7
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +27 -7
- package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/[id]/page.js +29 -8
- package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
- package/dist/modules/customers/commands/addresses.js +35 -21
- package/dist/modules/customers/commands/addresses.js.map +2 -2
- package/dist/modules/customers/commands/companies.js +163 -162
- package/dist/modules/customers/commands/companies.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +3 -4
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js +19 -22
- package/dist/modules/customers/commands/interactions.js.map +2 -2
- package/dist/modules/customers/commands/people.js +18 -15
- package/dist/modules/customers/commands/people.js.map +2 -2
- package/dist/modules/customers/commands/personCompanyLinks.js +105 -94
- package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
- package/dist/modules/customers/commands/pipeline-stages.js +30 -23
- package/dist/modules/customers/commands/pipeline-stages.js.map +2 -2
- package/dist/modules/customers/commands/pipelines.js +27 -20
- package/dist/modules/customers/commands/pipelines.js.map +2 -2
- package/dist/modules/customers/commands/tags.js +13 -5
- package/dist/modules/customers/commands/tags.js.map +2 -2
- package/dist/modules/dashboards/api/users/widgets/route.js +0 -1
- package/dist/modules/dashboards/api/users/widgets/route.js.map +2 -2
- package/dist/modules/dashboards/api/widgets/data/route.js +29 -1
- package/dist/modules/dashboards/api/widgets/data/route.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-engine.js +4 -4
- package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-run-service.js +51 -27
- package/dist/modules/data_sync/lib/sync-run-service.js.map +2 -2
- package/dist/modules/directory/commands/organizations.js +192 -158
- package/dist/modules/directory/commands/organizations.js.map +3 -3
- package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js +22 -16
- package/dist/modules/inbox_ops/api/emails/[id]/reprocess/route.js.map +2 -2
- package/dist/modules/messages/commands/messages.js +77 -75
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/messages/commands/shared.js +132 -132
- package/dist/modules/messages/commands/shared.js.map +2 -2
- package/dist/modules/perspectives/api/[tableId]/route.js +37 -26
- package/dist/modules/perspectives/api/[tableId]/route.js.map +2 -2
- package/dist/modules/progress/acl.js +8 -4
- package/dist/modules/progress/acl.js.map +2 -2
- package/dist/modules/resources/commands/resources.js +125 -117
- package/dist/modules/resources/commands/resources.js.map +2 -2
- package/dist/modules/resources/commands/tags.js +7 -3
- package/dist/modules/resources/commands/tags.js.map +2 -2
- package/dist/modules/sales/api/quotes/send/route.js +12 -11
- package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +629 -478
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +146 -146
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/sales/commands/returns.js +68 -60
- package/dist/modules/sales/commands/returns.js.map +2 -2
- package/dist/modules/staff/acl.js +10 -1
- package/dist/modules/staff/acl.js.map +2 -2
- package/dist/modules/staff/analytics.js +33 -0
- package/dist/modules/staff/analytics.js.map +7 -0
- package/dist/modules/staff/api/guards.js +31 -0
- package/dist/modules/staff/api/guards.js.map +7 -0
- package/dist/modules/staff/api/interceptors.js +96 -0
- package/dist/modules/staff/api/interceptors.js.map +7 -0
- package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js +170 -0
- package/dist/modules/staff/api/timesheets/my-projects/[projectId]/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/my-projects/route.js +103 -0
- package/dist/modules/staff/api/timesheets/my-projects/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/projects/kpis/route.js +147 -0
- package/dist/modules/staff/api/timesheets/projects/kpis/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js +171 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js +180 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/segments/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +155 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js +173 -0
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js +260 -0
- package/dist/modules/staff/api/timesheets/time-entries/bulk/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-entries/route.js +188 -0
- package/dist/modules/staff/api/timesheets/time-entries/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js +159 -0
- package/dist/modules/staff/api/timesheets/time-projects/[id]/employees/route.js.map +7 -0
- package/dist/modules/staff/api/timesheets/time-projects/route.js +230 -0
- package/dist/modules/staff/api/timesheets/time-projects/route.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/page.js +710 -0
- package/dist/modules/staff/backend/staff/timesheets/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/page.meta.js +22 -0
- package/dist/modules/staff/backend/staff/timesheets/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js +125 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js +418 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js +79 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js +16 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/create/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js +602 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js +25 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.meta.js.map +7 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js +123 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/projectFormConfig.js.map +7 -0
- package/dist/modules/staff/cli.js +38 -1
- package/dist/modules/staff/cli.js.map +2 -2
- package/dist/modules/staff/commands/index.js +2 -0
- package/dist/modules/staff/commands/index.js.map +2 -2
- package/dist/modules/staff/commands/leave-requests.js +30 -28
- package/dist/modules/staff/commands/leave-requests.js.map +3 -3
- package/dist/modules/staff/commands/team-members.js +21 -20
- package/dist/modules/staff/commands/team-members.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-entries.js +409 -0
- package/dist/modules/staff/commands/timesheets-entries.js.map +7 -0
- package/dist/modules/staff/commands/timesheets-projects.js +618 -0
- package/dist/modules/staff/commands/timesheets-projects.js.map +7 -0
- package/dist/modules/staff/data/enrichers.js +104 -0
- package/dist/modules/staff/data/enrichers.js.map +7 -0
- package/dist/modules/staff/data/entities.js +226 -1
- package/dist/modules/staff/data/entities.js.map +2 -2
- package/dist/modules/staff/data/validators.js +113 -1
- package/dist/modules/staff/data/validators.js.map +2 -2
- package/dist/modules/staff/events.js +13 -1
- package/dist/modules/staff/events.js.map +2 -2
- package/dist/modules/staff/lib/crud.js +7 -1
- package/dist/modules/staff/lib/crud.js.map +2 -2
- package/dist/modules/staff/lib/staffMemberResolver.js +15 -0
- package/dist/modules/staff/lib/staffMemberResolver.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.js +60 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectsKpis.js +260 -0
- package/dist/modules/staff/lib/timesheets-projects/computeProjectsKpis.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/dateBuckets.js +41 -0
- package/dist/modules/staff/lib/timesheets-projects/dateBuckets.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/initials.js +10 -0
- package/dist/modules/staff/lib/timesheets-projects/initials.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/kpiMath.js +12 -0
- package/dist/modules/staff/lib/timesheets-projects/kpiMath.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects/listProjectMembersPreview.js +55 -0
- package/dist/modules/staff/lib/timesheets-projects/listProjectMembersPreview.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/HoursSparkline.js +66 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/HoursSparkline.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js +81 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectCard.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.js +58 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.js +152 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js +37 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.js +57 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.js +50 -0
- package/dist/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/AddRowDropdown.js +163 -0
- package/dist/modules/staff/lib/timesheets-ui/AddRowDropdown.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js +209 -0
- package/dist/modules/staff/lib/timesheets-ui/CalendarPicker.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/ColorPicker.js +52 -0
- package/dist/modules/staff/lib/timesheets-ui/ColorPicker.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js +77 -0
- package/dist/modules/staff/lib/timesheets-ui/CreateProjectDialog.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/ListView.js +173 -0
- package/dist/modules/staff/lib/timesheets-ui/ListView.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/ProjectColorDot.js +32 -0
- package/dist/modules/staff/lib/timesheets-ui/ProjectColorDot.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/TimerBar.js +270 -0
- package/dist/modules/staff/lib/timesheets-ui/TimerBar.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/ViewSwitcher.js +57 -0
- package/dist/modules/staff/lib/timesheets-ui/ViewSwitcher.js.map +7 -0
- package/dist/modules/staff/lib/timesheets-ui/colors.js +43 -0
- package/dist/modules/staff/lib/timesheets-ui/colors.js.map +7 -0
- package/dist/modules/staff/migrations/Migration20260326135612.js +24 -0
- package/dist/modules/staff/migrations/Migration20260326135612.js.map +7 -0
- package/dist/modules/staff/migrations/Migration20260413102715.js +23 -0
- package/dist/modules/staff/migrations/Migration20260413102715.js.map +7 -0
- package/dist/modules/staff/migrations/Migration20260413111602.js +13 -0
- package/dist/modules/staff/migrations/Migration20260413111602.js.map +7 -0
- package/dist/modules/staff/migrations/Migration20260511112759.js +19 -0
- package/dist/modules/staff/migrations/Migration20260511112759.js.map +7 -0
- package/dist/modules/staff/search.js +35 -0
- package/dist/modules/staff/search.js.map +2 -2
- package/dist/modules/staff/setup.js +15 -1
- package/dist/modules/staff/setup.js.map +2 -2
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.js +16 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js +126 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.js +26 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/config.js +15 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/config.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js +238 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.js +26 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.js.map +7 -0
- package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js +145 -0
- package/dist/modules/staff/widgets/injection/timer-sidebar-indicator/widget.js.map +7 -0
- package/dist/modules/staff/widgets/injection-table.js +12 -0
- package/dist/modules/staff/widgets/injection-table.js.map +7 -0
- package/dist/modules/sync_excel/api/import/route.js +19 -17
- package/dist/modules/sync_excel/api/import/route.js.map +2 -2
- package/dist/modules/translations/commands/translations.js +22 -19
- package/dist/modules/translations/commands/translations.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.js +24 -6
- package/dist/modules/workflows/backend/events/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.js +27 -5
- package/dist/modules/workflows/backend/instances/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.js +25 -6
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
- package/generated/entities/staff_time_entry/index.ts +17 -0
- package/generated/entities/staff_time_entry_segment/index.ts +10 -0
- package/generated/entities/staff_time_project/index.ts +16 -0
- package/generated/entities/staff_time_project_member/index.ts +13 -0
- package/generated/entities.ids.generated.ts +5 -1
- package/generated/entity-fields-registry.ts +64 -0
- package/package.json +7 -7
- package/src/helpers/integration/timesheetFixtures.ts +61 -0
- package/src/modules/attachments/api/library/[id]/route.ts +24 -17
- package/src/modules/attachments/api/route.ts +20 -14
- package/src/modules/auth/api/roles/acl/route.ts +11 -5
- package/src/modules/auth/api/sidebar/preferences/route.ts +33 -24
- package/src/modules/auth/api/users/acl/route.ts +17 -12
- package/src/modules/auth/commands/users.ts +96 -80
- package/src/modules/auth/services/sidebarPreferencesService.ts +40 -32
- package/src/modules/business_rules/backend/logs/[id]/page.tsx +32 -7
- package/src/modules/catalog/api/offers/route.ts +20 -5
- package/src/modules/catalog/commands/categories.ts +61 -12
- package/src/modules/catalog/commands/products.ts +93 -60
- package/src/modules/catalog/commands/variants.ts +29 -16
- package/src/modules/currencies/backend/currencies/[id]/page.tsx +21 -2
- package/src/modules/currencies/commands/currencies.ts +27 -14
- package/src/modules/currencies/i18n/de.json +1 -0
- package/src/modules/currencies/i18n/en.json +1 -0
- package/src/modules/currencies/i18n/es.json +1 -0
- package/src/modules/currencies/i18n/pl.json +1 -0
- package/src/modules/customer_accounts/api/admin/users.ts +31 -26
- package/src/modules/customer_accounts/api/password/reset-confirm.ts +5 -6
- package/src/modules/customer_accounts/api/portal/users/[id]/roles.ts +14 -13
- package/src/modules/customer_accounts/backend/customer_accounts/roles/[id]/page.tsx +34 -11
- package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +34 -11
- package/src/modules/customers/backend/customers/people/[id]/page.tsx +35 -11
- package/src/modules/customers/commands/addresses.ts +35 -23
- package/src/modules/customers/commands/companies.ts +166 -165
- package/src/modules/customers/commands/deals.ts +2 -4
- package/src/modules/customers/commands/interactions.ts +20 -26
- package/src/modules/customers/commands/people.ts +18 -15
- package/src/modules/customers/commands/personCompanyLinks.ts +109 -100
- package/src/modules/customers/commands/pipeline-stages.ts +31 -27
- package/src/modules/customers/commands/pipelines.ts +29 -23
- package/src/modules/customers/commands/tags.ts +13 -5
- package/src/modules/dashboards/api/users/widgets/route.ts +0 -1
- package/src/modules/dashboards/api/widgets/data/route.ts +36 -1
- package/src/modules/data_sync/lib/sync-engine.ts +4 -5
- package/src/modules/data_sync/lib/sync-run-service.ts +57 -28
- package/src/modules/directory/commands/organizations.ts +203 -166
- package/src/modules/inbox_ops/api/emails/[id]/reprocess/route.ts +26 -18
- package/src/modules/messages/commands/messages.ts +82 -80
- package/src/modules/messages/commands/shared.ts +138 -133
- package/src/modules/perspectives/api/[tableId]/route.ts +38 -27
- package/src/modules/progress/acl.ts +4 -0
- package/src/modules/resources/commands/resources.ts +127 -117
- package/src/modules/resources/commands/tags.ts +7 -3
- package/src/modules/sales/api/quotes/send/route.ts +17 -12
- package/src/modules/sales/commands/documents.ts +673 -481
- package/src/modules/sales/commands/payments.ts +158 -152
- package/src/modules/sales/commands/returns.ts +74 -63
- package/src/modules/staff/acl.ts +11 -0
- package/src/modules/staff/analytics.ts +30 -0
- package/src/modules/staff/api/guards.ts +59 -0
- package/src/modules/staff/api/interceptors.ts +122 -0
- package/src/modules/staff/api/timesheets/my-projects/[projectId]/route.ts +191 -0
- package/src/modules/staff/api/timesheets/my-projects/route.ts +115 -0
- package/src/modules/staff/api/timesheets/projects/kpis/route.ts +159 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/segments/[segmentId]/route.ts +187 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/segments/route.ts +191 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +168 -0
- package/src/modules/staff/api/timesheets/time-entries/[id]/timer-stop/route.ts +191 -0
- package/src/modules/staff/api/timesheets/time-entries/bulk/route.ts +292 -0
- package/src/modules/staff/api/timesheets/time-entries/route.ts +193 -0
- package/src/modules/staff/api/timesheets/time-projects/[id]/employees/route.ts +167 -0
- package/src/modules/staff/api/timesheets/time-projects/route.ts +244 -0
- package/src/modules/staff/backend/staff/timesheets/page.meta.ts +20 -0
- package/src/modules/staff/backend/staff/timesheets/page.tsx +899 -0
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/edit/page.tsx +141 -0
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/timesheets/projects/[id]/page.tsx +579 -0
- package/src/modules/staff/backend/staff/timesheets/projects/create/page.meta.ts +12 -0
- package/src/modules/staff/backend/staff/timesheets/projects/create/page.tsx +90 -0
- package/src/modules/staff/backend/staff/timesheets/projects/page.meta.ts +23 -0
- package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +765 -0
- package/src/modules/staff/backend/staff/timesheets/projects/projectFormConfig.ts +138 -0
- package/src/modules/staff/cli.ts +40 -1
- package/src/modules/staff/commands/index.ts +2 -0
- package/src/modules/staff/commands/leave-requests.ts +37 -29
- package/src/modules/staff/commands/team-members.ts +25 -20
- package/src/modules/staff/commands/timesheets-entries.ts +504 -0
- package/src/modules/staff/commands/timesheets-projects.ts +699 -0
- package/src/modules/staff/data/enrichers.ts +134 -0
- package/src/modules/staff/data/entities.ts +198 -0
- package/src/modules/staff/data/validators.ts +129 -0
- package/src/modules/staff/events.ts +13 -0
- package/src/modules/staff/i18n/de.json +209 -1
- package/src/modules/staff/i18n/en.json +209 -1
- package/src/modules/staff/i18n/es.json +209 -1
- package/src/modules/staff/i18n/pl.json +209 -1
- package/src/modules/staff/lib/crud.ts +8 -0
- package/src/modules/staff/lib/staffMemberResolver.ts +22 -0
- package/src/modules/staff/lib/timesheets-projects/computeProjectHoursTrend.ts +89 -0
- package/src/modules/staff/lib/timesheets-projects/computeProjectsKpis.ts +311 -0
- package/src/modules/staff/lib/timesheets-projects/dateBuckets.ts +37 -0
- package/src/modules/staff/lib/timesheets-projects/initials.ts +6 -0
- package/src/modules/staff/lib/timesheets-projects/kpiMath.ts +8 -0
- package/src/modules/staff/lib/timesheets-projects/listProjectMembersPreview.ts +83 -0
- package/src/modules/staff/lib/timesheets-projects-ui/HoursSparkline.tsx +75 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ProjectCard.tsx +110 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ProjectMembersAvatarStack.tsx +73 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ProjectsKpiStrip.tsx +185 -0
- package/src/modules/staff/lib/timesheets-projects-ui/SavedViewTabs.tsx +53 -0
- package/src/modules/staff/lib/timesheets-projects-ui/ViewModeToggle.tsx +63 -0
- package/src/modules/staff/lib/timesheets-projects-ui/useProjectsViewMode.ts +63 -0
- package/src/modules/staff/lib/timesheets-ui/AddRowDropdown.tsx +188 -0
- package/src/modules/staff/lib/timesheets-ui/CalendarPicker.tsx +229 -0
- package/src/modules/staff/lib/timesheets-ui/ColorPicker.tsx +65 -0
- package/src/modules/staff/lib/timesheets-ui/CreateProjectDialog.tsx +99 -0
- package/src/modules/staff/lib/timesheets-ui/ListView.tsx +230 -0
- package/src/modules/staff/lib/timesheets-ui/ProjectColorDot.tsx +40 -0
- package/src/modules/staff/lib/timesheets-ui/TimerBar.tsx +327 -0
- package/src/modules/staff/lib/timesheets-ui/ViewSwitcher.tsx +60 -0
- package/src/modules/staff/lib/timesheets-ui/colors.ts +58 -0
- package/src/modules/staff/migrations/.snapshot-open-mercato.json +1148 -0
- package/src/modules/staff/migrations/Migration20260326135612.ts +26 -0
- package/src/modules/staff/migrations/Migration20260413102715.ts +25 -0
- package/src/modules/staff/migrations/Migration20260413111602.ts +13 -0
- package/src/modules/staff/migrations/Migration20260511112759.ts +21 -0
- package/src/modules/staff/search.ts +35 -0
- package/src/modules/staff/setup.ts +15 -0
- package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/config.ts +17 -0
- package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.client.tsx +158 -0
- package/src/modules/staff/widgets/dashboard/timesheets-hours-by-project/widget.ts +25 -0
- package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/config.ts +15 -0
- package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.tsx +297 -0
- package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.ts +25 -0
- package/src/modules/staff/widgets/injection/timer-sidebar-indicator/widget.tsx +161 -0
- package/src/modules/staff/widgets/injection-table.ts +10 -0
- package/src/modules/sync_excel/api/import/route.ts +23 -18
- package/src/modules/translations/commands/translations.ts +49 -41
- package/src/modules/workflows/backend/events/[id]/page.tsx +32 -10
- package/src/modules/workflows/backend/instances/[id]/page.tsx +33 -9
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +33 -10
- package/src/modules/workflows/i18n/de.json +1 -0
- package/src/modules/workflows/i18n/en.json +1 -0
- package/src/modules/workflows/i18n/es.json +1 -0
- package/src/modules/workflows/i18n/pl.json +1 -0
|
@@ -30,31 +30,34 @@ const saveTranslationCommand = {
|
|
|
30
30
|
},
|
|
31
31
|
async execute(input, ctx) {
|
|
32
32
|
const db = resolveDb(ctx);
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
33
|
+
const rowId = await db.transaction().execute(async (trx) => {
|
|
34
|
+
const existing = await trx.selectFrom("entity_translations").select(["id"]).where("entity_type", "=", input.entityType).where("entity_id", "=", input.entityId).where(sql`tenant_id is not distinct from ${input.tenantId}`).where(sql`organization_id is not distinct from ${input.organizationId}`).executeTakeFirst();
|
|
35
|
+
if (existing) {
|
|
36
|
+
await trx.updateTable("entity_translations").set({
|
|
37
|
+
translations: sql`${JSON.stringify(input.translations)}::jsonb`,
|
|
38
|
+
updated_at: sql`now()`
|
|
39
|
+
}).where("id", "=", existing.id).execute();
|
|
40
|
+
} else {
|
|
41
|
+
await trx.insertInto("entity_translations").values({
|
|
42
|
+
entity_type: input.entityType,
|
|
43
|
+
entity_id: input.entityId,
|
|
44
|
+
organization_id: input.organizationId,
|
|
45
|
+
tenant_id: input.tenantId,
|
|
46
|
+
translations: sql`${JSON.stringify(input.translations)}::jsonb`,
|
|
47
|
+
created_at: sql`now()`,
|
|
48
|
+
updated_at: sql`now()`
|
|
49
|
+
}).execute();
|
|
50
|
+
}
|
|
51
|
+
const saved = await trx.selectFrom("entity_translations").select(["id"]).where("entity_type", "=", input.entityType).where("entity_id", "=", input.entityId).where(sql`tenant_id is not distinct from ${input.tenantId}`).where(sql`organization_id is not distinct from ${input.organizationId}`).executeTakeFirst();
|
|
52
|
+
return saved?.id ?? "";
|
|
53
|
+
});
|
|
50
54
|
await emitTranslationsEvent("translations.translation.updated", {
|
|
51
55
|
entityType: input.entityType,
|
|
52
56
|
entityId: input.entityId,
|
|
53
57
|
organizationId: input.organizationId,
|
|
54
58
|
tenantId: input.tenantId
|
|
55
59
|
}, { persistent: true }).catch(() => void 0);
|
|
56
|
-
|
|
57
|
-
return { rowId: saved?.id ?? "" };
|
|
60
|
+
return { rowId };
|
|
58
61
|
},
|
|
59
62
|
async captureAfter(input, _result, ctx) {
|
|
60
63
|
const db = resolveDb(ctx);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/translations/commands/translations.ts"],
|
|
4
|
-
"sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { ensureTenantScope } from '@open-mercato/shared/lib/commands/scope'\nimport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { type Kysely, sql } from 'kysely'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { emitTranslationsEvent } from '../events'\n\ntype TranslationSnapshot = {\n id: string | null\n entityType: string\n entityId: string\n translations: Record<string, Record<string, string | null>> | null\n organizationId: string | null\n tenantId: string\n}\n\ntype TranslationUndoPayload = {\n before?: TranslationSnapshot | null\n after?: TranslationSnapshot | null\n}\n\ntype SaveInput = {\n entityType: string\n entityId: string\n translations: Record<string, Record<string, string | null>>\n organizationId: string | null\n tenantId: string\n}\n\ntype DeleteInput = {\n entityType: string\n entityId: string\n organizationId: string | null\n tenantId: string\n}\n\nfunction resolveDb(ctx: CommandRuntimeContext): Kysely<any> {\n const em = ctx.container.resolve('em') as EntityManager\n return em.getKysely<any>()\n}\n\nasync function loadTranslationSnapshot(\n db: Kysely<any>,\n entityType: string,\n entityId: string,\n tenantId: string,\n organizationId: string | null,\n): Promise<TranslationSnapshot | null> {\n const row = await (db as any)\n .selectFrom('entity_translations')\n .selectAll()\n .where('entity_type', '=', entityType)\n .where('entity_id', '=', entityId)\n .where(sql<boolean>`tenant_id is not distinct from ${tenantId}`)\n .where(sql<boolean>`organization_id is not distinct from ${organizationId}`)\n .executeTakeFirst() as Record<string, any> | undefined\n\n if (!row) return null\n return {\n id: row.id,\n entityType: row.entity_type,\n entityId: row.entity_id,\n translations: row.translations ?? null,\n organizationId: row.organization_id ?? null,\n tenantId: row.tenant_id,\n }\n}\n\nconst saveTranslationCommand: CommandHandler<SaveInput, { rowId: string }> = {\n id: 'translations.translation.save',\n\n async prepare(input, ctx) {\n ensureTenantScope(ctx, input.tenantId)\n const db = resolveDb(ctx)\n const snapshot = await loadTranslationSnapshot(db, input.entityType, input.entityId, input.tenantId, input.organizationId)\n return { before: snapshot }\n },\n\n async execute(input, ctx) {\n const db = resolveDb(ctx) as any\n const existing = await db\n .selectFrom('entity_translations')\n .select(['id'])\n .where('entity_type', '=', input.entityType)\n .where('entity_id', '=', input.entityId)\n .where(sql<boolean>`tenant_id is not distinct from ${input.tenantId}`)\n .where(sql<boolean>`organization_id is not distinct from ${input.organizationId}`)\n .executeTakeFirst() as { id: string } | undefined\n\n if (existing) {\n await db\n .updateTable('entity_translations')\n .set({\n translations: sql`${JSON.stringify(input.translations)}::jsonb`,\n updated_at: sql`now()`,\n } as any)\n .where('id', '=', existing.id)\n .execute()\n } else {\n await db\n .insertInto('entity_translations')\n .values({\n entity_type: input.entityType,\n entity_id: input.entityId,\n organization_id: input.organizationId,\n tenant_id: input.tenantId,\n translations: sql`${JSON.stringify(input.translations)}::jsonb`,\n created_at: sql`now()`,\n updated_at: sql`now()`,\n } as any)\n .execute()\n }\n\n await emitTranslationsEvent('translations.translation.updated', {\n entityType: input.entityType,\n entityId: input.entityId,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n }, { persistent: true }).catch(() => undefined)\n\n const saved = await db\n .selectFrom('entity_translations')\n .select(['id'])\n .where('entity_type', '=', input.entityType)\n .where('entity_id', '=', input.entityId)\n .where(sql<boolean>`tenant_id is not distinct from ${input.tenantId}`)\n .where(sql<boolean>`organization_id is not distinct from ${input.organizationId}`)\n .executeTakeFirst() as { id: string } | undefined\n\n return { rowId: saved?.id ?? '' }\n },\n\n async captureAfter(input, _result, ctx) {\n const db = resolveDb(ctx)\n return await loadTranslationSnapshot(db, input.entityType, input.entityId, input.tenantId, input.organizationId)\n },\n\n async buildLog({ snapshots, result }) {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as TranslationSnapshot | null | undefined\n const after = snapshots.after as TranslationSnapshot | null | undefined\n return {\n actionLabel: translate('translations.audit.save', 'Save translation'),\n resourceKind: 'translations.translation',\n resourceId: result.rowId,\n tenantId: after?.tenantId ?? before?.tenantId ?? null,\n organizationId: after?.organizationId ?? before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: { before: before ?? null, after: after ?? null } satisfies TranslationUndoPayload,\n },\n }\n },\n\n async undo({ logEntry, ctx }) {\n const payload = extractUndoPayload<TranslationUndoPayload>(logEntry)\n const before = payload?.before ?? null\n const db = resolveDb(ctx) as any\n\n if (!before || !before.translations) {\n // Was a create \u2014 delete the record\n const resourceId = logEntry?.resourceId\n if (resourceId) {\n await db.deleteFrom('entity_translations').where('id', '=', resourceId).execute()\n }\n } else {\n // Was an update \u2014 restore previous translations\n const existing = await db\n .selectFrom('entity_translations')\n .select(['id'])\n .where('entity_type', '=', before.entityType)\n .where('entity_id', '=', before.entityId)\n .where(sql<boolean>`tenant_id is not distinct from ${before.tenantId}`)\n .where(sql<boolean>`organization_id is not distinct from ${before.organizationId}`)\n .executeTakeFirst() as { id: string } | undefined\n\n if (existing) {\n await db\n .updateTable('entity_translations')\n .set({\n translations: sql`${JSON.stringify(before.translations)}::jsonb`,\n updated_at: sql`now()`,\n } as any)\n .where('id', '=', existing.id)\n .execute()\n } else {\n await db\n .insertInto('entity_translations')\n .values({\n entity_type: before.entityType,\n entity_id: before.entityId,\n organization_id: before.organizationId,\n tenant_id: before.tenantId,\n translations: sql`${JSON.stringify(before.translations)}::jsonb`,\n created_at: sql`now()`,\n updated_at: sql`now()`,\n } as any)\n .execute()\n }\n }\n },\n}\n\nconst deleteTranslationCommand: CommandHandler<DeleteInput, { deleted: boolean }> = {\n id: 'translations.translation.delete',\n\n async prepare(input, ctx) {\n ensureTenantScope(ctx, input.tenantId)\n const db = resolveDb(ctx)\n const snapshot = await loadTranslationSnapshot(db, input.entityType, input.entityId, input.tenantId, input.organizationId)\n return { before: snapshot }\n },\n\n async execute(input, ctx) {\n const db = resolveDb(ctx) as any\n const result = await db\n .deleteFrom('entity_translations')\n .where('entity_type', '=', input.entityType)\n .where('entity_id', '=', input.entityId)\n .where(sql<boolean>`tenant_id is not distinct from ${input.tenantId}`)\n .where(sql<boolean>`organization_id is not distinct from ${input.organizationId}`)\n .executeTakeFirst() as { numDeletedRows?: bigint | number } | undefined\n const count = Number(result?.numDeletedRows ?? 0)\n\n await emitTranslationsEvent('translations.translation.deleted', {\n entityType: input.entityType,\n entityId: input.entityId,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n }, { persistent: true }).catch(() => undefined)\n\n return { deleted: count > 0 }\n },\n\n async buildLog({ snapshots }) {\n const before = snapshots.before as TranslationSnapshot | null | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('translations.audit.delete', 'Delete translation'),\n resourceKind: 'translations.translation',\n resourceId: before.id ?? undefined,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies TranslationUndoPayload,\n },\n }\n },\n\n async undo({ logEntry, ctx }) {\n const payload = extractUndoPayload<TranslationUndoPayload>(logEntry)\n const before = payload?.before\n if (!before || !before.translations) return\n const db = resolveDb(ctx) as any\n\n const existing = await db\n .selectFrom('entity_translations')\n .select(['id'])\n .where('entity_type', '=', before.entityType)\n .where('entity_id', '=', before.entityId)\n .where(sql<boolean>`tenant_id is not distinct from ${before.tenantId}`)\n .where(sql<boolean>`organization_id is not distinct from ${before.organizationId}`)\n .executeTakeFirst() as { id: string } | undefined\n\n if (!existing) {\n await db\n .insertInto('entity_translations')\n .values({\n entity_type: before.entityType,\n entity_id: before.entityId,\n organization_id: before.organizationId,\n tenant_id: before.tenantId,\n translations: sql`${JSON.stringify(before.translations)}::jsonb`,\n created_at: sql`now()`,\n updated_at: sql`now()`,\n } as any)\n .execute()\n }\n },\n}\n\nregisterCommand(saveTranslationCommand)\nregisterCommand(deleteTranslationCommand)\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,uBAAuB;AAEhC,SAAS,yBAAyB;AAClC,SAAS,0BAA0B;AACnC,SAAS,2BAA2B;AACpC,SAAsB,WAAW;AAEjC,SAAS,6BAA6B;AA+BtC,SAAS,UAAU,KAAyC;AAC1D,QAAM,KAAK,IAAI,UAAU,QAAQ,IAAI;AACrC,SAAO,GAAG,UAAe;AAC3B;AAEA,eAAe,wBACb,IACA,YACA,UACA,UACA,gBACqC;AACrC,QAAM,MAAM,MAAO,GAChB,WAAW,qBAAqB,EAChC,UAAU,EACV,MAAM,eAAe,KAAK,UAAU,EACpC,MAAM,aAAa,KAAK,QAAQ,EAChC,MAAM,qCAA8C,QAAQ,EAAE,EAC9D,MAAM,2CAAoD,cAAc,EAAE,EAC1E,iBAAiB;AAEpB,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,YAAY,IAAI;AAAA,IAChB,UAAU,IAAI;AAAA,IACd,cAAc,IAAI,gBAAgB;AAAA,IAClC,gBAAgB,IAAI,mBAAmB;AAAA,IACvC,UAAU,IAAI;AAAA,EAChB;AACF;AAEA,MAAM,yBAAuE;AAAA,EAC3E,IAAI;AAAA,EAEJ,MAAM,QAAQ,OAAO,KAAK;AACxB,sBAAkB,KAAK,MAAM,QAAQ;AACrC,UAAM,KAAK,UAAU,GAAG;AACxB,UAAM,WAAW,MAAM,wBAAwB,IAAI,MAAM,YAAY,MAAM,UAAU,MAAM,UAAU,MAAM,cAAc;AACzH,WAAO,EAAE,QAAQ,SAAS;AAAA,EAC5B;AAAA,EAEA,MAAM,QAAQ,OAAO,KAAK;AACxB,UAAM,KAAK,UAAU,GAAG;
|
|
4
|
+
"sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { ensureTenantScope } from '@open-mercato/shared/lib/commands/scope'\nimport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { type Kysely, sql } from 'kysely'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { emitTranslationsEvent } from '../events'\n\ntype TranslationSnapshot = {\n id: string | null\n entityType: string\n entityId: string\n translations: Record<string, Record<string, string | null>> | null\n organizationId: string | null\n tenantId: string\n}\n\ntype TranslationUndoPayload = {\n before?: TranslationSnapshot | null\n after?: TranslationSnapshot | null\n}\n\ntype SaveInput = {\n entityType: string\n entityId: string\n translations: Record<string, Record<string, string | null>>\n organizationId: string | null\n tenantId: string\n}\n\ntype DeleteInput = {\n entityType: string\n entityId: string\n organizationId: string | null\n tenantId: string\n}\n\nfunction resolveDb(ctx: CommandRuntimeContext): Kysely<any> {\n const em = ctx.container.resolve('em') as EntityManager\n return em.getKysely<any>()\n}\n\nasync function loadTranslationSnapshot(\n db: Kysely<any>,\n entityType: string,\n entityId: string,\n tenantId: string,\n organizationId: string | null,\n): Promise<TranslationSnapshot | null> {\n const row = await (db as any)\n .selectFrom('entity_translations')\n .selectAll()\n .where('entity_type', '=', entityType)\n .where('entity_id', '=', entityId)\n .where(sql<boolean>`tenant_id is not distinct from ${tenantId}`)\n .where(sql<boolean>`organization_id is not distinct from ${organizationId}`)\n .executeTakeFirst() as Record<string, any> | undefined\n\n if (!row) return null\n return {\n id: row.id,\n entityType: row.entity_type,\n entityId: row.entity_id,\n translations: row.translations ?? null,\n organizationId: row.organization_id ?? null,\n tenantId: row.tenant_id,\n }\n}\n\nconst saveTranslationCommand: CommandHandler<SaveInput, { rowId: string }> = {\n id: 'translations.translation.save',\n\n async prepare(input, ctx) {\n ensureTenantScope(ctx, input.tenantId)\n const db = resolveDb(ctx)\n const snapshot = await loadTranslationSnapshot(db, input.entityType, input.entityId, input.tenantId, input.organizationId)\n return { before: snapshot }\n },\n\n async execute(input, ctx) {\n const db = resolveDb(ctx) as any\n\n // Run the lookup + upsert + id read in one transaction so a concurrent\n // writer cannot slip between the existence check and the insert/update.\n const rowId = await db.transaction().execute(async (trx: any) => {\n const existing = await trx\n .selectFrom('entity_translations')\n .select(['id'])\n .where('entity_type', '=', input.entityType)\n .where('entity_id', '=', input.entityId)\n .where(sql<boolean>`tenant_id is not distinct from ${input.tenantId}`)\n .where(sql<boolean>`organization_id is not distinct from ${input.organizationId}`)\n .executeTakeFirst() as { id: string } | undefined\n\n if (existing) {\n await trx\n .updateTable('entity_translations')\n .set({\n translations: sql`${JSON.stringify(input.translations)}::jsonb`,\n updated_at: sql`now()`,\n } as any)\n .where('id', '=', existing.id)\n .execute()\n } else {\n await trx\n .insertInto('entity_translations')\n .values({\n entity_type: input.entityType,\n entity_id: input.entityId,\n organization_id: input.organizationId,\n tenant_id: input.tenantId,\n translations: sql`${JSON.stringify(input.translations)}::jsonb`,\n created_at: sql`now()`,\n updated_at: sql`now()`,\n } as any)\n .execute()\n }\n\n const saved = await trx\n .selectFrom('entity_translations')\n .select(['id'])\n .where('entity_type', '=', input.entityType)\n .where('entity_id', '=', input.entityId)\n .where(sql<boolean>`tenant_id is not distinct from ${input.tenantId}`)\n .where(sql<boolean>`organization_id is not distinct from ${input.organizationId}`)\n .executeTakeFirst() as { id: string } | undefined\n\n return saved?.id ?? ''\n })\n\n // Emit AFTER the write commits \u2014 never announce a change that rolled back.\n await emitTranslationsEvent('translations.translation.updated', {\n entityType: input.entityType,\n entityId: input.entityId,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n }, { persistent: true }).catch(() => undefined)\n\n return { rowId }\n },\n\n async captureAfter(input, _result, ctx) {\n const db = resolveDb(ctx)\n return await loadTranslationSnapshot(db, input.entityType, input.entityId, input.tenantId, input.organizationId)\n },\n\n async buildLog({ snapshots, result }) {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as TranslationSnapshot | null | undefined\n const after = snapshots.after as TranslationSnapshot | null | undefined\n return {\n actionLabel: translate('translations.audit.save', 'Save translation'),\n resourceKind: 'translations.translation',\n resourceId: result.rowId,\n tenantId: after?.tenantId ?? before?.tenantId ?? null,\n organizationId: after?.organizationId ?? before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: { before: before ?? null, after: after ?? null } satisfies TranslationUndoPayload,\n },\n }\n },\n\n async undo({ logEntry, ctx }) {\n const payload = extractUndoPayload<TranslationUndoPayload>(logEntry)\n const before = payload?.before ?? null\n const db = resolveDb(ctx) as any\n\n if (!before || !before.translations) {\n // Was a create \u2014 delete the record\n const resourceId = logEntry?.resourceId\n if (resourceId) {\n await db.deleteFrom('entity_translations').where('id', '=', resourceId).execute()\n }\n } else {\n // Was an update \u2014 restore previous translations\n const existing = await db\n .selectFrom('entity_translations')\n .select(['id'])\n .where('entity_type', '=', before.entityType)\n .where('entity_id', '=', before.entityId)\n .where(sql<boolean>`tenant_id is not distinct from ${before.tenantId}`)\n .where(sql<boolean>`organization_id is not distinct from ${before.organizationId}`)\n .executeTakeFirst() as { id: string } | undefined\n\n if (existing) {\n await db\n .updateTable('entity_translations')\n .set({\n translations: sql`${JSON.stringify(before.translations)}::jsonb`,\n updated_at: sql`now()`,\n } as any)\n .where('id', '=', existing.id)\n .execute()\n } else {\n await db\n .insertInto('entity_translations')\n .values({\n entity_type: before.entityType,\n entity_id: before.entityId,\n organization_id: before.organizationId,\n tenant_id: before.tenantId,\n translations: sql`${JSON.stringify(before.translations)}::jsonb`,\n created_at: sql`now()`,\n updated_at: sql`now()`,\n } as any)\n .execute()\n }\n }\n },\n}\n\nconst deleteTranslationCommand: CommandHandler<DeleteInput, { deleted: boolean }> = {\n id: 'translations.translation.delete',\n\n async prepare(input, ctx) {\n ensureTenantScope(ctx, input.tenantId)\n const db = resolveDb(ctx)\n const snapshot = await loadTranslationSnapshot(db, input.entityType, input.entityId, input.tenantId, input.organizationId)\n return { before: snapshot }\n },\n\n async execute(input, ctx) {\n const db = resolveDb(ctx) as any\n const result = await db\n .deleteFrom('entity_translations')\n .where('entity_type', '=', input.entityType)\n .where('entity_id', '=', input.entityId)\n .where(sql<boolean>`tenant_id is not distinct from ${input.tenantId}`)\n .where(sql<boolean>`organization_id is not distinct from ${input.organizationId}`)\n .executeTakeFirst() as { numDeletedRows?: bigint | number } | undefined\n const count = Number(result?.numDeletedRows ?? 0)\n\n await emitTranslationsEvent('translations.translation.deleted', {\n entityType: input.entityType,\n entityId: input.entityId,\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n }, { persistent: true }).catch(() => undefined)\n\n return { deleted: count > 0 }\n },\n\n async buildLog({ snapshots }) {\n const before = snapshots.before as TranslationSnapshot | null | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('translations.audit.delete', 'Delete translation'),\n resourceKind: 'translations.translation',\n resourceId: before.id ?? undefined,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: { before } satisfies TranslationUndoPayload,\n },\n }\n },\n\n async undo({ logEntry, ctx }) {\n const payload = extractUndoPayload<TranslationUndoPayload>(logEntry)\n const before = payload?.before\n if (!before || !before.translations) return\n const db = resolveDb(ctx) as any\n\n const existing = await db\n .selectFrom('entity_translations')\n .select(['id'])\n .where('entity_type', '=', before.entityType)\n .where('entity_id', '=', before.entityId)\n .where(sql<boolean>`tenant_id is not distinct from ${before.tenantId}`)\n .where(sql<boolean>`organization_id is not distinct from ${before.organizationId}`)\n .executeTakeFirst() as { id: string } | undefined\n\n if (!existing) {\n await db\n .insertInto('entity_translations')\n .values({\n entity_type: before.entityType,\n entity_id: before.entityId,\n organization_id: before.organizationId,\n tenant_id: before.tenantId,\n translations: sql`${JSON.stringify(before.translations)}::jsonb`,\n created_at: sql`now()`,\n updated_at: sql`now()`,\n } as any)\n .execute()\n }\n },\n}\n\nregisterCommand(saveTranslationCommand)\nregisterCommand(deleteTranslationCommand)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -10,6 +10,7 @@ import { Button } from "@open-mercato/ui/primitives/button";
|
|
|
10
10
|
import { FormHeader } from "@open-mercato/ui/backend/forms";
|
|
11
11
|
import { Spinner } from "@open-mercato/ui/primitives/spinner";
|
|
12
12
|
import { JsonDisplay } from "@open-mercato/ui/backend/JsonDisplay";
|
|
13
|
+
import { RecordNotFoundState, ErrorMessage } from "@open-mercato/ui/backend/detail";
|
|
13
14
|
function WorkflowEventDetailPage() {
|
|
14
15
|
const router = useRouter();
|
|
15
16
|
const params = useParams();
|
|
@@ -25,8 +26,11 @@ function WorkflowEventDetailPage() {
|
|
|
25
26
|
queryFn: async () => {
|
|
26
27
|
const response = await apiFetch(`/api/workflows/events/${eventId}`);
|
|
27
28
|
if (!response.ok) {
|
|
28
|
-
const
|
|
29
|
-
|
|
29
|
+
const httpErr = new Error(
|
|
30
|
+
response.status === 404 ? t("workflows.events.notFound", "Event not found.") : t("workflows.events.messages.loadFailed")
|
|
31
|
+
);
|
|
32
|
+
httpErr.status = response.status;
|
|
33
|
+
throw httpErr;
|
|
30
34
|
}
|
|
31
35
|
const result = await response.json();
|
|
32
36
|
return result;
|
|
@@ -39,11 +43,25 @@ function WorkflowEventDetailPage() {
|
|
|
39
43
|
/* @__PURE__ */ jsx("span", { children: t("workflows.common.loading") })
|
|
40
44
|
] }) }) });
|
|
41
45
|
}
|
|
46
|
+
const isNotFound = !isLoading && error?.status === 404;
|
|
47
|
+
if (isNotFound) {
|
|
48
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
|
|
49
|
+
RecordNotFoundState,
|
|
50
|
+
{
|
|
51
|
+
label: t("workflows.events.notFound", "Event not found."),
|
|
52
|
+
backHref: "/backend/events",
|
|
53
|
+
backLabel: t("workflows.events.backToList", "Back to Events")
|
|
54
|
+
}
|
|
55
|
+
) }) });
|
|
56
|
+
}
|
|
42
57
|
if (error || !event) {
|
|
43
|
-
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
58
|
+
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
|
|
59
|
+
ErrorMessage,
|
|
60
|
+
{
|
|
61
|
+
label: error?.message ?? t("workflows.events.messages.loadFailed"),
|
|
62
|
+
action: /* @__PURE__ */ jsx(Button, { asChild: true, variant: "outline", size: "sm", children: /* @__PURE__ */ jsx(Link, { href: "/backend/events", children: t("workflows.events.backToList", "Back to Events") }) })
|
|
63
|
+
}
|
|
64
|
+
) }) });
|
|
47
65
|
}
|
|
48
66
|
const getEventTypeBadgeClass = (eventType) => {
|
|
49
67
|
if (eventType.includes("STARTED")) return "bg-blue-100 text-blue-800";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/workflows/backend/events/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useParams, useRouter } from 'next/navigation'\nimport { useQuery } from '@tanstack/react-query'\nimport { apiFetch } from '@open-mercato/ui/backend/utils/api'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\n\ntype WorkflowEvent = {\n id: string\n workflowInstanceId: string\n stepInstanceId: string | null\n eventType: string\n eventData: any\n occurredAt: string\n userId: string | null\n tenantId: string\n organizationId: string\n workflowInstance: {\n id: string\n workflowId: string\n version: number\n status: string\n currentStepId: string\n correlationKey: string | null\n startedAt: string | null\n completedAt: string | null\n context: any\n } | null\n}\n\nexport default function WorkflowEventDetailPage() {\n const router = useRouter()\n const params = useParams()\n const t = useT()\n\n // Handle both {id: '17'} and {slug: ['events', '17']} formats\n let eventId: string | undefined\n if (params?.id) {\n eventId = Array.isArray(params.id) ? params.id[0] : params.id\n } else if (params?.slug && Array.isArray(params.slug)) {\n // If slug is ['events', '17'], extract '17'\n eventId = params.slug[params.slug.length - 1]\n }\n\n const { data: event, isLoading, error } = useQuery({\n queryKey: ['workflows', 'events', eventId],\n queryFn: async () => {\n const response = await apiFetch(`/api/workflows/events/${eventId}`)\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}))\n throw new Error(t('workflows.events.messages.loadFailed'))\n }\n const result = await response.json()\n return result as WorkflowEvent\n },\n enabled: !!eventId,\n })\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-6 w-6\" />\n <span>{t('workflows.common.loading')}</span>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n if (error || !event) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <p>{error ? t('workflows.events.messages.loadFailed') : t('workflows.events.notFound')}</p>\n <Button asChild variant=\"outline\">\n <Link href=\"/backend/events\">\n {t('workflows.events.backToList')}\n </Link>\n </Button>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n const getEventTypeBadgeClass = (eventType: string) => {\n if (eventType.includes('STARTED')) return 'bg-blue-100 text-blue-800'\n if (eventType.includes('COMPLETED')) return 'bg-green-100 text-green-800'\n if (eventType.includes('FAILED') || eventType.includes('REJECTED')) return 'bg-red-100 text-red-800'\n if (eventType.includes('CANCELLED')) return 'bg-muted text-foreground'\n if (eventType.includes('ENTERED') || eventType.includes('EXITED')) return 'bg-purple-100 text-purple-800'\n return 'bg-muted text-foreground'\n }\n\n const getStatusBadgeClass = (status: string) => {\n switch (status) {\n case 'COMPLETED':\n return 'bg-green-100 text-green-800'\n case 'RUNNING':\n return 'bg-blue-100 text-blue-800'\n case 'FAILED':\n return 'bg-red-100 text-red-800'\n case 'CANCELLED':\n return 'bg-muted text-foreground'\n default:\n return 'bg-muted text-foreground'\n }\n }\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/events\"\n backLabel={t('workflows.events.backToList', 'Back to events')}\n entityTypeLabel={t('workflows.events.detail.type', 'Workflow event')}\n title={\n <div className=\"flex flex-wrap items-center gap-2\">\n <span>{event.eventType}</span>\n <span className=\"font-mono text-sm text-muted-foreground\">#{event.id.slice(0, 8)}</span>\n </div>\n }\n statusBadge={\n <span\n className={`inline-flex items-center px-3 py-1 rounded text-sm font-medium ${getEventTypeBadgeClass(event.eventType)}`}\n >\n {event.eventType}\n </span>\n }\n />\n\n {/* Event Summary */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.events.detail.summary')}\n </h2>\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.events.fields.occurredAt')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {new Date(event.occurredAt).toLocaleString()}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.events.fields.eventType')}\n </dt>\n <dd className=\"mt-1\">\n <span\n className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getEventTypeBadgeClass(\n event.eventType\n )}`}\n >\n {event.eventType}\n </span>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.events.fields.userId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.userId || t('common.none')}\n </dd>\n </div>\n {event.stepInstanceId && (\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.events.detail.stepInstanceId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.stepInstanceId}\n </dd>\n </div>\n )}\n </dl>\n </div>\n\n {/* Workflow Instance Information */}\n {event.workflowInstance && (\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.events.detail.workflowInstance')}\n </h2>\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.instanceId')}\n </dt>\n <dd className=\"mt-1\">\n <Link\n href={`/backend/instances/${event.workflowInstance.id}`}\n className=\"text-sm text-primary hover:underline font-mono\"\n >\n {event.workflowInstance.id}\n </Link>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.status')}\n </dt>\n <dd className=\"mt-1\">\n <span\n className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getStatusBadgeClass(\n event.workflowInstance.status\n )}`}\n >\n {event.workflowInstance.status}\n </span>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.workflowId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.workflowInstance.workflowId}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.version')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {event.workflowInstance.version}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.currentStep')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.workflowInstance.currentStepId}\n </dd>\n </div>\n {event.workflowInstance.correlationKey && (\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.correlationKey')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.workflowInstance.correlationKey}\n </dd>\n </div>\n )}\n {event.workflowInstance.startedAt && (\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.startedAt')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {new Date(event.workflowInstance.startedAt).toLocaleString()}\n </dd>\n </div>\n )}\n {event.workflowInstance.completedAt && (\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.completedAt')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {new Date(event.workflowInstance.completedAt).toLocaleString()}\n </dd>\n </div>\n )}\n </dl>\n </div>\n )}\n\n {/* Event Data */}\n <JsonDisplay\n data={event.eventData}\n title={t('workflows.events.detail.eventData')}\n />\n\n {/* Workflow Context (if available) */}\n {event.workflowInstance?.context && (\n <JsonDisplay\n data={event.workflowInstance.context}\n title={t('workflows.events.detail.workflowContext')}\n />\n )}\n\n {/* Technical Details */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.events.detail.technicalDetails')}\n </h2>\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.events.detail.tenantId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.tenantId}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.events.detail.organizationId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.organizationId}\n </dd>\n </div>\n </dl>\n </div>\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useParams, useRouter } from 'next/navigation'\nimport { useQuery } from '@tanstack/react-query'\nimport { apiFetch } from '@open-mercato/ui/backend/utils/api'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\nimport { RecordNotFoundState, ErrorMessage } from '@open-mercato/ui/backend/detail'\n\ntype WorkflowEvent = {\n id: string\n workflowInstanceId: string\n stepInstanceId: string | null\n eventType: string\n eventData: any\n occurredAt: string\n userId: string | null\n tenantId: string\n organizationId: string\n workflowInstance: {\n id: string\n workflowId: string\n version: number\n status: string\n currentStepId: string\n correlationKey: string | null\n startedAt: string | null\n completedAt: string | null\n context: any\n } | null\n}\n\nexport default function WorkflowEventDetailPage() {\n const router = useRouter()\n const params = useParams()\n const t = useT()\n\n // Handle both {id: '17'} and {slug: ['events', '17']} formats\n let eventId: string | undefined\n if (params?.id) {\n eventId = Array.isArray(params.id) ? params.id[0] : params.id\n } else if (params?.slug && Array.isArray(params.slug)) {\n // If slug is ['events', '17'], extract '17'\n eventId = params.slug[params.slug.length - 1]\n }\n\n const { data: event, isLoading, error } = useQuery({\n queryKey: ['workflows', 'events', eventId],\n queryFn: async () => {\n const response = await apiFetch(`/api/workflows/events/${eventId}`)\n\n if (!response.ok) {\n const httpErr = new Error(\n response.status === 404\n ? t('workflows.events.notFound', 'Event not found.')\n : t('workflows.events.messages.loadFailed')\n ) as Error & { status: number }\n httpErr.status = response.status\n throw httpErr\n }\n const result = await response.json()\n return result as WorkflowEvent\n },\n enabled: !!eventId,\n })\n\n if (isLoading) {\n return (\n <Page>\n <PageBody>\n <div className=\"flex h-[50vh] flex-col items-center justify-center gap-2 text-muted-foreground\">\n <Spinner className=\"h-6 w-6\" />\n <span>{t('workflows.common.loading')}</span>\n </div>\n </PageBody>\n </Page>\n )\n }\n\n const isNotFound = !isLoading && (error as (Error & { status?: number }) | null)?.status === 404\n\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('workflows.events.notFound', 'Event not found.')}\n backHref=\"/backend/events\"\n backLabel={t('workflows.events.backToList', 'Back to Events')}\n />\n </PageBody>\n </Page>\n )\n }\n\n if (error || !event) {\n return (\n <Page>\n <PageBody>\n <ErrorMessage\n label={(error as Error | null)?.message ?? t('workflows.events.messages.loadFailed')}\n action={\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href=\"/backend/events\">{t('workflows.events.backToList', 'Back to Events')}</Link>\n </Button>\n }\n />\n </PageBody>\n </Page>\n )\n }\n\n const getEventTypeBadgeClass = (eventType: string) => {\n if (eventType.includes('STARTED')) return 'bg-blue-100 text-blue-800'\n if (eventType.includes('COMPLETED')) return 'bg-green-100 text-green-800'\n if (eventType.includes('FAILED') || eventType.includes('REJECTED')) return 'bg-red-100 text-red-800'\n if (eventType.includes('CANCELLED')) return 'bg-muted text-foreground'\n if (eventType.includes('ENTERED') || eventType.includes('EXITED')) return 'bg-purple-100 text-purple-800'\n return 'bg-muted text-foreground'\n }\n\n const getStatusBadgeClass = (status: string) => {\n switch (status) {\n case 'COMPLETED':\n return 'bg-green-100 text-green-800'\n case 'RUNNING':\n return 'bg-blue-100 text-blue-800'\n case 'FAILED':\n return 'bg-red-100 text-red-800'\n case 'CANCELLED':\n return 'bg-muted text-foreground'\n default:\n return 'bg-muted text-foreground'\n }\n }\n\n return (\n <Page>\n <PageBody>\n <div className=\"space-y-6\">\n <FormHeader\n mode=\"detail\"\n backHref=\"/backend/events\"\n backLabel={t('workflows.events.backToList', 'Back to events')}\n entityTypeLabel={t('workflows.events.detail.type', 'Workflow event')}\n title={\n <div className=\"flex flex-wrap items-center gap-2\">\n <span>{event.eventType}</span>\n <span className=\"font-mono text-sm text-muted-foreground\">#{event.id.slice(0, 8)}</span>\n </div>\n }\n statusBadge={\n <span\n className={`inline-flex items-center px-3 py-1 rounded text-sm font-medium ${getEventTypeBadgeClass(event.eventType)}`}\n >\n {event.eventType}\n </span>\n }\n />\n\n {/* Event Summary */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.events.detail.summary')}\n </h2>\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.events.fields.occurredAt')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {new Date(event.occurredAt).toLocaleString()}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.events.fields.eventType')}\n </dt>\n <dd className=\"mt-1\">\n <span\n className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getEventTypeBadgeClass(\n event.eventType\n )}`}\n >\n {event.eventType}\n </span>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.events.fields.userId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.userId || t('common.none')}\n </dd>\n </div>\n {event.stepInstanceId && (\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.events.detail.stepInstanceId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.stepInstanceId}\n </dd>\n </div>\n )}\n </dl>\n </div>\n\n {/* Workflow Instance Information */}\n {event.workflowInstance && (\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.events.detail.workflowInstance')}\n </h2>\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.instanceId')}\n </dt>\n <dd className=\"mt-1\">\n <Link\n href={`/backend/instances/${event.workflowInstance.id}`}\n className=\"text-sm text-primary hover:underline font-mono\"\n >\n {event.workflowInstance.id}\n </Link>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.status')}\n </dt>\n <dd className=\"mt-1\">\n <span\n className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${getStatusBadgeClass(\n event.workflowInstance.status\n )}`}\n >\n {event.workflowInstance.status}\n </span>\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.workflowId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.workflowInstance.workflowId}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.version')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {event.workflowInstance.version}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.currentStep')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.workflowInstance.currentStepId}\n </dd>\n </div>\n {event.workflowInstance.correlationKey && (\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.correlationKey')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.workflowInstance.correlationKey}\n </dd>\n </div>\n )}\n {event.workflowInstance.startedAt && (\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.startedAt')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {new Date(event.workflowInstance.startedAt).toLocaleString()}\n </dd>\n </div>\n )}\n {event.workflowInstance.completedAt && (\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.instances.fields.completedAt')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground\">\n {new Date(event.workflowInstance.completedAt).toLocaleString()}\n </dd>\n </div>\n )}\n </dl>\n </div>\n )}\n\n {/* Event Data */}\n <JsonDisplay\n data={event.eventData}\n title={t('workflows.events.detail.eventData')}\n />\n\n {/* Workflow Context (if available) */}\n {event.workflowInstance?.context && (\n <JsonDisplay\n data={event.workflowInstance.context}\n title={t('workflows.events.detail.workflowContext')}\n />\n )}\n\n {/* Technical Details */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold mb-4\">\n {t('workflows.events.detail.technicalDetails')}\n </h2>\n <dl className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.events.detail.tenantId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.tenantId}\n </dd>\n </div>\n <div>\n <dt className=\"text-sm font-medium text-muted-foreground\">\n {t('workflows.events.detail.organizationId')}\n </dt>\n <dd className=\"mt-1 text-sm text-foreground font-mono\">\n {event.organizationId}\n </dd>\n </div>\n </dl>\n </div>\n </div>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -17,6 +17,7 @@ import { WorkflowLegend } from "../../../components/WorkflowLegend.js";
|
|
|
17
17
|
import { MobileInstanceOverview } from "../../../components/mobile/MobileInstanceOverview.js";
|
|
18
18
|
import { useIsMobile } from "@open-mercato/ui/hooks/useIsMobile";
|
|
19
19
|
import { definitionToGraph } from "../../../lib/graph-utils.js";
|
|
20
|
+
import { RecordNotFoundState, ErrorMessage } from "@open-mercato/ui/backend/detail";
|
|
20
21
|
function WorkflowInstanceDetailPage({ params }) {
|
|
21
22
|
const id = params?.id;
|
|
22
23
|
const t = useT();
|
|
@@ -28,7 +29,11 @@ function WorkflowInstanceDetailPage({ params }) {
|
|
|
28
29
|
queryFn: async () => {
|
|
29
30
|
const response = await apiFetch(`/api/workflows/instances/${id}`);
|
|
30
31
|
if (!response.ok) {
|
|
31
|
-
|
|
32
|
+
const httpErr = new Error(
|
|
33
|
+
response.status === 404 ? t("workflows.instances.detail.notFound", "Workflow instance not found.") : t("workflows.instances.loadFailed", "Failed to load workflow instance.")
|
|
34
|
+
);
|
|
35
|
+
httpErr.status = response.status;
|
|
36
|
+
throw httpErr;
|
|
32
37
|
}
|
|
33
38
|
const data = await response.json();
|
|
34
39
|
return data.data;
|
|
@@ -330,12 +335,29 @@ function WorkflowInstanceDetailPage({ params }) {
|
|
|
330
335
|
ConfirmDialogElement
|
|
331
336
|
] });
|
|
332
337
|
}
|
|
338
|
+
const isNotFound = !isLoading && error?.status === 404;
|
|
339
|
+
if (isNotFound) {
|
|
340
|
+
return /* @__PURE__ */ jsxs(Page, { children: [
|
|
341
|
+
/* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
|
|
342
|
+
RecordNotFoundState,
|
|
343
|
+
{
|
|
344
|
+
label: t("workflows.instances.detail.notFound", "Workflow instance not found."),
|
|
345
|
+
backHref: "/backend/instances",
|
|
346
|
+
backLabel: t("workflows.instances.actions.backToList", "Back to instances")
|
|
347
|
+
}
|
|
348
|
+
) }),
|
|
349
|
+
ConfirmDialogElement
|
|
350
|
+
] });
|
|
351
|
+
}
|
|
333
352
|
if (error || !instance) {
|
|
334
353
|
return /* @__PURE__ */ jsxs(Page, { children: [
|
|
335
|
-
/* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
354
|
+
/* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(
|
|
355
|
+
ErrorMessage,
|
|
356
|
+
{
|
|
357
|
+
label: error?.message ?? t("workflows.instances.loadFailed", "Failed to load workflow instance."),
|
|
358
|
+
action: /* @__PURE__ */ jsx(Button, { asChild: true, variant: "outline", size: "sm", children: /* @__PURE__ */ jsx(Link, { href: "/backend/instances", children: t("workflows.instances.actions.backToList", "Back to instances") }) })
|
|
359
|
+
}
|
|
360
|
+
) }),
|
|
339
361
|
ConfirmDialogElement
|
|
340
362
|
] });
|
|
341
363
|
}
|