@open-mercato/core 0.4.2-canary-f821f89ef6 → 0.4.2-canary-3b5064ce72
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/dist/generated/entities/notification/index.js +57 -0
- package/dist/generated/entities/notification/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +5 -2
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -2
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/api_docs/frontend/docs/api/page.js +3 -2
- package/dist/modules/api_docs/frontend/docs/api/page.js.map +2 -2
- package/dist/modules/api_keys/backend/api-keys/page.js +1 -1
- package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentLibrary.js +4 -0
- package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js +2 -0
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
- package/dist/modules/auth/api/admin/nav.js +4 -3
- package/dist/modules/auth/api/admin/nav.js.map +2 -2
- package/dist/modules/auth/api/login.js +25 -6
- package/dist/modules/auth/api/login.js.map +2 -2
- package/dist/modules/auth/api/profile/route.js +157 -0
- package/dist/modules/auth/api/profile/route.js.map +7 -0
- package/dist/modules/auth/api/reset/confirm.js +25 -2
- package/dist/modules/auth/api/reset/confirm.js.map +2 -2
- package/dist/modules/auth/api/reset.js +23 -0
- package/dist/modules/auth/api/reset.js.map +2 -2
- package/dist/modules/auth/api/sidebar/preferences/route.js +14 -9
- package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +4 -2
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/auth/profile/page.js +141 -0
- package/dist/modules/auth/backend/auth/profile/page.js.map +7 -0
- package/dist/modules/auth/backend/auth/profile/page.meta.js +13 -0
- package/dist/modules/auth/backend/auth/profile/page.meta.js.map +7 -0
- package/dist/modules/auth/backend/roles/[id]/edit/page.js +4 -1
- package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/roles/page.js +3 -3
- package/dist/modules/auth/backend/roles/page.js.map +2 -2
- package/dist/modules/auth/backend/users/[id]/edit/page.js +18 -3
- package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/users/create/page.js +15 -2
- package/dist/modules/auth/backend/users/create/page.js.map +2 -2
- package/dist/modules/auth/backend/users/page.js +3 -3
- package/dist/modules/auth/backend/users/page.js.map +2 -2
- package/dist/modules/auth/cli.js +25 -11
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/auth/commands/users.js +59 -2
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/data/validators.js +6 -3
- package/dist/modules/auth/data/validators.js.map +2 -2
- package/dist/modules/auth/frontend/login.js +112 -3
- package/dist/modules/auth/frontend/login.js.map +2 -2
- package/dist/modules/auth/frontend/reset/[token]/page.js +20 -10
- package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
- package/dist/modules/auth/lib/setup-app.js +42 -8
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/notifications.js +112 -0
- package/dist/modules/auth/notifications.js.map +7 -0
- package/dist/modules/auth/services/authService.js +24 -3
- package/dist/modules/auth/services/authService.js.map +2 -2
- package/dist/modules/business_rules/api/execute/route.js +7 -1
- package/dist/modules/business_rules/api/execute/route.js.map +2 -2
- package/dist/modules/business_rules/backend/rules/page.js +4 -0
- package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
- package/dist/modules/business_rules/backend/sets/page.js +3 -0
- package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
- package/dist/modules/business_rules/cli.js +2 -1
- package/dist/modules/business_rules/cli.js.map +2 -2
- package/dist/modules/business_rules/data/validators.js +0 -34
- package/dist/modules/business_rules/data/validators.js.map +2 -2
- package/dist/modules/business_rules/index.js +1 -21
- package/dist/modules/business_rules/index.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +34 -185
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/business_rules/notifications.js +28 -0
- package/dist/modules/business_rules/notifications.js.map +7 -0
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +37 -0
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +7 -0
- package/dist/modules/catalog/components/PriceKindSettings.js +2 -0
- package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js +2 -0
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/catalog/notifications.js +28 -0
- package/dist/modules/catalog/notifications.js.map +7 -0
- package/dist/modules/catalog/subscribers/low-stock-notification.js +38 -0
- package/dist/modules/catalog/subscribers/low-stock-notification.js.map +7 -0
- package/dist/modules/configs/cli.js +6 -0
- package/dist/modules/configs/cli.js.map +2 -2
- package/dist/modules/configs/components/CachePanel.js +4 -4
- package/dist/modules/configs/components/CachePanel.js.map +2 -2
- package/dist/modules/configs/lib/system-status.js +48 -1
- package/dist/modules/configs/lib/system-status.js.map +2 -2
- package/dist/modules/configs/lib/upgrade-actions.js +18 -0
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +3 -0
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +2 -0
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +3 -0
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +3 -0
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/page.js +3 -0
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +31 -0
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
- package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
- package/dist/modules/customers/notifications.js +48 -0
- package/dist/modules/customers/notifications.js.map +7 -0
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/customer-todos/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/new-customers/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/new-deals/widget.js.map +2 -2
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js +2 -1
- package/dist/modules/customers/widgets/dashboard/next-interactions/widget.js.map +2 -2
- package/dist/modules/dashboards/cli.js +44 -5
- package/dist/modules/dashboards/cli.js.map +2 -2
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +16 -11
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +3 -3
- package/dist/modules/dashboards/lib/role-widgets.js +58 -0
- package/dist/modules/dashboards/lib/role-widgets.js.map +7 -0
- package/dist/modules/dashboards/services/widgetDataService.js +139 -3
- package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/aov-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/orders-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/pipeline-summary/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/revenue-kpi/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.js.map +2 -2
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js +2 -1
- package/dist/modules/dashboards/widgets/dashboard/top-products/widget.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryTable.js +2 -0
- package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
- package/dist/modules/directory/api/get/tenants/lookup.js +70 -0
- package/dist/modules/directory/api/get/tenants/lookup.js.map +7 -0
- package/dist/modules/directory/backend/directory/organizations/page.js +2 -2
- package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- package/dist/modules/entities/components/SystemEntitiesTable.js +1 -1
- package/dist/modules/entities/components/SystemEntitiesTable.js.map +2 -2
- package/dist/modules/entities/components/UserEntitiesTable.js +2 -2
- package/dist/modules/entities/components/UserEntitiesTable.js.map +2 -2
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +3 -3
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
- package/dist/modules/feature_toggles/components/OverridesTable.js +1 -1
- package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
- package/dist/modules/notifications/acl.js +11 -0
- package/dist/modules/notifications/acl.js.map +7 -0
- package/dist/modules/notifications/api/[id]/action/route.js +74 -0
- package/dist/modules/notifications/api/[id]/action/route.js.map +7 -0
- package/dist/modules/notifications/api/[id]/dismiss/route.js +15 -0
- package/dist/modules/notifications/api/[id]/dismiss/route.js.map +7 -0
- package/dist/modules/notifications/api/[id]/read/route.js +15 -0
- package/dist/modules/notifications/api/[id]/read/route.js.map +7 -0
- package/dist/modules/notifications/api/[id]/restore/route.js +53 -0
- package/dist/modules/notifications/api/[id]/restore/route.js.map +7 -0
- package/dist/modules/notifications/api/batch/route.js +17 -0
- package/dist/modules/notifications/api/batch/route.js.map +7 -0
- package/dist/modules/notifications/api/feature/route.js +17 -0
- package/dist/modules/notifications/api/feature/route.js.map +7 -0
- package/dist/modules/notifications/api/mark-all-read/route.js +35 -0
- package/dist/modules/notifications/api/mark-all-read/route.js.map +7 -0
- package/dist/modules/notifications/api/openapi.js +76 -0
- package/dist/modules/notifications/api/openapi.js.map +7 -0
- package/dist/modules/notifications/api/role/route.js +17 -0
- package/dist/modules/notifications/api/role/route.js.map +7 -0
- package/dist/modules/notifications/api/route.js +85 -0
- package/dist/modules/notifications/api/route.js.map +7 -0
- package/dist/modules/notifications/api/settings/route.js +155 -0
- package/dist/modules/notifications/api/settings/route.js.map +7 -0
- package/dist/modules/notifications/api/unread-count/route.js +38 -0
- package/dist/modules/notifications/api/unread-count/route.js.map +7 -0
- package/dist/modules/notifications/backend/config/notifications/page.js +10 -0
- package/dist/modules/notifications/backend/config/notifications/page.js.map +7 -0
- package/dist/modules/notifications/backend/config/notifications/page.meta.js +24 -0
- package/dist/modules/notifications/backend/config/notifications/page.meta.js.map +7 -0
- package/dist/modules/notifications/cli.js +16 -0
- package/dist/modules/notifications/cli.js.map +7 -0
- package/dist/modules/notifications/data/entities.js +112 -0
- package/dist/modules/notifications/data/entities.js.map +7 -0
- package/dist/modules/notifications/data/validators.js +98 -0
- package/dist/modules/notifications/data/validators.js.map +7 -0
- package/dist/modules/notifications/di.js +13 -0
- package/dist/modules/notifications/di.js.map +7 -0
- package/dist/modules/notifications/emails/NotificationEmail.js +58 -0
- package/dist/modules/notifications/emails/NotificationEmail.js.map +7 -0
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js +44 -0
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js.map +7 -0
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +220 -0
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +7 -0
- package/dist/modules/notifications/index.js +14 -0
- package/dist/modules/notifications/index.js.map +7 -0
- package/dist/modules/notifications/lib/deliveryConfig.js +107 -0
- package/dist/modules/notifications/lib/deliveryConfig.js.map +7 -0
- package/dist/modules/notifications/lib/deliveryStrategies.js +14 -0
- package/dist/modules/notifications/lib/deliveryStrategies.js.map +7 -0
- package/dist/modules/notifications/lib/events.js +12 -0
- package/dist/modules/notifications/lib/events.js.map +7 -0
- package/dist/modules/notifications/lib/notificationBuilder.js +66 -0
- package/dist/modules/notifications/lib/notificationBuilder.js.map +7 -0
- package/dist/modules/notifications/lib/notificationFactory.js +54 -0
- package/dist/modules/notifications/lib/notificationFactory.js.map +7 -0
- package/dist/modules/notifications/lib/notificationMapper.js +34 -0
- package/dist/modules/notifications/lib/notificationMapper.js.map +7 -0
- package/dist/modules/notifications/lib/notificationRecipients.js +35 -0
- package/dist/modules/notifications/lib/notificationRecipients.js.map +7 -0
- package/dist/modules/notifications/lib/notificationService.js +279 -0
- package/dist/modules/notifications/lib/notificationService.js.map +7 -0
- package/dist/modules/notifications/lib/routeHelpers.js +101 -0
- package/dist/modules/notifications/lib/routeHelpers.js.map +7 -0
- package/dist/modules/notifications/lib/safeHref.js +24 -0
- package/dist/modules/notifications/lib/safeHref.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260123000001.js +70 -0
- package/dist/modules/notifications/migrations/Migration20260123000001.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260126150000.js +37 -0
- package/dist/modules/notifications/migrations/Migration20260126150000.js.map +7 -0
- package/dist/modules/notifications/migrations/Migration20260129082610.js +13 -0
- package/dist/modules/notifications/migrations/Migration20260129082610.js.map +7 -0
- package/dist/modules/notifications/subscribers/deliver-notification.js +165 -0
- package/dist/modules/notifications/subscribers/deliver-notification.js.map +7 -0
- package/dist/modules/notifications/workers/create-notification.worker.js +70 -0
- package/dist/modules/notifications/workers/create-notification.worker.js.map +7 -0
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
- package/dist/modules/query_index/cli.js +63 -7
- package/dist/modules/query_index/cli.js.map +2 -2
- package/dist/modules/query_index/components/QueryIndexesTable.js +7 -1
- package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
- package/dist/modules/sales/acl.js +0 -1
- package/dist/modules/sales/acl.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +2 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +2 -0
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +0 -12
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +53 -62
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +26 -0
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/sales/components/AdjustmentKindSettings.js +2 -2
- package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
- package/dist/modules/sales/components/PaymentMethodsSettings.js +2 -2
- package/dist/modules/sales/components/PaymentMethodsSettings.js.map +2 -2
- package/dist/modules/sales/components/ShippingMethodsSettings.js +2 -2
- package/dist/modules/sales/components/ShippingMethodsSettings.js.map +2 -2
- package/dist/modules/sales/components/TaxRatesSettings.js +2 -2
- package/dist/modules/sales/components/TaxRatesSettings.js.map +2 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +2 -0
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js +2 -0
- package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js +2 -1
- package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +2 -0
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/lib/dictionaries.js +0 -3
- package/dist/modules/sales/lib/dictionaries.js.map +2 -2
- package/dist/modules/sales/notifications.client.js +51 -0
- package/dist/modules/sales/notifications.client.js.map +7 -0
- package/dist/modules/sales/notifications.js +88 -0
- package/dist/modules/sales/notifications.js.map +7 -0
- package/dist/modules/sales/subscribers/quote-expiring-notification.js +38 -0
- package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +137 -0
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +137 -0
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/index.js +7 -0
- package/dist/modules/sales/widgets/notifications/index.js.map +7 -0
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js +60 -0
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js.map +7 -0
- package/dist/modules/staff/backend/staff/team-members/page.js +1 -1
- package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
- package/dist/modules/staff/commands/leave-requests.js +79 -0
- package/dist/modules/staff/commands/leave-requests.js.map +2 -2
- package/dist/modules/staff/notifications.js +75 -0
- package/dist/modules/staff/notifications.js.map +7 -0
- package/dist/modules/workflows/acl.js +0 -2
- package/dist/modules/workflows/acl.js.map +2 -2
- package/dist/modules/workflows/api/instances/route.js +6 -18
- package/dist/modules/workflows/api/instances/route.js.map +2 -2
- package/dist/modules/workflows/api/tasks/route.js +1 -6
- package/dist/modules/workflows/api/tasks/route.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.js +1 -9
- package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/[id]/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.js +15 -24
- package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/create/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/create/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/page.js +5 -0
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +132 -150
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.meta.js +1 -1
- package/dist/modules/workflows/backend/definitions/visual-editor/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.js +1 -1
- package/dist/modules/workflows/backend/events/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/events/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/instances/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.js +3 -0
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.js +1 -1
- package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.meta.js +2 -2
- package/dist/modules/workflows/backend/tasks/[id]/page.meta.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +9 -5
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/cli.js +15 -93
- package/dist/modules/workflows/cli.js.map +3 -3
- package/dist/modules/workflows/data/entities.js +1 -64
- package/dist/modules/workflows/data/entities.js.map +2 -2
- package/dist/modules/workflows/data/validators.js +0 -115
- package/dist/modules/workflows/data/validators.js.map +2 -2
- package/dist/modules/workflows/examples/checkout-demo-definition.json +5 -1
- package/dist/modules/workflows/lib/activity-executor.js +13 -75
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/dist/modules/workflows/lib/graph-utils.js +2 -71
- package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
- package/dist/modules/workflows/lib/seeds.js +5 -22
- package/dist/modules/workflows/lib/seeds.js.map +2 -2
- package/dist/modules/workflows/lib/start-validator.js +23 -33
- package/dist/modules/workflows/lib/start-validator.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +57 -161
- package/dist/modules/workflows/lib/transition-handler.js.map +3 -3
- package/dist/modules/workflows/notifications.js +28 -0
- package/dist/modules/workflows/notifications.js.map +7 -0
- package/dist/modules/workflows/subscribers/task-assigned-notification.js +38 -0
- package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +7 -0
- package/generated/entities/notification/index.ts +27 -0
- package/generated/entities.ids.generated.ts +5 -2
- package/generated/entity-fields-registry.ts +2 -2
- package/package.json +2 -2
- package/src/modules/api_docs/frontend/docs/api/page.tsx +3 -2
- package/src/modules/api_keys/backend/api-keys/page.tsx +1 -1
- package/src/modules/attachments/components/AttachmentLibrary.tsx +4 -0
- package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +2 -0
- package/src/modules/auth/README.md +1 -1
- package/src/modules/auth/__tests__/cli-setup-acl.test.ts +1 -1
- package/src/modules/auth/api/__tests__/login.test.ts +2 -0
- package/src/modules/auth/api/admin/nav.ts +10 -6
- package/src/modules/auth/api/login.ts +26 -7
- package/src/modules/auth/api/profile/route.ts +163 -0
- package/src/modules/auth/api/reset/confirm.ts +25 -2
- package/src/modules/auth/api/reset.ts +23 -0
- package/src/modules/auth/api/sidebar/preferences/route.ts +21 -12
- package/src/modules/auth/api/users/route.ts +5 -2
- package/src/modules/auth/backend/auth/profile/page.meta.ts +9 -0
- package/src/modules/auth/backend/auth/profile/page.tsx +174 -0
- package/src/modules/auth/backend/roles/[id]/edit/page.tsx +4 -1
- package/src/modules/auth/backend/roles/page.tsx +3 -3
- package/src/modules/auth/backend/users/[id]/edit/page.tsx +22 -3
- package/src/modules/auth/backend/users/create/page.tsx +19 -2
- package/src/modules/auth/backend/users/page.tsx +3 -3
- package/src/modules/auth/cli.ts +38 -11
- package/src/modules/auth/commands/users.ts +73 -2
- package/src/modules/auth/data/validators.ts +6 -2
- package/src/modules/auth/frontend/login.tsx +134 -5
- package/src/modules/auth/frontend/reset/[token]/page.tsx +24 -11
- package/src/modules/auth/i18n/de.json +48 -1
- package/src/modules/auth/i18n/en.json +48 -1
- package/src/modules/auth/i18n/es.json +48 -1
- package/src/modules/auth/i18n/pl.json +48 -1
- package/src/modules/auth/lib/setup-app.ts +58 -9
- package/src/modules/auth/notifications.ts +109 -0
- package/src/modules/auth/services/authService.ts +27 -4
- package/src/modules/business_rules/api/execute/route.ts +8 -1
- package/src/modules/business_rules/backend/rules/page.tsx +4 -0
- package/src/modules/business_rules/backend/sets/page.tsx +3 -0
- package/src/modules/business_rules/cli.ts +2 -1
- package/src/modules/business_rules/data/validators.ts +0 -40
- package/src/modules/business_rules/i18n/en.json +3 -1
- package/src/modules/business_rules/index.ts +0 -25
- package/src/modules/business_rules/lib/__tests__/rule-engine.test.ts +51 -0
- package/src/modules/business_rules/lib/rule-engine.ts +51 -277
- package/src/modules/business_rules/notifications.ts +25 -0
- package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +50 -0
- package/src/modules/catalog/components/PriceKindSettings.tsx +2 -0
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +2 -2
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +2 -0
- package/src/modules/catalog/i18n/en.json +3 -1
- package/src/modules/catalog/notifications.ts +25 -0
- package/src/modules/catalog/subscribers/low-stock-notification.ts +52 -0
- package/src/modules/configs/cli.ts +6 -0
- package/src/modules/configs/components/CachePanel.tsx +4 -4
- package/src/modules/configs/i18n/en.json +12 -2
- package/src/modules/configs/i18n/pl.json +12 -2
- package/src/modules/configs/lib/system-status.ts +48 -1
- package/src/modules/configs/lib/system-status.types.ts +1 -0
- package/src/modules/configs/lib/upgrade-actions.ts +18 -0
- package/src/modules/currencies/backend/currencies/page.tsx +3 -0
- package/src/modules/currencies/backend/exchange-rates/page.tsx +2 -0
- package/src/modules/customers/backend/customers/companies/page.tsx +3 -0
- package/src/modules/customers/backend/customers/deals/page.tsx +3 -0
- package/src/modules/customers/backend/customers/people/page.tsx +3 -0
- package/src/modules/customers/commands/deals.ts +39 -0
- package/src/modules/customers/components/CustomerTodosTable.tsx +1 -0
- package/src/modules/customers/i18n/en.json +5 -1
- package/src/modules/customers/notifications.ts +44 -0
- package/src/modules/customers/widgets/dashboard/customer-todos/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/new-customers/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/new-deals/widget.ts +2 -2
- package/src/modules/customers/widgets/dashboard/next-interactions/widget.ts +2 -2
- package/src/modules/dashboards/cli.ts +55 -5
- package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +22 -11
- package/src/modules/dashboards/lib/role-widgets.ts +80 -0
- package/src/modules/dashboards/services/widgetDataService.ts +164 -4
- package/src/modules/dashboards/widgets/dashboard/aov-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/new-customers-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/orders-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/pipeline-summary/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/revenue-kpi/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/top-customers/widget.ts +2 -2
- package/src/modules/dashboards/widgets/dashboard/top-products/widget.ts +2 -2
- package/src/modules/dictionaries/components/DictionaryTable.tsx +2 -0
- package/src/modules/directory/api/get/tenants/lookup.ts +75 -0
- package/src/modules/directory/backend/directory/organizations/page.tsx +2 -2
- package/src/modules/directory/backend/directory/tenants/page.tsx +2 -2
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +2 -2
- package/src/modules/entities/components/SystemEntitiesTable.tsx +1 -1
- package/src/modules/entities/components/UserEntitiesTable.tsx +2 -2
- package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +3 -4
- package/src/modules/feature_toggles/components/OverridesTable.tsx +1 -1
- package/src/modules/notifications/__tests__/deliver-notification.test.ts +195 -0
- package/src/modules/notifications/__tests__/deliveryStrategies.test.ts +19 -0
- package/src/modules/notifications/__tests__/notificationService.test.ts +208 -0
- package/src/modules/notifications/acl.ts +7 -0
- package/src/modules/notifications/api/[id]/action/route.ts +75 -0
- package/src/modules/notifications/api/[id]/dismiss/route.ts +12 -0
- package/src/modules/notifications/api/[id]/read/route.ts +12 -0
- package/src/modules/notifications/api/[id]/restore/route.ts +53 -0
- package/src/modules/notifications/api/batch/route.ts +14 -0
- package/src/modules/notifications/api/feature/route.ts +14 -0
- package/src/modules/notifications/api/mark-all-read/route.ts +34 -0
- package/src/modules/notifications/api/openapi.ts +76 -0
- package/src/modules/notifications/api/role/route.ts +14 -0
- package/src/modules/notifications/api/route.ts +92 -0
- package/src/modules/notifications/api/settings/route.ts +157 -0
- package/src/modules/notifications/api/unread-count/route.ts +38 -0
- package/src/modules/notifications/backend/config/notifications/page.meta.ts +22 -0
- package/src/modules/notifications/backend/config/notifications/page.tsx +12 -0
- package/src/modules/notifications/cli.ts +18 -0
- package/src/modules/notifications/data/entities.ts +99 -0
- package/src/modules/notifications/data/validators.ts +115 -0
- package/src/modules/notifications/di.ts +11 -0
- package/src/modules/notifications/emails/NotificationEmail.tsx +98 -0
- package/src/modules/notifications/frontend/NotificationInboxPageClient.tsx +42 -0
- package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +233 -0
- package/src/modules/notifications/i18n/de.json +50 -0
- package/src/modules/notifications/i18n/en.json +50 -0
- package/src/modules/notifications/i18n/es.json +50 -0
- package/src/modules/notifications/i18n/pl.json +50 -0
- package/src/modules/notifications/index.ts +12 -0
- package/src/modules/notifications/lib/deliveryConfig.ts +153 -0
- package/src/modules/notifications/lib/deliveryStrategies.ts +50 -0
- package/src/modules/notifications/lib/events.ts +48 -0
- package/src/modules/notifications/lib/notificationBuilder.ts +121 -0
- package/src/modules/notifications/lib/notificationFactory.ts +76 -0
- package/src/modules/notifications/lib/notificationMapper.ts +33 -0
- package/src/modules/notifications/lib/notificationRecipients.ts +83 -0
- package/src/modules/notifications/lib/notificationService.ts +414 -0
- package/src/modules/notifications/lib/routeHelpers.ts +151 -0
- package/src/modules/notifications/lib/safeHref.ts +29 -0
- package/src/modules/notifications/migrations/.snapshot-open-mercato.json +336 -0
- package/src/modules/notifications/migrations/Migration20260123000001.ts +73 -0
- package/src/modules/notifications/migrations/Migration20260126150000.ts +39 -0
- package/src/modules/notifications/migrations/Migration20260129082610.ts +13 -0
- package/src/modules/notifications/subscribers/deliver-notification.ts +204 -0
- package/src/modules/notifications/workers/create-notification.worker.ts +122 -0
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +2 -2
- package/src/modules/query_index/cli.ts +82 -13
- package/src/modules/query_index/components/QueryIndexesTable.tsx +8 -2
- package/src/modules/resources/backend/resources/resource-types/page.tsx +2 -2
- package/src/modules/resources/backend/resources/resources/page.tsx +2 -2
- package/src/modules/sales/acl.ts +0 -1
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +2 -0
- package/src/modules/sales/backend/sales/channels/page.tsx +2 -0
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +0 -16
- package/src/modules/sales/commands/documents.ts +62 -70
- package/src/modules/sales/commands/payments.ts +33 -0
- package/src/modules/sales/components/AdjustmentKindSettings.tsx +2 -2
- package/src/modules/sales/components/PaymentMethodsSettings.tsx +2 -2
- package/src/modules/sales/components/ShippingMethodsSettings.tsx +2 -2
- package/src/modules/sales/components/TaxRatesSettings.tsx +2 -2
- package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +2 -0
- package/src/modules/sales/components/documents/AdjustmentsSection.tsx +2 -0
- package/src/modules/sales/components/documents/PaymentsSection.tsx +2 -1
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +2 -0
- package/src/modules/sales/i18n/de.json +20 -0
- package/src/modules/sales/i18n/en.json +25 -1
- package/src/modules/sales/i18n/es.json +20 -0
- package/src/modules/sales/i18n/pl.json +20 -0
- package/src/modules/sales/lib/dictionaries.ts +0 -3
- package/src/modules/sales/notifications.client.ts +65 -0
- package/src/modules/sales/notifications.ts +82 -0
- package/src/modules/sales/subscribers/quote-expiring-notification.ts +53 -0
- package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +156 -0
- package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +156 -0
- package/src/modules/sales/widgets/notifications/index.ts +2 -0
- package/src/modules/sales/widgets/notifications/useSalesDocumentTotals.ts +81 -0
- package/src/modules/staff/backend/staff/team-members/page.tsx +1 -1
- package/src/modules/staff/backend/staff/team-roles/page.tsx +2 -2
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +2 -2
- package/src/modules/staff/backend/staff/teams/page.tsx +2 -2
- package/src/modules/staff/commands/leave-requests.ts +94 -0
- package/src/modules/staff/i18n/de.json +4 -0
- package/src/modules/staff/i18n/en.json +9 -1
- package/src/modules/staff/i18n/es.json +4 -0
- package/src/modules/staff/i18n/pl.json +4 -0
- package/src/modules/staff/notifications.ts +71 -0
- package/src/modules/workflows/acl.ts +0 -2
- package/src/modules/workflows/api/__tests__/instances.route.test.ts +2 -5
- package/src/modules/workflows/api/instances/route.ts +7 -21
- package/src/modules/workflows/api/tasks/route.ts +1 -7
- package/src/modules/workflows/backend/definitions/[id]/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/[id]/page.tsx +0 -9
- package/src/modules/workflows/backend/definitions/create/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/create/page.tsx +0 -9
- package/src/modules/workflows/backend/definitions/page.tsx +5 -0
- package/src/modules/workflows/backend/definitions/visual-editor/page.meta.ts +1 -1
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +3 -21
- package/src/modules/workflows/backend/events/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/events/[id]/page.tsx +1 -1
- package/src/modules/workflows/backend/instances/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/instances/page.tsx +4 -1
- package/src/modules/workflows/backend/tasks/[id]/page.meta.ts +2 -2
- package/src/modules/workflows/backend/tasks/[id]/page.tsx +1 -1
- package/src/modules/workflows/backend/tasks/page.tsx +10 -6
- package/src/modules/workflows/cli.ts +12 -123
- package/src/modules/workflows/data/entities.ts +0 -124
- package/src/modules/workflows/data/validators.ts +0 -138
- package/src/modules/workflows/examples/checkout-demo-definition.json +5 -1
- package/src/modules/workflows/i18n/en.json +3 -72
- package/src/modules/workflows/lib/__tests__/activity-executor.test.ts +36 -43
- package/src/modules/workflows/lib/__tests__/transition-handler.test.ts +90 -170
- package/src/modules/workflows/lib/activity-executor.ts +16 -129
- package/src/modules/workflows/lib/graph-utils.ts +2 -117
- package/src/modules/workflows/lib/seeds.ts +8 -34
- package/src/modules/workflows/lib/start-validator.ts +28 -38
- package/src/modules/workflows/lib/transition-handler.ts +71 -212
- package/src/modules/workflows/notifications.ts +25 -0
- package/src/modules/workflows/subscribers/task-assigned-notification.ts +53 -0
- package/dist/generated/entities/workflow_event_trigger/index.js +0 -33
- package/dist/generated/entities/workflow_event_trigger/index.js.map +0 -7
- package/dist/modules/auth/events.js +0 -30
- package/dist/modules/auth/events.js.map +0 -7
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js +0 -145
- package/dist/modules/business_rules/api/execute/[ruleId]/route.js.map +0 -7
- package/dist/modules/catalog/events.js +0 -34
- package/dist/modules/catalog/events.js.map +0 -7
- package/dist/modules/customers/events.js +0 -49
- package/dist/modules/customers/events.js.map +0 -7
- package/dist/modules/directory/events.js +0 -23
- package/dist/modules/directory/events.js.map +0 -7
- package/dist/modules/sales/events.js +0 -63
- package/dist/modules/sales/events.js.map +0 -7
- package/dist/modules/sales/lib/frontend/documentDataEvents.js +0 -25
- package/dist/modules/sales/lib/frontend/documentDataEvents.js.map +0 -7
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +0 -481
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +0 -7
- package/dist/modules/workflows/components/EventTriggersEditor.js +0 -553
- package/dist/modules/workflows/components/EventTriggersEditor.js.map +0 -7
- package/dist/modules/workflows/events.js +0 -38
- package/dist/modules/workflows/events.js.map +0 -7
- package/dist/modules/workflows/examples/order-approval-definition.json +0 -257
- package/dist/modules/workflows/examples/order-approval-guard-rules.json +0 -32
- package/dist/modules/workflows/lib/event-trigger-service.js +0 -308
- package/dist/modules/workflows/lib/event-trigger-service.js.map +0 -7
- package/dist/modules/workflows/migrations/Migration20260123143500.js +0 -36
- package/dist/modules/workflows/migrations/Migration20260123143500.js.map +0 -7
- package/dist/modules/workflows/subscribers/event-trigger.js +0 -78
- package/dist/modules/workflows/subscribers/event-trigger.js.map +0 -7
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js +0 -323
- package/dist/modules/workflows/widgets/injection/order-approval/widget.client.js.map +0 -7
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js +0 -17
- package/dist/modules/workflows/widgets/injection/order-approval/widget.js.map +0 -7
- package/dist/modules/workflows/widgets/injection-table.js +0 -19
- package/dist/modules/workflows/widgets/injection-table.js.map +0 -7
- package/generated/entities/workflow_event_trigger/index.ts +0 -15
- package/src/modules/auth/events.ts +0 -39
- package/src/modules/business_rules/api/execute/[ruleId]/route.ts +0 -163
- package/src/modules/catalog/events.ts +0 -45
- package/src/modules/customers/events.ts +0 -63
- package/src/modules/directory/events.ts +0 -31
- package/src/modules/sales/events.ts +0 -82
- package/src/modules/sales/lib/frontend/documentDataEvents.ts +0 -28
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +0 -581
- package/src/modules/workflows/components/EventTriggersEditor.tsx +0 -664
- package/src/modules/workflows/events.ts +0 -49
- package/src/modules/workflows/examples/order-approval-definition.json +0 -257
- package/src/modules/workflows/examples/order-approval-guard-rules.json +0 -32
- package/src/modules/workflows/lib/event-trigger-service.ts +0 -557
- package/src/modules/workflows/migrations/Migration20260123143500.ts +0 -38
- package/src/modules/workflows/subscribers/event-trigger.ts +0 -109
- package/src/modules/workflows/widgets/injection/order-approval/widget.client.tsx +0 -446
- package/src/modules/workflows/widgets/injection/order-approval/widget.ts +0 -16
- package/src/modules/workflows/widgets/injection-table.ts +0 -21
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/directory/backend/directory/tenants/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'\nimport type { FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype TenantRow = {\n id: string\n name: string\n isActive: boolean\n createdAt: string | null\n updatedAt: string | null\n}\n\ntype TenantsResponse = {\n items: TenantRow[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n}\n\n\nexport default function DirectoryTenantsPage() {\n const queryClient = useQueryClient()\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'name', desc: false }])\n const [page, setPage] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [filters, setFilters] = React.useState<FilterValues>({})\n const [canManage, setCanManage] = React.useState(false)\n const scopeVersion = useOrganizationScopeVersion()\n const t = useT()\n const columns = React.useMemo<ColumnDef<TenantRow>[]>(() => [\n { accessorKey: 'name', header: t('directory.tenants.list.columns.tenant', 'Tenant'), meta: { priority: 1 } },\n {\n accessorKey: 'isActive',\n header: t('directory.tenants.list.columns.active', 'Active'),\n enableSorting: false,\n meta: { priority: 2 },\n cell: ({ getValue }) => <BooleanIcon value={Boolean(getValue())} />,\n },\n {\n accessorKey: 'createdAt',\n header: t('directory.tenants.list.columns.created', 'Created'),\n meta: { priority: 3 },\n cell: ({ getValue }) => {\n const timestamp = getValue() as string | null\n if (!timestamp) return <span className=\"text-xs text-muted-foreground\">\u2014</span>\n const date = new Date(timestamp)\n if (Number.isNaN(date.getTime())) return <span className=\"text-xs text-muted-foreground\">\u2014</span>\n return <span>{date.toLocaleString()}</span>\n },\n },\n ], [t])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadFeature() {\n try {\n const call = await apiCall<{ ok?: boolean; granted?: string[] }>('/api/auth/feature-check', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ features: ['directory.tenants.manage'] }),\n })\n if (!cancelled) {\n const granted = Array.isArray(call.result?.granted) ? call.result!.granted! : []\n setCanManage(call.result?.ok === true || granted.includes('directory.tenants.manage'))\n }\n } catch {\n if (!cancelled) setCanManage(false)\n }\n }\n loadFeature()\n return () => { cancelled = true }\n }, [])\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', '20')\n if (sorting.length > 0) {\n params.set('sortField', sorting[0]?.id || 'name')\n params.set('sortDir', sorting[0]?.desc ? 'desc' : 'asc')\n }\n if (search) params.set('search', search)\n if (filters.active !== undefined && filters.active !== '') params.set('isActive', String(filters.active))\n return params.toString()\n }, [page, sorting, search, filters])\n\n const { data, isLoading } = useQuery({\n queryKey: ['directory-tenants', queryParams, scopeVersion],\n queryFn: async (): Promise<TenantsResponse> => {\n return readApiResultOrThrow<TenantsResponse>(\n `/api/directory/tenants?${queryParams}`,\n undefined,\n { errorMessage: t('directory.tenants.list.error.load', 'Failed to load tenants') },\n )\n },\n })\n\n const rows = data?.items ?? []\n const total = data?.total ?? 0\n const totalPages = data?.totalPages ?? 1\n\n const handleDelete = React.useCallback(async (tenant: TenantRow) => {\n if (!window.confirm(t('directory.tenants.list.confirmDelete', 'Delete tenant \"{{name}}\"? This will archive it.').replace('{{name}}', tenant.name))) return\n try {\n const call = await apiCall(\n `/api/directory/tenants?id=${encodeURIComponent(tenant.id)}`,\n { method: 'DELETE' },\n )\n if (!call.ok) {\n await raiseCrudError(call.response, t('directory.tenants.list.error.delete', 'Failed to delete tenant'))\n }\n await queryClient.invalidateQueries({ queryKey: ['directory-tenants'] })\n flash(t('directory.tenants.list.success.delete', 'Tenant deleted'), 'success')\n } catch (err: any) {\n const message = err instanceof Error ? err.message : t('directory.tenants.list.error.delete', 'Failed to delete tenant')\n flash(message, 'error')\n }\n }, [queryClient, t])\n\n return (\n <Page>\n <PageBody>\n <DataTable\n title={t('directory.tenants.list.title', 'Tenants')}\n actions={canManage ? (\n <Button asChild>\n <Link href=\"/backend/directory/tenants/create\">{t('directory.tenants.list.actions.create', 'Create')}</Link>\n </Button>\n ) : undefined}\n columns={columns}\n data={rows}\n searchValue={search}\n onSearchChange={(value) => { setSearch(value); setPage(1) }}\n filters={[{ id: 'active', label: t('directory.tenants.list.filters.status', 'Status'), type: 'select', options: [\n { value: 'true', label: t('directory.tenants.list.filters.active', 'Active') },\n { value: 'false', label: t('directory.tenants.list.filters.inactive', 'Inactive') },\n ] }]}\n filterValues={filters}\n onFiltersApply={(vals) => { setFilters(vals); setPage(1) }}\n onFiltersClear={() => { setFilters({}); setPage(1) }}\n sortable\n sorting={sorting}\n onSortingChange={(state) => { setSorting(state); setPage(1) }}\n perspective={{ tableId: 'directory.tenants.list' }}\n rowActions={(row) => (\n canManage ? (\n <RowActions\n items={[\n { label: t('common.edit', 'Edit'), href: `/backend/directory/tenants/${row.id}/edit` },\n { label: t('common.delete', 'Delete'), destructive: true, onSelect: () => handleDelete(row) },\n ]}\n />\n ) : null\n )}\n pagination={{ page, pageSize: 20, total, totalPages, onPageChange: setPage }}\n isLoading={isLoading}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'\nimport type { FilterValues } from '@open-mercato/ui/backend/FilterBar'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype TenantRow = {\n id: string\n name: string\n isActive: boolean\n createdAt: string | null\n updatedAt: string | null\n}\n\ntype TenantsResponse = {\n items: TenantRow[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n}\n\n\nexport default function DirectoryTenantsPage() {\n const queryClient = useQueryClient()\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'name', desc: false }])\n const [page, setPage] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [filters, setFilters] = React.useState<FilterValues>({})\n const [canManage, setCanManage] = React.useState(false)\n const scopeVersion = useOrganizationScopeVersion()\n const t = useT()\n const columns = React.useMemo<ColumnDef<TenantRow>[]>(() => [\n { accessorKey: 'name', header: t('directory.tenants.list.columns.tenant', 'Tenant'), meta: { priority: 1 } },\n {\n accessorKey: 'isActive',\n header: t('directory.tenants.list.columns.active', 'Active'),\n enableSorting: false,\n meta: { priority: 2 },\n cell: ({ getValue }) => <BooleanIcon value={Boolean(getValue())} />,\n },\n {\n accessorKey: 'createdAt',\n header: t('directory.tenants.list.columns.created', 'Created'),\n meta: { priority: 3 },\n cell: ({ getValue }) => {\n const timestamp = getValue() as string | null\n if (!timestamp) return <span className=\"text-xs text-muted-foreground\">\u2014</span>\n const date = new Date(timestamp)\n if (Number.isNaN(date.getTime())) return <span className=\"text-xs text-muted-foreground\">\u2014</span>\n return <span>{date.toLocaleString()}</span>\n },\n },\n ], [t])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadFeature() {\n try {\n const call = await apiCall<{ ok?: boolean; granted?: string[] }>('/api/auth/feature-check', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ features: ['directory.tenants.manage'] }),\n })\n if (!cancelled) {\n const granted = Array.isArray(call.result?.granted) ? call.result!.granted! : []\n setCanManage(call.result?.ok === true || granted.includes('directory.tenants.manage'))\n }\n } catch {\n if (!cancelled) setCanManage(false)\n }\n }\n loadFeature()\n return () => { cancelled = true }\n }, [])\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', '20')\n if (sorting.length > 0) {\n params.set('sortField', sorting[0]?.id || 'name')\n params.set('sortDir', sorting[0]?.desc ? 'desc' : 'asc')\n }\n if (search) params.set('search', search)\n if (filters.active !== undefined && filters.active !== '') params.set('isActive', String(filters.active))\n return params.toString()\n }, [page, sorting, search, filters])\n\n const { data, isLoading } = useQuery({\n queryKey: ['directory-tenants', queryParams, scopeVersion],\n queryFn: async (): Promise<TenantsResponse> => {\n return readApiResultOrThrow<TenantsResponse>(\n `/api/directory/tenants?${queryParams}`,\n undefined,\n { errorMessage: t('directory.tenants.list.error.load', 'Failed to load tenants') },\n )\n },\n })\n\n const rows = data?.items ?? []\n const total = data?.total ?? 0\n const totalPages = data?.totalPages ?? 1\n\n const handleDelete = React.useCallback(async (tenant: TenantRow) => {\n if (!window.confirm(t('directory.tenants.list.confirmDelete', 'Delete tenant \"{{name}}\"? This will archive it.').replace('{{name}}', tenant.name))) return\n try {\n const call = await apiCall(\n `/api/directory/tenants?id=${encodeURIComponent(tenant.id)}`,\n { method: 'DELETE' },\n )\n if (!call.ok) {\n await raiseCrudError(call.response, t('directory.tenants.list.error.delete', 'Failed to delete tenant'))\n }\n await queryClient.invalidateQueries({ queryKey: ['directory-tenants'] })\n flash(t('directory.tenants.list.success.delete', 'Tenant deleted'), 'success')\n } catch (err: any) {\n const message = err instanceof Error ? err.message : t('directory.tenants.list.error.delete', 'Failed to delete tenant')\n flash(message, 'error')\n }\n }, [queryClient, t])\n\n return (\n <Page>\n <PageBody>\n <DataTable\n title={t('directory.tenants.list.title', 'Tenants')}\n actions={canManage ? (\n <Button asChild>\n <Link href=\"/backend/directory/tenants/create\">{t('directory.tenants.list.actions.create', 'Create')}</Link>\n </Button>\n ) : undefined}\n columns={columns}\n data={rows}\n searchValue={search}\n onSearchChange={(value) => { setSearch(value); setPage(1) }}\n filters={[{ id: 'active', label: t('directory.tenants.list.filters.status', 'Status'), type: 'select', options: [\n { value: 'true', label: t('directory.tenants.list.filters.active', 'Active') },\n { value: 'false', label: t('directory.tenants.list.filters.inactive', 'Inactive') },\n ] }]}\n filterValues={filters}\n onFiltersApply={(vals) => { setFilters(vals); setPage(1) }}\n onFiltersClear={() => { setFilters({}); setPage(1) }}\n sortable\n sorting={sorting}\n onSortingChange={(state) => { setSorting(state); setPage(1) }}\n perspective={{ tableId: 'directory.tenants.list' }}\n rowActions={(row) => (\n canManage ? (\n <RowActions\n items={[\n { id: 'edit', label: t('common.edit', 'Edit'), href: `/backend/directory/tenants/${row.id}/edit` },\n { id: 'delete', label: t('common.delete', 'Delete'), destructive: true, onSelect: () => handleDelete(row) },\n ]}\n />\n ) : null\n )}\n pagination={{ page, pageSize: 20, total, totalPages, onPageChange: setPage }}\n isLoading={isLoading}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -281,8 +281,8 @@ export RECORD_ID="<record uuid>"` }) }),
|
|
|
281
281
|
RowActions,
|
|
282
282
|
{
|
|
283
283
|
items: [
|
|
284
|
-
{ label: "Edit", href: `/backend/entities/user/${encodeURIComponent(entityId)}/records/${encodeURIComponent(String(row.id))}` },
|
|
285
|
-
{ label: "Delete", destructive: true, onSelect: async () => {
|
|
284
|
+
{ id: "edit", label: "Edit", href: `/backend/entities/user/${encodeURIComponent(entityId)}/records/${encodeURIComponent(String(row.id))}` },
|
|
285
|
+
{ id: "delete", label: "Delete", destructive: true, onSelect: async () => {
|
|
286
286
|
try {
|
|
287
287
|
if (typeof window !== "undefined") {
|
|
288
288
|
const ok = window.confirm("Delete this record?");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../../src/modules/entities/backend/entities/user/%5BentityId%5D/records/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useSearchParams } from 'next/navigation'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { filterCustomFieldDefs, useCustomFieldDefs } from '@open-mercato/ui/backend/utils/customFieldDefs'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable, type DataTableExportFormat } from '@open-mercato/ui/backend/DataTable'\nimport type { PreparedExport } from '@open-mercato/shared/lib/crud/exporters'\nimport type { FilterDef } from '@open-mercato/ui/backend/FilterBar'\nimport { ContextHelp } from '@open-mercato/ui/backend/ContextHelp'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport Link from 'next/link'\nimport { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\n\ntype RecordsResponse = {\n items: any[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n}\n\nfunction toCsvUrl(base: string, params: URLSearchParams) {\n // Build a relative URL to avoid SSR/CSR origin mismatch hydration issues\n const p = new URLSearchParams(params)\n p.set('format', 'csv')\n const qs = p.toString()\n return qs ? `${base}?${qs}` : base\n}\n\nfunction normalizeCell(v: any): string {\n if (Array.isArray(v)) return v.filter((x) => x != null && x !== '').join(', ')\n if (v === true) return 'Yes'\n if (v === false) return 'No'\n if (v == null) return ''\n if (v instanceof Date) return v.toISOString()\n return String(v)\n}\n\nexport default function RecordsPage({ params }: { params: { entityId?: string } }) {\n const entityId = decodeURIComponent(params?.entityId || '')\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'id', desc: false }])\n const [page, setPage] = React.useState(1)\n const [pageSize, setPageSize] = React.useState(50)\n const [search, setSearch] = React.useState('')\n const [filterValues, setFilterValues] = React.useState<Record<string, any>>({})\n const [columns, setColumns] = React.useState<ColumnDef<any>[]>([])\n const [rawData, setRawData] = React.useState<any[]>([])\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [loading, setLoading] = React.useState(false)\n const scopeVersion = useOrganizationScopeVersion()\n const { data: cfDefs = [] } = useCustomFieldDefs(entityId, {\n enabled: Boolean(entityId),\n keyExtras: [scopeVersion],\n })\n\n // Fetch records whenever paging/sorting/filters change (do NOT refetch on cfDefs/search changes)\n React.useEffect(() => {\n let cancelled = false\n const run = async () => {\n setLoading(true)\n try {\n const params = new URLSearchParams()\n params.set('entityId', entityId)\n params.set('page', String(page))\n params.set('pageSize', String(pageSize))\n const s = sorting?.[0]\n if (s?.id) {\n params.set('sortField', String(s.id))\n params.set('sortDir', s.desc ? 'desc' : 'asc')\n }\n // Flatten filter values into query params\n for (const [k, v] of Object.entries(filterValues)) {\n if (v == null) continue\n if (Array.isArray(v)) {\n if (v.length) params.set(k, v.join(','))\n } else if (typeof v === 'object') {\n // dateRange-like shapes are not supported generically here; skip\n } else {\n params.set(k, String(v))\n }\n }\n const j = await readApiResultOrThrow<RecordsResponse>(\n `/api/entities/records?${params.toString()}`,\n undefined,\n {\n errorMessage: 'Failed to load records',\n fallback: {\n items: [],\n total: 0,\n page,\n pageSize,\n totalPages: 1,\n },\n },\n )\n if (!cancelled) {\n setRawData(j.items || [])\n setTotal(j.total)\n setTotalPages(j.totalPages)\n }\n } catch (e) {\n if (!cancelled) {\n setRawData([])\n setTotal(0)\n setTotalPages(1)\n }\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n if (entityId) run()\n return () => { cancelled = true }\n }, [entityId, page, pageSize, sorting, filterValues, scopeVersion])\n\n // Build columns from custom field definitions only (no data round-trip)\n React.useEffect(() => {\n const visibleDefs = filterCustomFieldDefs(cfDefs, 'list') as any\n const maxVisible = 10\n const cols: ColumnDef<any>[] = visibleDefs.map((d: any, idx: number) => ({\n accessorKey: d.key,\n header: d.label || d.key,\n meta: { priority: idx < 4 ? 1 : idx < 6 ? 2 : idx < 8 ? 3 : idx < maxVisible ? 4 : 5 },\n cell: ({ getValue }: { getValue: () => unknown }) => {\n const v = getValue() as any\n return <span className=\"truncate max-w-[24ch] inline-block align-top\" title={normalizeCell(v)}>{normalizeCell(v)}</span>\n },\n }))\n // Ensure hidden 'id' column exists for sorting/state\n const hasIdCol = cols.some((c) => (c as any).accessorKey === 'id' || (c as any).id === 'id')\n if (!hasIdCol) cols.unshift({ accessorKey: 'id', header: 'ID', meta: { hidden: true, priority: 6 } } as any)\n setColumns(cols)\n }, [cfDefs])\n\n // Client-side quick search filtering without triggering server refetch\n const data = React.useMemo(() => {\n if (!search.trim()) return rawData\n const q = search.trim().toLowerCase()\n return (rawData || []).filter((row: any) => {\n const values = Object.values(row || {})\n return values.some((v) => normalizeCell(v).toLowerCase().includes(q))\n })\n }, [rawData, search])\n\n const viewExportColumns = React.useMemo(() => {\n return (columns || [])\n .map((col) => {\n const accessorKey = (col as any).accessorKey\n if (!accessorKey || typeof accessorKey !== 'string') return null\n if ((col as any).meta?.hidden) return null\n const header = typeof col.header === 'string'\n ? col.header\n : accessorKey.startsWith('cf_')\n ? accessorKey.slice(3)\n : accessorKey\n return { field: accessorKey, header }\n })\n .filter((col): col is { field: string; header: string } => !!col)\n }, [columns])\n\n const buildFullExportUrl = React.useCallback((format: DataTableExportFormat) => {\n const qp = new URLSearchParams({\n entityId,\n format,\n exportScope: 'full',\n all: 'true',\n })\n const sort = sorting?.[0]\n if (sort?.id) {\n qp.set('sortField', String(sort.id))\n qp.set('sortDir', sort.desc ? 'desc' : 'asc')\n }\n return `/api/entities/records?${qp.toString()}`\n }, [entityId, sorting])\n\n const exportConfig = React.useMemo(() => {\n const safeEntityId = entityId.replace(/[^a-z0-9_-]/gi, '_') || 'records'\n return {\n view: {\n description: 'Exports the current list respecting filters and column visibility.',\n prepare: async (): Promise<{ prepared: PreparedExport; filename: string }> => {\n const rowsForExport = data.map((row) => {\n const out: Record<string, unknown> = {}\n for (const col of viewExportColumns) {\n out[col.field] = (row as Record<string, unknown>)[col.field]\n }\n return out\n })\n const prepared: PreparedExport = {\n columns: viewExportColumns.map((col) => ({ field: col.field, header: col.header })),\n rows: rowsForExport,\n }\n return { prepared, filename: `${safeEntityId}_view` }\n },\n },\n full: {\n description: 'Exports raw records with every field and custom field included.',\n getUrl: (format: DataTableExportFormat) => buildFullExportUrl(format),\n filename: () => `${safeEntityId}_full`,\n },\n }\n }, [buildFullExportUrl, data, entityId, viewExportColumns])\n\n const hasAnyFormFields = React.useMemo(() => filterCustomFieldDefs(cfDefs, 'form').length > 0, [cfDefs])\n const actions = (\n <>\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href={`/backend/entities/user/${encodeURIComponent(entityId)}`}>\n Edit Entity Definition\n </Link>\n </Button>\n {hasAnyFormFields && (\n <Button asChild>\n <Link href={`/backend/entities/user/${encodeURIComponent(entityId)}/records/create`}>\n Create\n </Link>\n </Button>\n )}\n </>\n )\n\n // Ensure filters are visible even if no custom fields are marked filterable\n const baseFilters: FilterDef[] = React.useMemo(() => ([\n { id: 'id', label: 'ID', type: 'text' },\n ]), [])\n\n return (\n <Page>\n <PageBody>\n <ContextHelp bulb title=\"API: Manage Records via cURL\" className=\"mb-4\">\n <p className=\"mb-2\">\n Interact with this custom entity via the backend API using cURL. Use API keys for machine-to-machine access\u2014mint one from the{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/user-guide/api-keys\">\n Managing API keys guide\n </a>{' '}\n or the{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/cli/api-keys\">\n API keys CLI documentation\n </a>{' '}\n before running these calls.\n </p>\n <div className=\"space-y-2\">\n <div>\n <div className=\"font-medium mb-1\">1) Configure environment variables</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`export BASE_URL=\"http://localhost:3000/api\"\nexport API_KEY=\"<paste API key secret here>\" # scoped with entities.features\nexport ENTITY_ID=\"${entityId}\"\nexport RECORD_ID=\"<record uuid>\"`}</code></pre>\n <p className=\"text-muted-foreground mt-1\">\n Need a new key? Follow the{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/user-guide/api-keys\">\n Managing API keys\n </a>{' '}\n walkthrough or mint one via{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/cli/api-keys\">\n mercato api_keys add\n </a>\n .\n </p>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">2) List records</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -H \"X-Api-Key: $API_KEY\" \\\n \"$BASE_URL/entities/records?entityId=$ENTITY_ID\" | jq`}</code></pre>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">3) Read a single record (by id)</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -H \"X-Api-Key: $API_KEY\" \\\n \"$BASE_URL/entities/records?entityId=$ENTITY_ID&id=$RECORD_ID\" | jq`}</code></pre>\n <p className=\"text-muted-foreground mt-1\">Note: Response is a list; filter by <code>id</code> to get a single item.</p>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">4) Create a record</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -X POST \\\n -H \"X-Api-Key: $API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d \"{\n \\\\\"entityId\\\\\": \\\\\"$ENTITY_ID\\\\\",\n \\\\\"values\\\\\": {\n \\\\\"field_one\\\\\": \\\\\"Example\\\\\",\n \\\\\"field_two\\\\\": 123\n }\n }\" \\\n \"$BASE_URL/entities/records\" | jq`}</code></pre>\n <p className=\"text-muted-foreground mt-1\">For custom entities, send field keys without the <code>cf_</code> prefix. The API normalizes this server-side.</p>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">5) Update a record</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -X PUT \\\n -H \"X-Api-Key: $API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d \"{\n \\\\\"entityId\\\\\": \\\\\"$ENTITY_ID\\\\\",\n \\\\\"recordId\\\\\": \\\\\"$RECORD_ID\\\\\",\n \\\\\"values\\\\\": {\n \\\\\"field_one\\\\\": \\\\\"Updated\\\\\"\n }\n }\" \\\n \"$BASE_URL/entities/records\" | jq`}</code></pre>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">6) Delete a record</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -X DELETE \\\n -H \"X-Api-Key: $API_KEY\" \\\n \"$BASE_URL/entities/records?entityId=$ENTITY_ID&recordId=$RECORD_ID\" | jq`}</code></pre>\n </div>\n\n <div className=\"text-muted-foreground\">\n Security notes:\n <ul className=\"list-disc pl-5 mt-1 space-y-1\">\n <li>All endpoints require a valid API key. Keys inherit tenant, organization, and feature scope.</li>\n <li>Rotate keys regularly and delete unused ones in the admin UI.</li>\n <li>Store the secret in a secure vault; anyone with the header can act within the key's permissions.</li>\n </ul>\n </div>\n </div>\n </ContextHelp>\n <DataTable\n title={`Records: ${entityId}`}\n entityId={entityId}\n actions={actions}\n columns={columns}\n data={data}\n perspective={{ tableId: `entities.user.records.${entityId}` }}\n exporter={exportConfig}\n filters={baseFilters}\n filterValues={filterValues}\n rowActions={(row) => (\n <RowActions\n items={[\n { label: 'Edit', href: `/backend/entities/user/${encodeURIComponent(entityId)}/records/${encodeURIComponent(String((row as any).id))}` },\n { label: 'Delete', destructive: true, onSelect: async () => {\n try {\n if (typeof window !== 'undefined') {\n const ok = window.confirm('Delete this record?')\n if (!ok) return\n }\n const deleteCall = await apiCall(\n `/api/entities/records?entityId=${encodeURIComponent(entityId)}&recordId=${encodeURIComponent(String((row as any).id))}`,\n { method: 'DELETE' },\n )\n if (!deleteCall.ok) {\n await raiseCrudError(deleteCall.response, 'Failed to delete record')\n }\n const j = await readApiResultOrThrow<RecordsResponse>(\n `/api/entities/records?entityId=${encodeURIComponent(entityId)}&page=${page}&pageSize=${pageSize}`,\n undefined,\n {\n errorMessage: 'Failed to reload records',\n fallback: { items: [], total: 0, page, pageSize, totalPages: 1 },\n },\n )\n setRawData(j.items || [])\n setTotal(j.total || 0)\n setTotalPages(j.totalPages || 1)\n flash('Record has been removed', 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to delete record'\n flash(message, 'error')\n }\n } },\n ]}\n />\n )}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n searchValue={search}\n onSearchChange={(v) => { setSearch(v); setPage(1) }}\n onFiltersApply={(vals) => { setFilterValues(vals); setPage(1) }}\n onFiltersClear={() => { setFilterValues({}); setPage(1) }}\n pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}\n isLoading={loading}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": ";AAkIe,SAgFX,UAhFW,KAgFX,YAhFW;AAjIf,YAAY,WAAW;AAGvB,SAAS,uBAAuB,0BAA0B;AAC1D,SAAS,MAAM,gBAAgB;AAC/B,SAAS,iBAA6C;AAGtD,SAAS,mBAAmB;AAC5B,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,OAAO,UAAU;AACjB,SAAS,SAAS,4BAA4B;AAC9C,SAAS,aAAa;AACtB,SAAS,sBAAsB;AAC/B,SAAS,mCAAmC;AAU5C,SAAS,SAAS,MAAc,QAAyB;AAEvD,QAAM,IAAI,IAAI,gBAAgB,MAAM;AACpC,IAAE,IAAI,UAAU,KAAK;AACrB,QAAM,KAAK,EAAE,SAAS;AACtB,SAAO,KAAK,GAAG,IAAI,IAAI,EAAE,KAAK;AAChC;AAEA,SAAS,cAAc,GAAgB;AACrC,MAAI,MAAM,QAAQ,CAAC,EAAG,QAAO,EAAE,OAAO,CAAC,MAAM,KAAK,QAAQ,MAAM,EAAE,EAAE,KAAK,IAAI;AAC7E,MAAI,MAAM,KAAM,QAAO;AACvB,MAAI,MAAM,MAAO,QAAO;AACxB,MAAI,KAAK,KAAM,QAAO;AACtB,MAAI,aAAa,KAAM,QAAO,EAAE,YAAY;AAC5C,SAAO,OAAO,CAAC;AACjB;AAEe,SAAR,YAA6B,EAAE,OAAO,GAAsC;AACjF,QAAM,WAAW,mBAAmB,QAAQ,YAAY,EAAE;AAC1D,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAuB,CAAC,EAAE,IAAI,MAAM,MAAM,MAAM,CAAC,CAAC;AACtF,QAAM,CAAC,MAAM,OAAO,IAAI,MAAM,SAAS,CAAC;AACxC,QAAM,CAAC,UAAU,WAAW,IAAI,MAAM,SAAS,EAAE;AACjD,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,EAAE;AAC7C,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAA8B,CAAC,CAAC;AAC9E,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAA2B,CAAC,CAAC;AACjE,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAgB,CAAC,CAAC;AACtD,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAS,CAAC;AAC1C,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,CAAC;AACpD,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAS,KAAK;AAClD,QAAM,eAAe,4BAA4B;AACjD,QAAM,EAAE,MAAM,SAAS,CAAC,EAAE,IAAI,mBAAmB,UAAU;AAAA,IACzD,SAAS,QAAQ,QAAQ;AAAA,IACzB,WAAW,CAAC,YAAY;AAAA,EAC1B,CAAC;AAGD,QAAM,UAAU,MAAM;AACpB,QAAI,YAAY;AAChB,UAAM,MAAM,YAAY;AACtB,iBAAW,IAAI;AACf,UAAI;AACF,cAAMA,UAAS,IAAI,gBAAgB;AACnC,QAAAA,QAAO,IAAI,YAAY,QAAQ;AAC/B,QAAAA,QAAO,IAAI,QAAQ,OAAO,IAAI,CAAC;AAC/B,QAAAA,QAAO,IAAI,YAAY,OAAO,QAAQ,CAAC;AACvC,cAAM,IAAI,UAAU,CAAC;AACrB,YAAI,GAAG,IAAI;AACT,UAAAA,QAAO,IAAI,aAAa,OAAO,EAAE,EAAE,CAAC;AACpC,UAAAA,QAAO,IAAI,WAAW,EAAE,OAAO,SAAS,KAAK;AAAA,QAC/C;AAEA,mBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,YAAY,GAAG;AACjD,cAAI,KAAK,KAAM;AACf,cAAI,MAAM,QAAQ,CAAC,GAAG;AACpB,gBAAI,EAAE,OAAQ,CAAAA,QAAO,IAAI,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA,UACzC,WAAW,OAAO,MAAM,UAAU;AAAA,UAElC,OAAO;AACL,YAAAA,QAAO,IAAI,GAAG,OAAO,CAAC,CAAC;AAAA,UACzB;AAAA,QACF;AACA,cAAM,IAAI,MAAM;AAAA,UACd,yBAAyBA,QAAO,SAAS,CAAC;AAAA,UAC1C;AAAA,UACA;AAAA,YACE,cAAc;AAAA,YACd,UAAU;AAAA,cACR,OAAO,CAAC;AAAA,cACR,OAAO;AAAA,cACP;AAAA,cACA;AAAA,cACA,YAAY;AAAA,YACd;AAAA,UACF;AAAA,QACF;AACA,YAAI,CAAC,WAAW;AACd,qBAAW,EAAE,SAAS,CAAC,CAAC;AACxB,mBAAS,EAAE,KAAK;AAChB,wBAAc,EAAE,UAAU;AAAA,QAC5B;AAAA,MACF,SAAS,GAAG;AACV,YAAI,CAAC,WAAW;AACd,qBAAW,CAAC,CAAC;AACb,mBAAS,CAAC;AACV,wBAAc,CAAC;AAAA,QACjB;AAAA,MACF,UAAE;AACA,YAAI,CAAC,UAAW,YAAW,KAAK;AAAA,MAClC;AAAA,IACF;AACA,QAAI,SAAU,KAAI;AAClB,WAAO,MAAM;AAAE,kBAAY;AAAA,IAAK;AAAA,EAClC,GAAG,CAAC,UAAU,MAAM,UAAU,SAAS,cAAc,YAAY,CAAC;AAGlE,QAAM,UAAU,MAAM;AACpB,UAAM,cAAc,sBAAsB,QAAQ,MAAM;AACxD,UAAM,aAAa;AACnB,UAAM,OAAyB,YAAY,IAAI,CAAC,GAAQ,SAAiB;AAAA,MACvE,aAAa,EAAE;AAAA,MACf,QAAQ,EAAE,SAAS,EAAE;AAAA,MACrB,MAAM,EAAE,UAAU,MAAM,IAAI,IAAI,MAAM,IAAI,IAAI,MAAM,IAAI,IAAI,MAAM,aAAa,IAAI,EAAE;AAAA,MACrF,MAAM,CAAC,EAAE,SAAS,MAAmC;AACnD,cAAM,IAAI,SAAS;AACnB,eAAO,oBAAC,UAAK,WAAU,gDAA+C,OAAO,cAAc,CAAC,GAAI,wBAAc,CAAC,GAAE;AAAA,MACnH;AAAA,IACF,EAAE;AAEF,UAAM,WAAW,KAAK,KAAK,CAAC,MAAO,EAAU,gBAAgB,QAAS,EAAU,OAAO,IAAI;AAC3F,QAAI,CAAC,SAAU,MAAK,QAAQ,EAAE,aAAa,MAAM,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,UAAU,EAAE,EAAE,CAAQ;AAC3G,eAAW,IAAI;AAAA,EACjB,GAAG,CAAC,MAAM,CAAC;AAGX,QAAM,OAAO,MAAM,QAAQ,MAAM;AAC/B,QAAI,CAAC,OAAO,KAAK,EAAG,QAAO;AAC3B,UAAM,IAAI,OAAO,KAAK,EAAE,YAAY;AACpC,YAAQ,WAAW,CAAC,GAAG,OAAO,CAAC,QAAa;AAC1C,YAAM,SAAS,OAAO,OAAO,OAAO,CAAC,CAAC;AACtC,aAAO,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;AAAA,IACtE,CAAC;AAAA,EACH,GAAG,CAAC,SAAS,MAAM,CAAC;AAEpB,QAAM,oBAAoB,MAAM,QAAQ,MAAM;AAC5C,YAAQ,WAAW,CAAC,GACjB,IAAI,CAAC,QAAQ;AACZ,YAAM,cAAe,IAAY;AACjC,UAAI,CAAC,eAAe,OAAO,gBAAgB,SAAU,QAAO;AAC5D,UAAK,IAAY,MAAM,OAAQ,QAAO;AACtC,YAAM,SAAS,OAAO,IAAI,WAAW,WACjC,IAAI,SACJ,YAAY,WAAW,KAAK,IAC1B,YAAY,MAAM,CAAC,IACnB;AACN,aAAO,EAAE,OAAO,aAAa,OAAO;AAAA,IACtC,CAAC,EACA,OAAO,CAAC,QAAkD,CAAC,CAAC,GAAG;AAAA,EACpE,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,qBAAqB,MAAM,YAAY,CAAC,WAAkC;AAC9E,UAAM,KAAK,IAAI,gBAAgB;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,aAAa;AAAA,MACb,KAAK;AAAA,IACP,CAAC;AACD,UAAM,OAAO,UAAU,CAAC;AACxB,QAAI,MAAM,IAAI;AACZ,SAAG,IAAI,aAAa,OAAO,KAAK,EAAE,CAAC;AACnC,SAAG,IAAI,WAAW,KAAK,OAAO,SAAS,KAAK;AAAA,IAC9C;AACA,WAAO,yBAAyB,GAAG,SAAS,CAAC;AAAA,EAC/C,GAAG,CAAC,UAAU,OAAO,CAAC;AAEtB,QAAM,eAAe,MAAM,QAAQ,MAAM;AACvC,UAAM,eAAe,SAAS,QAAQ,iBAAiB,GAAG,KAAK;AAC/D,WAAO;AAAA,MACL,MAAM;AAAA,QACJ,aAAa;AAAA,QACb,SAAS,YAAqE;AAC5E,gBAAM,gBAAgB,KAAK,IAAI,CAAC,QAAQ;AACtC,kBAAM,MAA+B,CAAC;AACtC,uBAAW,OAAO,mBAAmB;AACnC,kBAAI,IAAI,KAAK,IAAK,IAAgC,IAAI,KAAK;AAAA,YAC7D;AACA,mBAAO;AAAA,UACT,CAAC;AACD,gBAAM,WAA2B;AAAA,YAC/B,SAAS,kBAAkB,IAAI,CAAC,SAAS,EAAE,OAAO,IAAI,OAAO,QAAQ,IAAI,OAAO,EAAE;AAAA,YAClF,MAAM;AAAA,UACR;AACA,iBAAO,EAAE,UAAU,UAAU,GAAG,YAAY,QAAQ;AAAA,QACtD;AAAA,MACF;AAAA,MACA,MAAM;AAAA,QACJ,aAAa;AAAA,QACb,QAAQ,CAAC,WAAkC,mBAAmB,MAAM;AAAA,QACpE,UAAU,MAAM,GAAG,YAAY;AAAA,MACjC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,oBAAoB,MAAM,UAAU,iBAAiB,CAAC;AAE1D,QAAM,mBAAmB,MAAM,QAAQ,MAAM,sBAAsB,QAAQ,MAAM,EAAE,SAAS,GAAG,CAAC,MAAM,CAAC;AACvG,QAAM,UACJ,iCACE;AAAA,wBAAC,UAAO,SAAO,MAAC,SAAQ,WAAU,MAAK,MACrC,8BAAC,QAAK,MAAM,0BAA0B,mBAAmB,QAAQ,CAAC,IAAI,oCAEtE,GACF;AAAA,IACC,oBACC,oBAAC,UAAO,SAAO,MACb,8BAAC,QAAK,MAAM,0BAA0B,mBAAmB,QAAQ,CAAC,mBAAmB,oBAErF,GACF;AAAA,KAEJ;AAIF,QAAM,cAA2B,MAAM,QAAQ,MAAO;AAAA,IACpD,EAAE,IAAI,MAAM,OAAO,MAAM,MAAM,OAAO;AAAA,EACxC,GAAI,CAAC,CAAC;AAEN,SACE,oBAAC,QACC,+BAAC,YACC;AAAA,yBAAC,eAAY,MAAI,MAAC,OAAM,gCAA+B,WAAU,QAC/D;AAAA,2BAAC,OAAE,WAAU,QAAO;AAAA;AAAA,QAC4G;AAAA,QAC9H,oBAAC,OAAE,WAAU,aAAY,QAAO,UAAS,KAAI,cAAa,MAAK,oDAAmD,qCAElH;AAAA,QAAK;AAAA,QAAI;AAAA,QACF;AAAA,QACP,oBAAC,OAAE,WAAU,aAAY,QAAO,UAAS,KAAI,cAAa,MAAK,6CAA4C,wCAE3G;AAAA,QAAK;AAAA,QAAI;AAAA,SAEX;AAAA,MACA,qBAAC,SAAI,WAAU,aACb;AAAA,6BAAC,SACC;AAAA,8BAAC,SAAI,WAAU,oBAAmB,gDAAkC;AAAA,UACpE,oBAAC,SAAI,WAAU,8CAA6C,8BAAC,UAAM;AAAA;AAAA,oBAE7D,QAAQ;AAAA,mCACM,GAAO;AAAA,UAC3B,qBAAC,OAAE,WAAU,8BAA6B;AAAA;AAAA,YACb;AAAA,YAC3B,oBAAC,OAAE,WAAU,aAAY,QAAO,UAAS,KAAI,cAAa,MAAK,oDAAmD,+BAElH;AAAA,YAAK;AAAA,YAAI;AAAA,YACmB;AAAA,YAC5B,oBAAC,OAAE,WAAU,aAAY,QAAO,UAAS,KAAI,cAAa,MAAK,6CAA4C,kCAE3G;AAAA,YAAI;AAAA,aAEN;AAAA,WACF;AAAA,QAEA,qBAAC,SACC;AAAA,8BAAC,SAAI,WAAU,oBAAmB,6BAAe;AAAA,UACjD,oBAAC,SAAI,WAAU,8CAA6C,8BAAC,UAAM,sGACxB,GAAO;AAAA,WACpD;AAAA,QAEA,qBAAC,SACC;AAAA,8BAAC,SAAI,WAAU,oBAAmB,6CAA+B;AAAA,UACjE,oBAAC,SAAI,WAAU,8CAA6C,8BAAC,UAAM,oHACV,GAAO;AAAA,UAChE,qBAAC,OAAE,WAAU,8BAA6B;AAAA;AAAA,YAAoC,oBAAC,UAAK,gBAAE;AAAA,YAAO;AAAA,aAAsB;AAAA,WACrH;AAAA,QAEA,qBAAC,SACC;AAAA,8BAAC,SAAI,WAAU,oBAAmB,gCAAkB;AAAA,UACpD,oBAAC,SAAI,WAAU,8CAA6C,8BAAC,UAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2CAU5C,GAAO;AAAA,UAC9B,qBAAC,OAAE,WAAU,8BAA6B;AAAA;AAAA,YAAiD,oBAAC,UAAK,iBAAG;AAAA,YAAO;AAAA,aAA6C;AAAA,WAC1J;AAAA,QAEA,qBAAC,SACC;AAAA,8BAAC,SAAI,WAAU,oBAAmB,gCAAkB;AAAA,UACpD,oBAAC,SAAI,WAAU,8CAA6C,8BAAC,UAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2CAU5C,GAAO;AAAA,WAChC;AAAA,QAEA,qBAAC,SACC;AAAA,8BAAC,SAAI,WAAU,oBAAmB,gCAAkB;AAAA,UACpD,oBAAC,SAAI,WAAU,8CAA6C,8BAAC,UAAM,sIAEJ,GAAO;AAAA,WACxE;AAAA,QAEA,qBAAC,SAAI,WAAU,yBAAwB;AAAA;AAAA,UAErC,qBAAC,QAAG,WAAU,iCACZ;AAAA,gCAAC,QAAG,0GAA4F;AAAA,YAChG,oBAAC,QAAG,2EAA6D;AAAA,YACjE,oBAAC,QAAG,8GAAqG;AAAA,aAC3G;AAAA,WACF;AAAA,SACF;AAAA,OACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,YAAY,QAAQ;AAAA,QAC3B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa,EAAE,SAAS,yBAAyB,QAAQ,GAAG;AAAA,QAC5D,UAAU;AAAA,QACV,SAAS;AAAA,QACT;AAAA,QACA,YAAY,CAAC,QACX;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,EAAE,OAAO,QAAQ,MAAM,0BAA0B,mBAAmB,QAAQ,CAAC,YAAY,mBAAmB,OAAQ,IAAY,EAAE,CAAC,CAAC,GAAG;AAAA,
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useSearchParams } from 'next/navigation'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { filterCustomFieldDefs, useCustomFieldDefs } from '@open-mercato/ui/backend/utils/customFieldDefs'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable, type DataTableExportFormat } from '@open-mercato/ui/backend/DataTable'\nimport type { PreparedExport } from '@open-mercato/shared/lib/crud/exporters'\nimport type { FilterDef } from '@open-mercato/ui/backend/FilterBar'\nimport { ContextHelp } from '@open-mercato/ui/backend/ContextHelp'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport Link from 'next/link'\nimport { apiCall, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\n\ntype RecordsResponse = {\n items: any[]\n total: number\n page: number\n pageSize: number\n totalPages: number\n}\n\nfunction toCsvUrl(base: string, params: URLSearchParams) {\n // Build a relative URL to avoid SSR/CSR origin mismatch hydration issues\n const p = new URLSearchParams(params)\n p.set('format', 'csv')\n const qs = p.toString()\n return qs ? `${base}?${qs}` : base\n}\n\nfunction normalizeCell(v: any): string {\n if (Array.isArray(v)) return v.filter((x) => x != null && x !== '').join(', ')\n if (v === true) return 'Yes'\n if (v === false) return 'No'\n if (v == null) return ''\n if (v instanceof Date) return v.toISOString()\n return String(v)\n}\n\nexport default function RecordsPage({ params }: { params: { entityId?: string } }) {\n const entityId = decodeURIComponent(params?.entityId || '')\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'id', desc: false }])\n const [page, setPage] = React.useState(1)\n const [pageSize, setPageSize] = React.useState(50)\n const [search, setSearch] = React.useState('')\n const [filterValues, setFilterValues] = React.useState<Record<string, any>>({})\n const [columns, setColumns] = React.useState<ColumnDef<any>[]>([])\n const [rawData, setRawData] = React.useState<any[]>([])\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [loading, setLoading] = React.useState(false)\n const scopeVersion = useOrganizationScopeVersion()\n const { data: cfDefs = [] } = useCustomFieldDefs(entityId, {\n enabled: Boolean(entityId),\n keyExtras: [scopeVersion],\n })\n\n // Fetch records whenever paging/sorting/filters change (do NOT refetch on cfDefs/search changes)\n React.useEffect(() => {\n let cancelled = false\n const run = async () => {\n setLoading(true)\n try {\n const params = new URLSearchParams()\n params.set('entityId', entityId)\n params.set('page', String(page))\n params.set('pageSize', String(pageSize))\n const s = sorting?.[0]\n if (s?.id) {\n params.set('sortField', String(s.id))\n params.set('sortDir', s.desc ? 'desc' : 'asc')\n }\n // Flatten filter values into query params\n for (const [k, v] of Object.entries(filterValues)) {\n if (v == null) continue\n if (Array.isArray(v)) {\n if (v.length) params.set(k, v.join(','))\n } else if (typeof v === 'object') {\n // dateRange-like shapes are not supported generically here; skip\n } else {\n params.set(k, String(v))\n }\n }\n const j = await readApiResultOrThrow<RecordsResponse>(\n `/api/entities/records?${params.toString()}`,\n undefined,\n {\n errorMessage: 'Failed to load records',\n fallback: {\n items: [],\n total: 0,\n page,\n pageSize,\n totalPages: 1,\n },\n },\n )\n if (!cancelled) {\n setRawData(j.items || [])\n setTotal(j.total)\n setTotalPages(j.totalPages)\n }\n } catch (e) {\n if (!cancelled) {\n setRawData([])\n setTotal(0)\n setTotalPages(1)\n }\n } finally {\n if (!cancelled) setLoading(false)\n }\n }\n if (entityId) run()\n return () => { cancelled = true }\n }, [entityId, page, pageSize, sorting, filterValues, scopeVersion])\n\n // Build columns from custom field definitions only (no data round-trip)\n React.useEffect(() => {\n const visibleDefs = filterCustomFieldDefs(cfDefs, 'list') as any\n const maxVisible = 10\n const cols: ColumnDef<any>[] = visibleDefs.map((d: any, idx: number) => ({\n accessorKey: d.key,\n header: d.label || d.key,\n meta: { priority: idx < 4 ? 1 : idx < 6 ? 2 : idx < 8 ? 3 : idx < maxVisible ? 4 : 5 },\n cell: ({ getValue }: { getValue: () => unknown }) => {\n const v = getValue() as any\n return <span className=\"truncate max-w-[24ch] inline-block align-top\" title={normalizeCell(v)}>{normalizeCell(v)}</span>\n },\n }))\n // Ensure hidden 'id' column exists for sorting/state\n const hasIdCol = cols.some((c) => (c as any).accessorKey === 'id' || (c as any).id === 'id')\n if (!hasIdCol) cols.unshift({ accessorKey: 'id', header: 'ID', meta: { hidden: true, priority: 6 } } as any)\n setColumns(cols)\n }, [cfDefs])\n\n // Client-side quick search filtering without triggering server refetch\n const data = React.useMemo(() => {\n if (!search.trim()) return rawData\n const q = search.trim().toLowerCase()\n return (rawData || []).filter((row: any) => {\n const values = Object.values(row || {})\n return values.some((v) => normalizeCell(v).toLowerCase().includes(q))\n })\n }, [rawData, search])\n\n const viewExportColumns = React.useMemo(() => {\n return (columns || [])\n .map((col) => {\n const accessorKey = (col as any).accessorKey\n if (!accessorKey || typeof accessorKey !== 'string') return null\n if ((col as any).meta?.hidden) return null\n const header = typeof col.header === 'string'\n ? col.header\n : accessorKey.startsWith('cf_')\n ? accessorKey.slice(3)\n : accessorKey\n return { field: accessorKey, header }\n })\n .filter((col): col is { field: string; header: string } => !!col)\n }, [columns])\n\n const buildFullExportUrl = React.useCallback((format: DataTableExportFormat) => {\n const qp = new URLSearchParams({\n entityId,\n format,\n exportScope: 'full',\n all: 'true',\n })\n const sort = sorting?.[0]\n if (sort?.id) {\n qp.set('sortField', String(sort.id))\n qp.set('sortDir', sort.desc ? 'desc' : 'asc')\n }\n return `/api/entities/records?${qp.toString()}`\n }, [entityId, sorting])\n\n const exportConfig = React.useMemo(() => {\n const safeEntityId = entityId.replace(/[^a-z0-9_-]/gi, '_') || 'records'\n return {\n view: {\n description: 'Exports the current list respecting filters and column visibility.',\n prepare: async (): Promise<{ prepared: PreparedExport; filename: string }> => {\n const rowsForExport = data.map((row) => {\n const out: Record<string, unknown> = {}\n for (const col of viewExportColumns) {\n out[col.field] = (row as Record<string, unknown>)[col.field]\n }\n return out\n })\n const prepared: PreparedExport = {\n columns: viewExportColumns.map((col) => ({ field: col.field, header: col.header })),\n rows: rowsForExport,\n }\n return { prepared, filename: `${safeEntityId}_view` }\n },\n },\n full: {\n description: 'Exports raw records with every field and custom field included.',\n getUrl: (format: DataTableExportFormat) => buildFullExportUrl(format),\n filename: () => `${safeEntityId}_full`,\n },\n }\n }, [buildFullExportUrl, data, entityId, viewExportColumns])\n\n const hasAnyFormFields = React.useMemo(() => filterCustomFieldDefs(cfDefs, 'form').length > 0, [cfDefs])\n const actions = (\n <>\n <Button asChild variant=\"outline\" size=\"sm\">\n <Link href={`/backend/entities/user/${encodeURIComponent(entityId)}`}>\n Edit Entity Definition\n </Link>\n </Button>\n {hasAnyFormFields && (\n <Button asChild>\n <Link href={`/backend/entities/user/${encodeURIComponent(entityId)}/records/create`}>\n Create\n </Link>\n </Button>\n )}\n </>\n )\n\n // Ensure filters are visible even if no custom fields are marked filterable\n const baseFilters: FilterDef[] = React.useMemo(() => ([\n { id: 'id', label: 'ID', type: 'text' },\n ]), [])\n\n return (\n <Page>\n <PageBody>\n <ContextHelp bulb title=\"API: Manage Records via cURL\" className=\"mb-4\">\n <p className=\"mb-2\">\n Interact with this custom entity via the backend API using cURL. Use API keys for machine-to-machine access\u2014mint one from the{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/user-guide/api-keys\">\n Managing API keys guide\n </a>{' '}\n or the{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/cli/api-keys\">\n API keys CLI documentation\n </a>{' '}\n before running these calls.\n </p>\n <div className=\"space-y-2\">\n <div>\n <div className=\"font-medium mb-1\">1) Configure environment variables</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`export BASE_URL=\"http://localhost:3000/api\"\nexport API_KEY=\"<paste API key secret here>\" # scoped with entities.features\nexport ENTITY_ID=\"${entityId}\"\nexport RECORD_ID=\"<record uuid>\"`}</code></pre>\n <p className=\"text-muted-foreground mt-1\">\n Need a new key? Follow the{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/user-guide/api-keys\">\n Managing API keys\n </a>{' '}\n walkthrough or mint one via{' '}\n <a className=\"underline\" target=\"_blank\" rel=\"noreferrer\" href=\"https://docs.openmercato.com/cli/api-keys\">\n mercato api_keys add\n </a>\n .\n </p>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">2) List records</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -H \"X-Api-Key: $API_KEY\" \\\n \"$BASE_URL/entities/records?entityId=$ENTITY_ID\" | jq`}</code></pre>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">3) Read a single record (by id)</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -H \"X-Api-Key: $API_KEY\" \\\n \"$BASE_URL/entities/records?entityId=$ENTITY_ID&id=$RECORD_ID\" | jq`}</code></pre>\n <p className=\"text-muted-foreground mt-1\">Note: Response is a list; filter by <code>id</code> to get a single item.</p>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">4) Create a record</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -X POST \\\n -H \"X-Api-Key: $API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d \"{\n \\\\\"entityId\\\\\": \\\\\"$ENTITY_ID\\\\\",\n \\\\\"values\\\\\": {\n \\\\\"field_one\\\\\": \\\\\"Example\\\\\",\n \\\\\"field_two\\\\\": 123\n }\n }\" \\\n \"$BASE_URL/entities/records\" | jq`}</code></pre>\n <p className=\"text-muted-foreground mt-1\">For custom entities, send field keys without the <code>cf_</code> prefix. The API normalizes this server-side.</p>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">5) Update a record</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -X PUT \\\n -H \"X-Api-Key: $API_KEY\" \\\n -H \"Content-Type: application/json\" \\\n -d \"{\n \\\\\"entityId\\\\\": \\\\\"$ENTITY_ID\\\\\",\n \\\\\"recordId\\\\\": \\\\\"$RECORD_ID\\\\\",\n \\\\\"values\\\\\": {\n \\\\\"field_one\\\\\": \\\\\"Updated\\\\\"\n }\n }\" \\\n \"$BASE_URL/entities/records\" | jq`}</code></pre>\n </div>\n\n <div>\n <div className=\"font-medium mb-1\">6) Delete a record</div>\n <pre className=\"bg-muted p-3 rounded text-xs overflow-auto\"><code>{`curl -s -X DELETE \\\n -H \"X-Api-Key: $API_KEY\" \\\n \"$BASE_URL/entities/records?entityId=$ENTITY_ID&recordId=$RECORD_ID\" | jq`}</code></pre>\n </div>\n\n <div className=\"text-muted-foreground\">\n Security notes:\n <ul className=\"list-disc pl-5 mt-1 space-y-1\">\n <li>All endpoints require a valid API key. Keys inherit tenant, organization, and feature scope.</li>\n <li>Rotate keys regularly and delete unused ones in the admin UI.</li>\n <li>Store the secret in a secure vault; anyone with the header can act within the key's permissions.</li>\n </ul>\n </div>\n </div>\n </ContextHelp>\n <DataTable\n title={`Records: ${entityId}`}\n entityId={entityId}\n actions={actions}\n columns={columns}\n data={data}\n perspective={{ tableId: `entities.user.records.${entityId}` }}\n exporter={exportConfig}\n filters={baseFilters}\n filterValues={filterValues}\n rowActions={(row) => (\n <RowActions\n items={[\n { id: 'edit', label: 'Edit', href: `/backend/entities/user/${encodeURIComponent(entityId)}/records/${encodeURIComponent(String((row as any).id))}` },\n { id: 'delete', label: 'Delete', destructive: true, onSelect: async () => {\n try {\n if (typeof window !== 'undefined') {\n const ok = window.confirm('Delete this record?')\n if (!ok) return\n }\n const deleteCall = await apiCall(\n `/api/entities/records?entityId=${encodeURIComponent(entityId)}&recordId=${encodeURIComponent(String((row as any).id))}`,\n { method: 'DELETE' },\n )\n if (!deleteCall.ok) {\n await raiseCrudError(deleteCall.response, 'Failed to delete record')\n }\n const j = await readApiResultOrThrow<RecordsResponse>(\n `/api/entities/records?entityId=${encodeURIComponent(entityId)}&page=${page}&pageSize=${pageSize}`,\n undefined,\n {\n errorMessage: 'Failed to reload records',\n fallback: { items: [], total: 0, page, pageSize, totalPages: 1 },\n },\n )\n setRawData(j.items || [])\n setTotal(j.total || 0)\n setTotalPages(j.totalPages || 1)\n flash('Record has been removed', 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Failed to delete record'\n flash(message, 'error')\n }\n } },\n ]}\n />\n )}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n searchValue={search}\n onSearchChange={(v) => { setSearch(v); setPage(1) }}\n onFiltersApply={(vals) => { setFilterValues(vals); setPage(1) }}\n onFiltersClear={() => { setFilterValues({}); setPage(1) }}\n pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}\n isLoading={loading}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["params"]
|
|
7
7
|
}
|
|
@@ -73,7 +73,7 @@ function SystemEntitiesTable() {
|
|
|
73
73
|
RowActions,
|
|
74
74
|
{
|
|
75
75
|
items: [
|
|
76
|
-
{ label: "Edit", href: `/backend/entities/system/${encodeURIComponent(row.entityId)}` }
|
|
76
|
+
{ id: "edit", label: "Edit", href: `/backend/entities/system/${encodeURIComponent(row.entityId)}` }
|
|
77
77
|
]
|
|
78
78
|
}
|
|
79
79
|
),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/entities/components/SystemEntitiesTable.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\n\ntype EntityRow = {\n entityId: string\n label: string\n source: 'code' | 'custom'\n count: number\n}\n\ntype EntitiesResponse = { items: EntityRow[] }\n\nconst columns: ColumnDef<EntityRow>[] = [\n { accessorKey: 'entityId', header: 'Entity', meta: { priority: 1 }, cell: ({ getValue }) => <span className=\"font-mono\">{String(getValue())}</span> },\n { accessorKey: 'label', header: 'Label', meta: { priority: 2 } },\n { accessorKey: 'source', header: 'Source', meta: { priority: 3 } },\n { accessorKey: 'count', header: 'Fields', meta: { priority: 4 } },\n]\n\nfunction toCsv(rows: EntityRow[]) {\n const header = ['entityId','label','source','count']\n const esc = (s: string | number) => {\n const str = String(s ?? '')\n if (/[\",\\n]/.test(str)) return '\"' + str.replace(/\"/g, '\"\"') + '\"'\n return str\n }\n const lines = [header.join(',')]\n for (const r of rows) lines.push([r.entityId, r.label, r.source, r.count].map(esc).join(','))\n return lines.join('\\n')\n}\n\nexport default function SystemEntitiesTable() {\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'entityId', desc: false }])\n const [page, setPage] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const scopeVersion = useOrganizationScopeVersion()\n\n const { data, isLoading } = useQuery<EntitiesResponse>({\n queryKey: ['custom-entities', scopeVersion],\n queryFn: async () => {\n return readApiResultOrThrow<EntitiesResponse>('/api/entities/entities', undefined, {\n errorMessage: 'Failed to load entities',\n })\n },\n })\n\n const rowsAll = data?.items || []\n // Filter to only show system entities (source: 'code')\n const systemRows = rowsAll.filter(row => row.source === 'code')\n const rows = React.useMemo(() => {\n if (!search) return systemRows\n const q = search.toLowerCase()\n return systemRows.filter(r => r.entityId.toLowerCase().includes(q) || r.label.toLowerCase().includes(q))\n }, [systemRows, search])\n\n return (\n <DataTable\n title=\"System Entities\"\n actions={(\n <>\n <Button variant=\"outline\" onClick={() => {\n const csv = toCsv(rows)\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = 'entities-system.csv'\n a.click()\n URL.revokeObjectURL(url)\n }}>Export</Button>\n </>\n )}\n columns={columns}\n data={rows}\n searchValue={search}\n onSearchChange={(v) => { setSearch(v); setPage(1) }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n perspective={{ tableId: 'entities.system.list' }}\n rowActions={(row) => (\n <RowActions\n items={[\n { label: 'Edit', href: `/backend/entities/system/${encodeURIComponent(row.entityId)}` },\n ]}\n />\n )}\n pagination={{ page, pageSize: 50, total: rows.length, totalPages: 1, onPageChange: setPage }}\n isLoading={isLoading}\n />\n )\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useQuery } from '@tanstack/react-query'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\n\ntype EntityRow = {\n entityId: string\n label: string\n source: 'code' | 'custom'\n count: number\n}\n\ntype EntitiesResponse = { items: EntityRow[] }\n\nconst columns: ColumnDef<EntityRow>[] = [\n { accessorKey: 'entityId', header: 'Entity', meta: { priority: 1 }, cell: ({ getValue }) => <span className=\"font-mono\">{String(getValue())}</span> },\n { accessorKey: 'label', header: 'Label', meta: { priority: 2 } },\n { accessorKey: 'source', header: 'Source', meta: { priority: 3 } },\n { accessorKey: 'count', header: 'Fields', meta: { priority: 4 } },\n]\n\nfunction toCsv(rows: EntityRow[]) {\n const header = ['entityId','label','source','count']\n const esc = (s: string | number) => {\n const str = String(s ?? '')\n if (/[\",\\n]/.test(str)) return '\"' + str.replace(/\"/g, '\"\"') + '\"'\n return str\n }\n const lines = [header.join(',')]\n for (const r of rows) lines.push([r.entityId, r.label, r.source, r.count].map(esc).join(','))\n return lines.join('\\n')\n}\n\nexport default function SystemEntitiesTable() {\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'entityId', desc: false }])\n const [page, setPage] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const scopeVersion = useOrganizationScopeVersion()\n\n const { data, isLoading } = useQuery<EntitiesResponse>({\n queryKey: ['custom-entities', scopeVersion],\n queryFn: async () => {\n return readApiResultOrThrow<EntitiesResponse>('/api/entities/entities', undefined, {\n errorMessage: 'Failed to load entities',\n })\n },\n })\n\n const rowsAll = data?.items || []\n // Filter to only show system entities (source: 'code')\n const systemRows = rowsAll.filter(row => row.source === 'code')\n const rows = React.useMemo(() => {\n if (!search) return systemRows\n const q = search.toLowerCase()\n return systemRows.filter(r => r.entityId.toLowerCase().includes(q) || r.label.toLowerCase().includes(q))\n }, [systemRows, search])\n\n return (\n <DataTable\n title=\"System Entities\"\n actions={(\n <>\n <Button variant=\"outline\" onClick={() => {\n const csv = toCsv(rows)\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = 'entities-system.csv'\n a.click()\n URL.revokeObjectURL(url)\n }}>Export</Button>\n </>\n )}\n columns={columns}\n data={rows}\n searchValue={search}\n onSearchChange={(v) => { setSearch(v); setPage(1) }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n perspective={{ tableId: 'entities.system.list' }}\n rowActions={(row) => (\n <RowActions\n items={[\n { id: 'edit', label: 'Edit', href: `/backend/entities/system/${encodeURIComponent(row.entityId)}` },\n ]}\n />\n )}\n pagination={{ page, pageSize: 50, total: rows.length, totalPages: 1, onPageChange: setPage }}\n isLoading={isLoading}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -86,8 +86,8 @@ function UserEntitiesTable() {
|
|
|
86
86
|
RowActions,
|
|
87
87
|
{
|
|
88
88
|
items: [
|
|
89
|
-
{ label: t("common.edit", "Edit"), href: `/backend/entities/user/${encodeURIComponent(row.entityId)}` },
|
|
90
|
-
{ label: t("entities.user.table.actions.showRecords", "Show records"), href: `/backend/entities/user/${encodeURIComponent(row.entityId)}/records` }
|
|
89
|
+
{ id: "edit", label: t("common.edit", "Edit"), href: `/backend/entities/user/${encodeURIComponent(row.entityId)}` },
|
|
90
|
+
{ id: "show-records", label: t("entities.user.table.actions.showRecords", "Show records"), href: `/backend/entities/user/${encodeURIComponent(row.entityId)}/records` }
|
|
91
91
|
]
|
|
92
92
|
}
|
|
93
93
|
),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/entities/components/UserEntitiesTable.tsx"],
|
|
4
|
-
"sourcesContent": ["\n\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useQuery } from '@tanstack/react-query'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { DataTable, RowActions, Button } from '@open-mercato/ui'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype EntityRow = {\n entityId: string\n label: string\n source: 'code' | 'custom'\n count: number\n showInSidebar?: boolean\n}\n\ntype EntitiesResponse = { items: EntityRow[] }\n\nfunction buildColumns(t: (key: string, fallback: string) => string): ColumnDef<EntityRow>[] {\n return [\n { accessorKey: 'entityId', header: t('entities.user.table.column.entity', 'Entity'), meta: { priority: 1 }, cell: ({ getValue }) => <span className=\"font-mono\">{String(getValue())}</span> },\n { accessorKey: 'label', header: t('entities.user.table.column.label', 'Label'), meta: { priority: 2 } },\n { accessorKey: 'source', header: t('entities.user.table.column.source', 'Source'), meta: { priority: 3 } },\n { accessorKey: 'count', header: t('entities.user.table.column.fields', 'Fields'), meta: { priority: 4 } },\n { \n accessorKey: 'showInSidebar', \n header: t('entities.user.table.column.inSidebar', 'In Sidebar'), \n meta: { priority: 5 },\n cell: ({ getValue }) => (\n <span className={`px-2 py-1 rounded text-xs ${\n getValue() ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400' : 'bg-muted text-muted-foreground'\n }`}>\n {getValue() ? t('common.yes', 'Yes') : t('common.no', 'No')}\n </span>\n )\n },\n ]\n}\n\nfunction toCsv(rows: EntityRow[]) {\n const header = ['entityId','label','source','count','showInSidebar']\n const esc = (s: string | number | boolean) => {\n const str = String(s ?? '')\n if (/[\",\\n]/.test(str)) return '\"' + str.replace(/\"/g, '\"\"') + '\"'\n return str\n }\n const lines = [header.join(',')]\n for (const r of rows) lines.push([r.entityId, r.label, r.source, r.count, r.showInSidebar || false].map(esc).join(','))\n return lines.join('\\n')\n}\n\nexport default function UserEntitiesTable() {\n const t = useT()\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'entityId', desc: false }])\n const [page, setPage] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const scopeVersion = useOrganizationScopeVersion()\n \n const columns = React.useMemo(() => buildColumns(t), [t])\n\n const { data, isLoading } = useQuery<EntitiesResponse>({\n queryKey: ['custom-entities', scopeVersion],\n queryFn: async () => {\n return readApiResultOrThrow<EntitiesResponse>('/api/entities/entities', undefined, {\n errorMessage: 'Failed to load entities',\n })\n },\n })\n\n const rowsAll = data?.items || []\n // Filter to only show user entities (source: 'custom')\n const userRows = rowsAll.filter(row => row.source === 'custom')\n const rows = React.useMemo(() => {\n if (!search) return userRows\n const q = search.toLowerCase()\n return userRows.filter(r => r.entityId.toLowerCase().includes(q) || r.label.toLowerCase().includes(q))\n }, [userRows, search])\n\n return (\n <DataTable\n title={t('entities.user.table.title', 'User Entities')}\n actions={(\n <>\n <Button variant=\"outline\" onClick={() => {\n const csv = toCsv(rows)\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = 'entities-user.csv'\n a.click()\n URL.revokeObjectURL(url)\n }}>{t('common.export', 'Export')}</Button>\n <Button asChild>\n <Link href=\"/backend/entities/user/create\">{t('common.create', 'Create')}</Link>\n </Button>\n </>\n )}\n columns={columns}\n data={rows}\n searchValue={search}\n onSearchChange={(v) => { setSearch(v); setPage(1) }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n perspective={{ tableId: 'entities.user.list' }}\n rowActions={(row) => (\n <RowActions\n items={[\n { label: t('common.edit', 'Edit'), href: `/backend/entities/user/${encodeURIComponent(row.entityId)}` },\n { label: t('entities.user.table.actions.showRecords', 'Show records'), href: `/backend/entities/user/${encodeURIComponent(row.entityId)}/records` },\n ]}\n />\n )}\n pagination={{ page, pageSize: 50, total: rows.length, totalPages: 1, onPageChange: setPage }}\n isLoading={isLoading}\n />\n )\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["\n\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { useQuery } from '@tanstack/react-query'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { DataTable, RowActions, Button } from '@open-mercato/ui'\nimport { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype EntityRow = {\n entityId: string\n label: string\n source: 'code' | 'custom'\n count: number\n showInSidebar?: boolean\n}\n\ntype EntitiesResponse = { items: EntityRow[] }\n\nfunction buildColumns(t: (key: string, fallback: string) => string): ColumnDef<EntityRow>[] {\n return [\n { accessorKey: 'entityId', header: t('entities.user.table.column.entity', 'Entity'), meta: { priority: 1 }, cell: ({ getValue }) => <span className=\"font-mono\">{String(getValue())}</span> },\n { accessorKey: 'label', header: t('entities.user.table.column.label', 'Label'), meta: { priority: 2 } },\n { accessorKey: 'source', header: t('entities.user.table.column.source', 'Source'), meta: { priority: 3 } },\n { accessorKey: 'count', header: t('entities.user.table.column.fields', 'Fields'), meta: { priority: 4 } },\n { \n accessorKey: 'showInSidebar', \n header: t('entities.user.table.column.inSidebar', 'In Sidebar'), \n meta: { priority: 5 },\n cell: ({ getValue }) => (\n <span className={`px-2 py-1 rounded text-xs ${\n getValue() ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400' : 'bg-muted text-muted-foreground'\n }`}>\n {getValue() ? t('common.yes', 'Yes') : t('common.no', 'No')}\n </span>\n )\n },\n ]\n}\n\nfunction toCsv(rows: EntityRow[]) {\n const header = ['entityId','label','source','count','showInSidebar']\n const esc = (s: string | number | boolean) => {\n const str = String(s ?? '')\n if (/[\",\\n]/.test(str)) return '\"' + str.replace(/\"/g, '\"\"') + '\"'\n return str\n }\n const lines = [header.join(',')]\n for (const r of rows) lines.push([r.entityId, r.label, r.source, r.count, r.showInSidebar || false].map(esc).join(','))\n return lines.join('\\n')\n}\n\nexport default function UserEntitiesTable() {\n const t = useT()\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'entityId', desc: false }])\n const [page, setPage] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const scopeVersion = useOrganizationScopeVersion()\n \n const columns = React.useMemo(() => buildColumns(t), [t])\n\n const { data, isLoading } = useQuery<EntitiesResponse>({\n queryKey: ['custom-entities', scopeVersion],\n queryFn: async () => {\n return readApiResultOrThrow<EntitiesResponse>('/api/entities/entities', undefined, {\n errorMessage: 'Failed to load entities',\n })\n },\n })\n\n const rowsAll = data?.items || []\n // Filter to only show user entities (source: 'custom')\n const userRows = rowsAll.filter(row => row.source === 'custom')\n const rows = React.useMemo(() => {\n if (!search) return userRows\n const q = search.toLowerCase()\n return userRows.filter(r => r.entityId.toLowerCase().includes(q) || r.label.toLowerCase().includes(q))\n }, [userRows, search])\n\n return (\n <DataTable\n title={t('entities.user.table.title', 'User Entities')}\n actions={(\n <>\n <Button variant=\"outline\" onClick={() => {\n const csv = toCsv(rows)\n const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = 'entities-user.csv'\n a.click()\n URL.revokeObjectURL(url)\n }}>{t('common.export', 'Export')}</Button>\n <Button asChild>\n <Link href=\"/backend/entities/user/create\">{t('common.create', 'Create')}</Link>\n </Button>\n </>\n )}\n columns={columns}\n data={rows}\n searchValue={search}\n onSearchChange={(v) => { setSearch(v); setPage(1) }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n perspective={{ tableId: 'entities.user.list' }}\n rowActions={(row) => (\n <RowActions\n items={[\n { id: 'edit', label: t('common.edit', 'Edit'), href: `/backend/entities/user/${encodeURIComponent(row.entityId)}` },\n { id: 'show-records', label: t('entities.user.table.actions.showRecords', 'Show records'), href: `/backend/entities/user/${encodeURIComponent(row.entityId)}/records` },\n ]}\n />\n )}\n pagination={{ page, pageSize: 50, total: rows.length, totalPages: 1, onPageChange: setPage }}\n isLoading={isLoading}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -163,9 +163,9 @@ function FeatureTogglesTable() {
|
|
|
163
163
|
onPageChange: handlePageChange
|
|
164
164
|
},
|
|
165
165
|
rowActions: (row) => /* @__PURE__ */ jsx(RowActions, { items: [
|
|
166
|
-
{ label: t("common.edit", "Edit"), href: `/backend/feature-toggles/global/${row.id}/edit` },
|
|
167
|
-
{ label: t("common.view", "Overrides"), href: `/backend/feature-toggles/global/${row.id}` },
|
|
168
|
-
{ label: t("common.delete", "Delete"), destructive: true, onSelect: () => {
|
|
166
|
+
{ id: "edit", label: t("common.edit", "Edit"), href: `/backend/feature-toggles/global/${row.id}/edit` },
|
|
167
|
+
{ id: "view", label: t("common.view", "Overrides"), href: `/backend/feature-toggles/global/${row.id}` },
|
|
168
|
+
{ id: "delete", label: t("common.delete", "Delete"), destructive: true, onSelect: () => {
|
|
169
169
|
void handleDelete(row);
|
|
170
170
|
} }
|
|
171
171
|
] })
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/feature_toggles/components/FeatureTogglesTable.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport { DataTable } from \"@open-mercato/ui/backend/DataTable\";\nimport { RowActions } from \"@open-mercato/ui/backend/RowActions\";\nimport { useT } from \"@open-mercato/shared/lib/i18n/context\";\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport * as React from 'react'\nimport type { FilterDef, FilterValues } from \"@open-mercato/ui/backend/FilterBar\"\nimport { useMutation } from '@tanstack/react-query'\nimport { deleteCrud, updateCrud } from \"@open-mercato/ui/backend/utils/crud\";\nimport { Button } from \"@open-mercato/ui/primitives/button\";\nimport { Badge } from \"@open-mercato/ui/primitives/badge\";\nimport Link from \"next/link\";\nimport { FeatureToggleType } from \"../data/entities\";\n\ntype Row = {\n id: string\n identifier: string\n name: string\n description: string\n category?: string\n type: FeatureToggleType\n}\n\ntype BadgeVariant = 'default' | 'secondary' | 'destructive' | 'outline' | 'muted'\n\nexport function FeatureTogglesTable() {\n const t = useT()\n const queryClient = useQueryClient()\n\n const featureToggleTypeLabelMap = React.useMemo(() => new Map<FeatureToggleType, { label: string; variant: BadgeVariant }>([\n ['boolean', { label: t('feature_toggles.types.boolean', 'Boolean'), variant: 'default' }],\n ['string', { label: t('feature_toggles.types.string', 'String'), variant: 'secondary' }],\n ['number', { label: t('feature_toggles.types.number', 'Number'), variant: 'outline' }],\n ['json', { label: t('feature_toggles.types.json', 'JSON'), variant: 'destructive' }],\n ]), [t])\n\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [sorting, setSorting] = React.useState<SortingState>([])\n const [pagination, setPagination] = React.useState({ page: 1, pageSize: 25 })\n\n const categoryFilterValue = typeof filterValues.category === 'string' ? filterValues.category.trim() : ''\n const nameFilterValue = typeof filterValues.name === 'string' ? filterValues.name.trim() : ''\n const identifierFilterValue = typeof filterValues.identifier === 'string' ? filterValues.identifier.trim() : ''\n const typeFilterValue = typeof filterValues.type === 'string' ? filterValues.type.trim() : ''\n const sortField = sorting.length > 0 ? sorting[0].id : 'category'\n const sortDir = sorting.length > 0 && sorting[0].desc ? 'desc' : 'asc'\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n if (categoryFilterValue) params.set('category', categoryFilterValue)\n if (nameFilterValue) params.set('name', nameFilterValue)\n if (identifierFilterValue) params.set('identifier', identifierFilterValue)\n if (typeFilterValue) params.set('type', typeFilterValue)\n\n params.set('sortField', sortField)\n params.set('sortDir', sortDir)\n\n params.set('page', pagination.page.toString())\n params.set('pageSize', pagination.pageSize.toString())\n\n return params.toString()\n }, [categoryFilterValue, identifierFilterValue, nameFilterValue, sortField, sortDir, typeFilterValue, pagination])\n\n const handleSortingChange = React.useCallback((newSorting: SortingState) => {\n setSorting(newSorting)\n }, [])\n\n const handlePageChange = React.useCallback((page: number) => {\n setPagination(prev => ({ ...prev, page }))\n }, [])\n\n const { data: featureTogglesData, isLoading } = useQuery({\n queryKey: ['feature_toggles', queryParams],\n queryFn: async () => {\n const call = await apiCall<{ items: Row[]; total: number; totalPages: number; page: number; pageSize: number; isSuperAdmin?: boolean }>(\n `/api/feature_toggles/global${queryParams ? `?${queryParams}` : ''}`,\n )\n if (!call.ok) {\n await raiseCrudError(call.response, t('feature_toggles.list.error.load', 'Failed to load feature toggles'))\n }\n return call.result ?? { items: [], total: 0, totalPages: 1, page: 1, pageSize: 25 }\n },\n })\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'identifier',\n label: t('feature_toggles.list.filters.identifier', 'Identifier'),\n type: 'text',\n },\n {\n id: 'name',\n label: t('feature_toggles.list.filters.name', 'Name'),\n type: 'text',\n },\n {\n id: 'category',\n label: t('feature_toggles.list.filters.category', 'Category'),\n type: 'text',\n },\n {\n id: 'type',\n label: t('feature_toggles.list.filters.type', 'Type'),\n type: 'select',\n options: [\n { label: t('feature_toggles.types.boolean', 'Boolean'), value: 'boolean' },\n { label: t('feature_toggles.types.string', 'String'), value: 'string' },\n { label: t('feature_toggles.types.number', 'Number'), value: 'number' },\n { label: t('feature_toggles.types.json', 'JSON'), value: 'json' },\n ],\n },\n ], [t])\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n setFilterValues(values)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n }, [])\n\n const deleteFeatureToggleMutation = useMutation({\n mutationFn: async (row: Row) => {\n await deleteCrud('feature_toggles/global', row.id)\n },\n onSuccess: async () => {\n await queryClient.invalidateQueries({ queryKey: ['feature_toggles'] })\n },\n })\n\n const handleDelete = React.useCallback(async (row: Row) => {\n if (!window.confirm(t('feature_toggles.list.confirmDelete', 'Delete feature toggle \"{identifier}\"?', { identifier: row.identifier }))) return\n await deleteFeatureToggleMutation.mutateAsync(row)\n }, [deleteFeatureToggleMutation, t])\n\n const columns = React.useMemo<ColumnDef<Row>[]>(() => {\n const base: ColumnDef<Row>[] = [\n {\n accessorKey: 'category',\n header: t('feature_toggles.list.headers.category', 'Category'),\n enableSorting: true,\n cell: ({ row }) => {\n return row.original.category || '-'\n },\n },\n {\n accessorKey: 'identifier',\n header: t('feature_toggles.list.headers.identifier', 'Identifier'),\n enableSorting: true\n },\n {\n accessorKey: 'name',\n header: t('feature_toggles.list.headers.name', 'Name'),\n enableSorting: true\n },\n {\n accessorKey: 'type',\n header: t('feature_toggles.list.headers.type', 'Type'),\n enableSorting: true,\n cell: ({ row }) => {\n const typeInfo = featureToggleTypeLabelMap.get(row.original.type)\n if (!typeInfo) return '-'\n\n return (\n <Badge variant={typeInfo.variant}>\n {typeInfo.label}\n </Badge>\n )\n },\n },\n ]\n return base\n }, [t, featureToggleTypeLabelMap])\n\n return (\n <DataTable\n title={t('feature_toggles.global.help.title', 'Feature Toggles')}\n disableRowClick\n actions={\n <Button asChild>\n <Link href=\"/backend/feature-toggles/global/create\">\n {t('common.create', 'Create')}\n </Link>\n </Button>\n }\n columns={columns}\n data={featureTogglesData?.items ?? []}\n isLoading={isLoading}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n sorting={sorting}\n onSortingChange={handleSortingChange}\n sortable={true}\n pagination={{\n page: featureTogglesData?.page ?? 1,\n pageSize: featureTogglesData?.pageSize ?? 25,\n total: featureTogglesData?.total ?? 0,\n totalPages: featureTogglesData?.totalPages ?? 1,\n onPageChange: handlePageChange,\n }}\n rowActions={(row) => (\n <RowActions items={[\n { label: t('common.edit', 'Edit'), href: `/backend/feature-toggles/global/${row.id}/edit` },\n { label: t('common.view', 'Overrides'), href: `/backend/feature-toggles/global/${row.id}` },\n { label: t('common.delete', 'Delete'), destructive: true, onSelect: () => { void handleDelete(row) } },\n ]} />\n )}\n />\n )\n}\n
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport { DataTable } from \"@open-mercato/ui/backend/DataTable\";\nimport { RowActions } from \"@open-mercato/ui/backend/RowActions\";\nimport { useT } from \"@open-mercato/shared/lib/i18n/context\";\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { raiseCrudError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport * as React from 'react'\nimport type { FilterDef, FilterValues } from \"@open-mercato/ui/backend/FilterBar\"\nimport { useMutation } from '@tanstack/react-query'\nimport { deleteCrud, updateCrud } from \"@open-mercato/ui/backend/utils/crud\";\nimport { Button } from \"@open-mercato/ui/primitives/button\";\nimport { Badge } from \"@open-mercato/ui/primitives/badge\";\nimport Link from \"next/link\";\nimport { FeatureToggleType } from \"../data/entities\";\n\ntype Row = {\n id: string\n identifier: string\n name: string\n description: string\n category?: string\n type: FeatureToggleType\n}\n\ntype BadgeVariant = 'default' | 'secondary' | 'destructive' | 'outline' | 'muted'\n\nexport function FeatureTogglesTable() {\n const t = useT()\n const queryClient = useQueryClient()\n\n const featureToggleTypeLabelMap = React.useMemo(() => new Map<FeatureToggleType, { label: string; variant: BadgeVariant }>([\n ['boolean', { label: t('feature_toggles.types.boolean', 'Boolean'), variant: 'default' }],\n ['string', { label: t('feature_toggles.types.string', 'String'), variant: 'secondary' }],\n ['number', { label: t('feature_toggles.types.number', 'Number'), variant: 'outline' }],\n ['json', { label: t('feature_toggles.types.json', 'JSON'), variant: 'destructive' }],\n ]), [t])\n\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [sorting, setSorting] = React.useState<SortingState>([])\n const [pagination, setPagination] = React.useState({ page: 1, pageSize: 25 })\n\n const categoryFilterValue = typeof filterValues.category === 'string' ? filterValues.category.trim() : ''\n const nameFilterValue = typeof filterValues.name === 'string' ? filterValues.name.trim() : ''\n const identifierFilterValue = typeof filterValues.identifier === 'string' ? filterValues.identifier.trim() : ''\n const typeFilterValue = typeof filterValues.type === 'string' ? filterValues.type.trim() : ''\n const sortField = sorting.length > 0 ? sorting[0].id : 'category'\n const sortDir = sorting.length > 0 && sorting[0].desc ? 'desc' : 'asc'\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n if (categoryFilterValue) params.set('category', categoryFilterValue)\n if (nameFilterValue) params.set('name', nameFilterValue)\n if (identifierFilterValue) params.set('identifier', identifierFilterValue)\n if (typeFilterValue) params.set('type', typeFilterValue)\n\n params.set('sortField', sortField)\n params.set('sortDir', sortDir)\n\n params.set('page', pagination.page.toString())\n params.set('pageSize', pagination.pageSize.toString())\n\n return params.toString()\n }, [categoryFilterValue, identifierFilterValue, nameFilterValue, sortField, sortDir, typeFilterValue, pagination])\n\n const handleSortingChange = React.useCallback((newSorting: SortingState) => {\n setSorting(newSorting)\n }, [])\n\n const handlePageChange = React.useCallback((page: number) => {\n setPagination(prev => ({ ...prev, page }))\n }, [])\n\n const { data: featureTogglesData, isLoading } = useQuery({\n queryKey: ['feature_toggles', queryParams],\n queryFn: async () => {\n const call = await apiCall<{ items: Row[]; total: number; totalPages: number; page: number; pageSize: number; isSuperAdmin?: boolean }>(\n `/api/feature_toggles/global${queryParams ? `?${queryParams}` : ''}`,\n )\n if (!call.ok) {\n await raiseCrudError(call.response, t('feature_toggles.list.error.load', 'Failed to load feature toggles'))\n }\n return call.result ?? { items: [], total: 0, totalPages: 1, page: 1, pageSize: 25 }\n },\n })\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'identifier',\n label: t('feature_toggles.list.filters.identifier', 'Identifier'),\n type: 'text',\n },\n {\n id: 'name',\n label: t('feature_toggles.list.filters.name', 'Name'),\n type: 'text',\n },\n {\n id: 'category',\n label: t('feature_toggles.list.filters.category', 'Category'),\n type: 'text',\n },\n {\n id: 'type',\n label: t('feature_toggles.list.filters.type', 'Type'),\n type: 'select',\n options: [\n { label: t('feature_toggles.types.boolean', 'Boolean'), value: 'boolean' },\n { label: t('feature_toggles.types.string', 'String'), value: 'string' },\n { label: t('feature_toggles.types.number', 'Number'), value: 'number' },\n { label: t('feature_toggles.types.json', 'JSON'), value: 'json' },\n ],\n },\n ], [t])\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n setFilterValues(values)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n }, [])\n\n const deleteFeatureToggleMutation = useMutation({\n mutationFn: async (row: Row) => {\n await deleteCrud('feature_toggles/global', row.id)\n },\n onSuccess: async () => {\n await queryClient.invalidateQueries({ queryKey: ['feature_toggles'] })\n },\n })\n\n const handleDelete = React.useCallback(async (row: Row) => {\n if (!window.confirm(t('feature_toggles.list.confirmDelete', 'Delete feature toggle \"{identifier}\"?', { identifier: row.identifier }))) return\n await deleteFeatureToggleMutation.mutateAsync(row)\n }, [deleteFeatureToggleMutation, t])\n\n const columns = React.useMemo<ColumnDef<Row>[]>(() => {\n const base: ColumnDef<Row>[] = [\n {\n accessorKey: 'category',\n header: t('feature_toggles.list.headers.category', 'Category'),\n enableSorting: true,\n cell: ({ row }) => {\n return row.original.category || '-'\n },\n },\n {\n accessorKey: 'identifier',\n header: t('feature_toggles.list.headers.identifier', 'Identifier'),\n enableSorting: true\n },\n {\n accessorKey: 'name',\n header: t('feature_toggles.list.headers.name', 'Name'),\n enableSorting: true\n },\n {\n accessorKey: 'type',\n header: t('feature_toggles.list.headers.type', 'Type'),\n enableSorting: true,\n cell: ({ row }) => {\n const typeInfo = featureToggleTypeLabelMap.get(row.original.type)\n if (!typeInfo) return '-'\n\n return (\n <Badge variant={typeInfo.variant}>\n {typeInfo.label}\n </Badge>\n )\n },\n },\n ]\n return base\n }, [t, featureToggleTypeLabelMap])\n\n return (\n <DataTable\n title={t('feature_toggles.global.help.title', 'Feature Toggles')}\n disableRowClick\n actions={\n <Button asChild>\n <Link href=\"/backend/feature-toggles/global/create\">\n {t('common.create', 'Create')}\n </Link>\n </Button>\n }\n columns={columns}\n data={featureTogglesData?.items ?? []}\n isLoading={isLoading}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n sorting={sorting}\n onSortingChange={handleSortingChange}\n sortable={true}\n pagination={{\n page: featureTogglesData?.page ?? 1,\n pageSize: featureTogglesData?.pageSize ?? 25,\n total: featureTogglesData?.total ?? 0,\n totalPages: featureTogglesData?.totalPages ?? 1,\n onPageChange: handlePageChange,\n }}\n rowActions={(row) => (\n <RowActions items={[\n { id: 'edit', label: t('common.edit', 'Edit'), href: `/backend/feature-toggles/global/${row.id}/edit` },\n { id: 'view', label: t('common.view', 'Overrides'), href: `/backend/feature-toggles/global/${row.id}` },\n { id: 'delete', label: t('common.delete', 'Delete'), destructive: true, onSelect: () => { void handleDelete(row) } },\n ]} />\n )}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -134,7 +134,7 @@ function OverridesTable() {
|
|
|
134
134
|
isRefreshing: isLoading
|
|
135
135
|
},
|
|
136
136
|
rowActions: (row) => /* @__PURE__ */ jsx(RowActions, { items: [
|
|
137
|
-
{ label: t("common.edit", "Edit"), href: `/backend/feature-toggles/global/${row.toggleId}` }
|
|
137
|
+
{ id: "edit", label: t("common.edit", "Edit"), href: `/backend/feature-toggles/global/${row.toggleId}` }
|
|
138
138
|
] }),
|
|
139
139
|
error: error ? error.message : void 0
|
|
140
140
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/feature_toggles/components/OverridesTable.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport { DataTable } from \"@open-mercato/ui/backend/DataTable\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { apiCall } from \"@open-mercato/ui/backend/utils/apiCall\";\nimport { raiseCrudError } from \"@open-mercato/ui/backend/utils/serverErrors\";\nimport { useT } from \"@open-mercato/shared/lib/i18n/context\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { ColumnDef, SortingState } from \"@tanstack/react-table\";\nimport * as React from 'react'\nimport type { FilterDef, FilterValues } from \"@open-mercato/ui/backend/FilterBar\"\nimport { RowActions } from \"@open-mercato/ui/backend/RowActions\";\nimport { OverrideListResponse } from \"../data/validators\";\n\n\nexport default function OverridesTable() {\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [sorting, setSorting] = React.useState<SortingState>([])\n const [pagination, setPagination] = React.useState({ page: 1, pageSize: 25 })\n\n const t = useT()\n const queryClient = useQueryClient()\n\n const sortField = sorting.length > 0 ? sorting[0].id : undefined\n const sortDir = sorting.length > 0 && sorting[0].desc ? 'desc' : 'asc'\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n Object.entries(filterValues).forEach(([key, value]) => {\n params.set(key, value as string)\n })\n if (sortField) params.set('sortField', sortField)\n if (sorting.length > 0) params.set('sortDir', sortDir)\n\n params.set('page', pagination.page.toString())\n params.set('pageSize', pagination.pageSize.toString())\n\n return params.toString()\n }, [filterValues, sortField, sortDir, pagination])\n\n const { data: featureTogglesData, isLoading, error } = useQuery({\n queryKey: ['feature_toggle_overrides', queryParams],\n queryFn: async () => {\n const call = await apiCall<{\n items: OverrideListResponse[];\n total: number;\n totalPages: number;\n page: number;\n pageSize: number;\n isSuperAdmin?: boolean\n }>(`/api/feature_toggles/overrides?${queryParams}`)\n if (!call.ok) {\n await raiseCrudError(call.response, t('feature_toggles.list.error.load', 'Failed to load feature toggles'))\n }\n return call.result ?? {\n items: [],\n total: 0,\n totalPages: 1,\n page: 1,\n pageSize: 25\n }\n },\n })\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n setFilterValues(values)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n }, [])\n\n const handleSortingChange = React.useCallback((newSorting: SortingState) => {\n setSorting(newSorting)\n }, [])\n\n const handlePageChange = React.useCallback((page: number) => {\n setPagination(prev => ({ ...prev, page }))\n }, [])\n\n const handleRefresh = React.useCallback(() => {\n void queryClient.refetchQueries({ queryKey: ['feature_toggle_overrides'] })\n }, [queryClient])\n\n const columns = React.useMemo<ColumnDef<OverrideListResponse>[]>(() => {\n return [\n {\n accessorKey: 'tenantName',\n header: t('feature_toggles.overrides.headers.tenant', 'Tenant'),\n enableSorting: true\n },\n {\n accessorKey: 'identifier',\n header: t('feature_toggles.overrides.headers.identifier', 'Identifier'),\n enableSorting: true\n },\n {\n accessorKey: 'name',\n header: t('feature_toggles.overrides.headers.name', 'Name'),\n enableSorting: true\n },\n {\n accessorKey: 'category',\n header: t('feature_toggles.overrides.headers.category', 'Category'),\n enableSorting: true\n },\n {\n accessorKey: 'isOverride',\n header: t('feature_toggles.overrides.headers.overrideState', 'Override'),\n enableSorting: false,\n cell: ({ row }) => {\n return row.original.isOverride ? t('feature_toggles.overrides.headers.isOverride.true', 'Yes') : t('feature_toggles.overrides.headers.isOverride.false', 'No')\n },\n },\n ]\n }, [])\n\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'identifier',\n label: t('feature_toggles.list.filters.identifier', 'Identifier'),\n type: 'text',\n },\n {\n id: 'name',\n label: t('feature_toggles.list.filters.name', 'Name'),\n type: 'text',\n },\n {\n id: 'category',\n label: t('feature_toggles.list.filters.category', 'Category'),\n type: 'text',\n }\n ], [t])\n\n return (\n <DataTable\n title={t('feature_toggles.overrides.help.title', 'Feature Toggle Overrides')}\n columns={columns}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n data={featureTogglesData?.items ?? []}\n isLoading={isLoading}\n sorting={sorting}\n onSortingChange={handleSortingChange}\n sortable={true}\n pagination={{\n page: featureTogglesData?.page ?? 1,\n pageSize: featureTogglesData?.pageSize ?? 25,\n total: featureTogglesData?.total ?? 0,\n totalPages: featureTogglesData?.totalPages ?? 1,\n onPageChange: handlePageChange,\n }}\n refreshButton={{\n label: t('feature_toggles.list.table.refresh', 'Refresh'),\n onRefresh: handleRefresh,\n isRefreshing: isLoading,\n }}\n rowActions={(row) => (\n <RowActions items={[\n { label: t('common.edit', 'Edit'), href: `/backend/feature-toggles/global/${row.toggleId}` },\n ]} />\n )}\n error={error ? error.message : undefined}\n />\n )\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport { DataTable } from \"@open-mercato/ui/backend/DataTable\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { apiCall } from \"@open-mercato/ui/backend/utils/apiCall\";\nimport { raiseCrudError } from \"@open-mercato/ui/backend/utils/serverErrors\";\nimport { useT } from \"@open-mercato/shared/lib/i18n/context\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { ColumnDef, SortingState } from \"@tanstack/react-table\";\nimport * as React from 'react'\nimport type { FilterDef, FilterValues } from \"@open-mercato/ui/backend/FilterBar\"\nimport { RowActions } from \"@open-mercato/ui/backend/RowActions\";\nimport { OverrideListResponse } from \"../data/validators\";\n\n\nexport default function OverridesTable() {\n const [filterValues, setFilterValues] = React.useState<FilterValues>({})\n const [sorting, setSorting] = React.useState<SortingState>([])\n const [pagination, setPagination] = React.useState({ page: 1, pageSize: 25 })\n\n const t = useT()\n const queryClient = useQueryClient()\n\n const sortField = sorting.length > 0 ? sorting[0].id : undefined\n const sortDir = sorting.length > 0 && sorting[0].desc ? 'desc' : 'asc'\n\n const queryParams = React.useMemo(() => {\n const params = new URLSearchParams()\n Object.entries(filterValues).forEach(([key, value]) => {\n params.set(key, value as string)\n })\n if (sortField) params.set('sortField', sortField)\n if (sorting.length > 0) params.set('sortDir', sortDir)\n\n params.set('page', pagination.page.toString())\n params.set('pageSize', pagination.pageSize.toString())\n\n return params.toString()\n }, [filterValues, sortField, sortDir, pagination])\n\n const { data: featureTogglesData, isLoading, error } = useQuery({\n queryKey: ['feature_toggle_overrides', queryParams],\n queryFn: async () => {\n const call = await apiCall<{\n items: OverrideListResponse[];\n total: number;\n totalPages: number;\n page: number;\n pageSize: number;\n isSuperAdmin?: boolean\n }>(`/api/feature_toggles/overrides?${queryParams}`)\n if (!call.ok) {\n await raiseCrudError(call.response, t('feature_toggles.list.error.load', 'Failed to load feature toggles'))\n }\n return call.result ?? {\n items: [],\n total: 0,\n totalPages: 1,\n page: 1,\n pageSize: 25\n }\n },\n })\n\n const handleFiltersApply = React.useCallback((values: FilterValues) => {\n setFilterValues(values)\n }, [])\n\n const handleFiltersClear = React.useCallback(() => {\n setFilterValues({})\n }, [])\n\n const handleSortingChange = React.useCallback((newSorting: SortingState) => {\n setSorting(newSorting)\n }, [])\n\n const handlePageChange = React.useCallback((page: number) => {\n setPagination(prev => ({ ...prev, page }))\n }, [])\n\n const handleRefresh = React.useCallback(() => {\n void queryClient.refetchQueries({ queryKey: ['feature_toggle_overrides'] })\n }, [queryClient])\n\n const columns = React.useMemo<ColumnDef<OverrideListResponse>[]>(() => {\n return [\n {\n accessorKey: 'tenantName',\n header: t('feature_toggles.overrides.headers.tenant', 'Tenant'),\n enableSorting: true\n },\n {\n accessorKey: 'identifier',\n header: t('feature_toggles.overrides.headers.identifier', 'Identifier'),\n enableSorting: true\n },\n {\n accessorKey: 'name',\n header: t('feature_toggles.overrides.headers.name', 'Name'),\n enableSorting: true\n },\n {\n accessorKey: 'category',\n header: t('feature_toggles.overrides.headers.category', 'Category'),\n enableSorting: true\n },\n {\n accessorKey: 'isOverride',\n header: t('feature_toggles.overrides.headers.overrideState', 'Override'),\n enableSorting: false,\n cell: ({ row }) => {\n return row.original.isOverride ? t('feature_toggles.overrides.headers.isOverride.true', 'Yes') : t('feature_toggles.overrides.headers.isOverride.false', 'No')\n },\n },\n ]\n }, [])\n\n\n const filters = React.useMemo<FilterDef[]>(() => [\n {\n id: 'identifier',\n label: t('feature_toggles.list.filters.identifier', 'Identifier'),\n type: 'text',\n },\n {\n id: 'name',\n label: t('feature_toggles.list.filters.name', 'Name'),\n type: 'text',\n },\n {\n id: 'category',\n label: t('feature_toggles.list.filters.category', 'Category'),\n type: 'text',\n }\n ], [t])\n\n return (\n <DataTable\n title={t('feature_toggles.overrides.help.title', 'Feature Toggle Overrides')}\n columns={columns}\n filters={filters}\n filterValues={filterValues}\n onFiltersApply={handleFiltersApply}\n onFiltersClear={handleFiltersClear}\n data={featureTogglesData?.items ?? []}\n isLoading={isLoading}\n sorting={sorting}\n onSortingChange={handleSortingChange}\n sortable={true}\n pagination={{\n page: featureTogglesData?.page ?? 1,\n pageSize: featureTogglesData?.pageSize ?? 25,\n total: featureTogglesData?.total ?? 0,\n totalPages: featureTogglesData?.totalPages ?? 1,\n onPageChange: handlePageChange,\n }}\n refreshButton={{\n label: t('feature_toggles.list.table.refresh', 'Refresh'),\n onRefresh: handleRefresh,\n isRefreshing: isLoading,\n }}\n rowActions={(row) => (\n <RowActions items={[\n { id: 'edit', label: t('common.edit', 'Edit'), href: `/backend/feature-toggles/global/${row.toggleId}` },\n ]} />\n )}\n error={error ? error.message : undefined}\n />\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAkKgB;AAhKhB,SAAS,iBAAiB;AAC1B,SAAS,gBAAgB;AACzB,SAAS,eAAe;AACxB,SAAS,sBAAsB;AAC/B,SAAS,YAAY;AACrB,SAAS,sBAAsB;AAE/B,YAAY,WAAW;AAEvB,SAAS,kBAAkB;AAIZ,SAAR,iBAAkC;AACrC,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAAuB,CAAC,CAAC;AACvE,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAuB,CAAC,CAAC;AAC7D,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,CAAC;AAE5E,QAAM,IAAI,KAAK;AACf,QAAM,cAAc,eAAe;AAEnC,QAAM,YAAY,QAAQ,SAAS,IAAI,QAAQ,CAAC,EAAE,KAAK;AACvD,QAAM,UAAU,QAAQ,SAAS,KAAK,QAAQ,CAAC,EAAE,OAAO,SAAS;AAEjE,QAAM,cAAc,MAAM,QAAQ,MAAM;AACpC,UAAM,SAAS,IAAI,gBAAgB;AACnC,WAAO,QAAQ,YAAY,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACnD,aAAO,IAAI,KAAK,KAAe;AAAA,IACnC,CAAC;AACD,QAAI,UAAW,QAAO,IAAI,aAAa,SAAS;AAChD,QAAI,QAAQ,SAAS,EAAG,QAAO,IAAI,WAAW,OAAO;AAErD,WAAO,IAAI,QAAQ,WAAW,KAAK,SAAS,CAAC;AAC7C,WAAO,IAAI,YAAY,WAAW,SAAS,SAAS,CAAC;AAErD,WAAO,OAAO,SAAS;AAAA,EAC3B,GAAG,CAAC,cAAc,WAAW,SAAS,UAAU,CAAC;AAEjD,QAAM,EAAE,MAAM,oBAAoB,WAAW,MAAM,IAAI,SAAS;AAAA,IAC5D,UAAU,CAAC,4BAA4B,WAAW;AAAA,IAClD,SAAS,YAAY;AACjB,YAAM,OAAO,MAAM,QAOhB,kCAAkC,WAAW,EAAE;AAClD,UAAI,CAAC,KAAK,IAAI;AACV,cAAM,eAAe,KAAK,UAAU,EAAE,mCAAmC,gCAAgC,CAAC;AAAA,MAC9G;AACA,aAAO,KAAK,UAAU;AAAA,QAClB,OAAO,CAAC;AAAA,QACR,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,MAAM;AAAA,QACN,UAAU;AAAA,MACd;AAAA,IACJ;AAAA,EACJ,CAAC;AAED,QAAM,qBAAqB,MAAM,YAAY,CAAC,WAAyB;AACnE,oBAAgB,MAAM;AAAA,EAC1B,GAAG,CAAC,CAAC;AAEL,QAAM,qBAAqB,MAAM,YAAY,MAAM;AAC/C,oBAAgB,CAAC,CAAC;AAAA,EACtB,GAAG,CAAC,CAAC;AAEL,QAAM,sBAAsB,MAAM,YAAY,CAAC,eAA6B;AACxE,eAAW,UAAU;AAAA,EACzB,GAAG,CAAC,CAAC;AAEL,QAAM,mBAAmB,MAAM,YAAY,CAAC,SAAiB;AACzD,kBAAc,WAAS,EAAE,GAAG,MAAM,KAAK,EAAE;AAAA,EAC7C,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgB,MAAM,YAAY,MAAM;AAC1C,SAAK,YAAY,eAAe,EAAE,UAAU,CAAC,0BAA0B,EAAE,CAAC;AAAA,EAC9E,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,UAAU,MAAM,QAA2C,MAAM;AACnE,WAAO;AAAA,MACH;AAAA,QACI,aAAa;AAAA,QACb,QAAQ,EAAE,4CAA4C,QAAQ;AAAA,QAC9D,eAAe;AAAA,MACnB;AAAA,MACA;AAAA,QACI,aAAa;AAAA,QACb,QAAQ,EAAE,gDAAgD,YAAY;AAAA,QACtE,eAAe;AAAA,MACnB;AAAA,MACA;AAAA,QACI,aAAa;AAAA,QACb,QAAQ,EAAE,0CAA0C,MAAM;AAAA,QAC1D,eAAe;AAAA,MACnB;AAAA,MACA;AAAA,QACI,aAAa;AAAA,QACb,QAAQ,EAAE,8CAA8C,UAAU;AAAA,QAClE,eAAe;AAAA,MACnB;AAAA,MACA;AAAA,QACI,aAAa;AAAA,QACb,QAAQ,EAAE,mDAAmD,UAAU;AAAA,QACvE,eAAe;AAAA,QACf,MAAM,CAAC,EAAE,IAAI,MAAM;AACf,iBAAO,IAAI,SAAS,aAAa,EAAE,qDAAqD,KAAK,IAAI,EAAE,sDAAsD,IAAI;AAAA,QACjK;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ,GAAG,CAAC,CAAC;AAGL,QAAM,UAAU,MAAM,QAAqB,MAAM;AAAA,IAC7C;AAAA,MACI,IAAI;AAAA,MACJ,OAAO,EAAE,2CAA2C,YAAY;AAAA,MAChE,MAAM;AAAA,IACV;AAAA,IACA;AAAA,MACI,IAAI;AAAA,MACJ,OAAO,EAAE,qCAAqC,MAAM;AAAA,MACpD,MAAM;AAAA,IACV;AAAA,IACA;AAAA,MACI,IAAI;AAAA,MACJ,OAAO,EAAE,yCAAyC,UAAU;AAAA,MAC5D,MAAM;AAAA,IACV;AAAA,EACJ,GAAG,CAAC,CAAC,CAAC;AAEN,SACI;AAAA,IAAC;AAAA;AAAA,MACG,OAAO,EAAE,wCAAwC,0BAA0B;AAAA,MAC3E;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,MAChB,MAAM,oBAAoB,SAAS,CAAC;AAAA,MACpC;AAAA,MACA;AAAA,MACA,iBAAiB;AAAA,MACjB,UAAU;AAAA,MACV,YAAY;AAAA,QACR,MAAM,oBAAoB,QAAQ;AAAA,QAClC,UAAU,oBAAoB,YAAY;AAAA,QAC1C,OAAO,oBAAoB,SAAS;AAAA,QACpC,YAAY,oBAAoB,cAAc;AAAA,QAC9C,cAAc;AAAA,MAClB;AAAA,MACA,eAAe;AAAA,QACX,OAAO,EAAE,sCAAsC,SAAS;AAAA,QACxD,WAAW;AAAA,QACX,cAAc;AAAA,MAClB;AAAA,MACA,YAAY,CAAC,QACT,oBAAC,cAAW,OAAO;AAAA,QACf,EAAE,IAAI,QAAQ,OAAO,EAAE,eAAe,MAAM,GAAG,MAAM,mCAAmC,IAAI,QAAQ,GAAG;AAAA,MAC3G,GAAG;AAAA,MAEP,OAAO,QAAQ,MAAM,UAAU;AAAA;AAAA,EACnC;AAER;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const features = [
|
|
2
|
+
{ id: "notifications.view", title: "View own notifications", module: "notifications" },
|
|
3
|
+
{ id: "notifications.create", title: "Create notifications for others", module: "notifications" },
|
|
4
|
+
{ id: "notifications.manage", title: "Manage all notifications", module: "notifications" }
|
|
5
|
+
];
|
|
6
|
+
var acl_default = features;
|
|
7
|
+
export {
|
|
8
|
+
acl_default as default,
|
|
9
|
+
features
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=acl.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/notifications/acl.ts"],
|
|
4
|
+
"sourcesContent": ["export const features = [\n { id: 'notifications.view', title: 'View own notifications', module: 'notifications' },\n { id: 'notifications.create', title: 'Create notifications for others', module: 'notifications' },\n { id: 'notifications.manage', title: 'Manage all notifications', module: 'notifications' },\n]\n\nexport default features\n"],
|
|
5
|
+
"mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,EAAE,IAAI,sBAAsB,OAAO,0BAA0B,QAAQ,gBAAgB;AAAA,EACrF,EAAE,IAAI,wBAAwB,OAAO,mCAAmC,QAAQ,gBAAgB;AAAA,EAChG,EAAE,IAAI,wBAAwB,OAAO,4BAA4B,QAAQ,gBAAgB;AAC3F;AAEA,IAAO,cAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { executeActionSchema } from "../../../data/validators.js";
|
|
2
|
+
import { actionResultResponseSchema, errorResponseSchema } from "../../openapi.js";
|
|
3
|
+
import { resolveNotificationContext } from "../../../lib/routeHelpers.js";
|
|
4
|
+
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
|
|
5
|
+
const metadata = {
|
|
6
|
+
POST: { requireAuth: true }
|
|
7
|
+
};
|
|
8
|
+
async function POST(req, { params }) {
|
|
9
|
+
const { id } = await params;
|
|
10
|
+
const { service, scope } = await resolveNotificationContext(req);
|
|
11
|
+
const body = await req.json().catch(() => ({}));
|
|
12
|
+
const input = executeActionSchema.parse(body);
|
|
13
|
+
try {
|
|
14
|
+
const { notification, result } = await service.executeAction(id, input, scope);
|
|
15
|
+
const action = notification.actionData?.actions?.find((a) => a.id === input.actionId);
|
|
16
|
+
const href = action?.href?.replace("{sourceEntityId}", notification.sourceEntityId ?? "");
|
|
17
|
+
return Response.json({
|
|
18
|
+
ok: true,
|
|
19
|
+
result,
|
|
20
|
+
href
|
|
21
|
+
});
|
|
22
|
+
} catch (error) {
|
|
23
|
+
const { t } = await resolveTranslations();
|
|
24
|
+
const fallback = t("notifications.error.action", "Failed to execute action");
|
|
25
|
+
const message = error instanceof Error && error.message ? error.message : fallback;
|
|
26
|
+
return Response.json({ error: message }, { status: 400 });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const openApi = {
|
|
30
|
+
POST: {
|
|
31
|
+
summary: "Execute notification action",
|
|
32
|
+
tags: ["Notifications"],
|
|
33
|
+
parameters: [
|
|
34
|
+
{
|
|
35
|
+
name: "id",
|
|
36
|
+
in: "path",
|
|
37
|
+
required: true,
|
|
38
|
+
schema: { type: "string", format: "uuid" }
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
requestBody: {
|
|
42
|
+
required: true,
|
|
43
|
+
content: {
|
|
44
|
+
"application/json": {
|
|
45
|
+
schema: executeActionSchema
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
responses: {
|
|
50
|
+
200: {
|
|
51
|
+
description: "Action executed successfully",
|
|
52
|
+
content: {
|
|
53
|
+
"application/json": {
|
|
54
|
+
schema: actionResultResponseSchema
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
400: {
|
|
59
|
+
description: "Action not found or failed",
|
|
60
|
+
content: {
|
|
61
|
+
"application/json": {
|
|
62
|
+
schema: errorResponseSchema
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
export {
|
|
70
|
+
POST,
|
|
71
|
+
metadata,
|
|
72
|
+
openApi
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=route.js.map
|