@open-mercato/core 0.4.2-canary-ab36fbd8f2 → 0.4.2-canary-da2b080494
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.ids.generated.js +1 -5
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +0 -2
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/api_docs/frontend/docs/api/page.js +2 -3
- 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 +0 -4
- package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js +0 -2
- package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
- package/dist/modules/auth/api/admin/nav.js +3 -4
- package/dist/modules/auth/api/admin/nav.js.map +2 -2
- package/dist/modules/auth/api/reset/confirm.js +2 -25
- package/dist/modules/auth/api/reset/confirm.js.map +2 -2
- package/dist/modules/auth/api/reset.js +0 -23
- package/dist/modules/auth/api/reset.js.map +2 -2
- package/dist/modules/auth/api/sidebar/preferences/route.js +9 -14
- package/dist/modules/auth/api/sidebar/preferences/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +2 -4
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/roles/[id]/edit/page.js +1 -4
- 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 +3 -18
- package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
- package/dist/modules/auth/backend/users/create/page.js +2 -15
- 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 +11 -25
- package/dist/modules/auth/cli.js.map +2 -2
- package/dist/modules/auth/commands/users.js +2 -59
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/auth/data/validators.js +2 -4
- package/dist/modules/auth/data/validators.js.map +2 -2
- package/dist/modules/auth/frontend/reset/[token]/page.js +10 -20
- package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
- package/dist/modules/auth/lib/setup-app.js +0 -1
- package/dist/modules/auth/lib/setup-app.js.map +2 -2
- package/dist/modules/auth/services/authService.js +3 -3
- package/dist/modules/auth/services/authService.js.map +2 -2
- package/dist/modules/business_rules/api/execute/route.js +1 -7
- package/dist/modules/business_rules/api/execute/route.js.map +2 -2
- package/dist/modules/business_rules/backend/rules/page.js +0 -4
- package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
- package/dist/modules/business_rules/backend/sets/page.js +0 -3
- package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-engine.js +3 -33
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/catalog/components/PriceKindSettings.js +0 -2
- 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 +0 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/configs/cli.js +0 -6
- 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 +1 -48
- package/dist/modules/configs/lib/system-status.js.map +2 -2
- package/dist/modules/configs/lib/upgrade-actions.js +0 -18
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +0 -3
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +0 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +0 -3
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +0 -3
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/page.js +0 -3
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +0 -31
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/components/CustomerTodosTable.js +0 -1
- package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
- package/dist/modules/dashboards/cli.js +5 -44
- package/dist/modules/dashboards/cli.js.map +2 -2
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +11 -16
- package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +3 -3
- package/dist/modules/dashboards/services/widgetDataService.js +3 -132
- package/dist/modules/dashboards/services/widgetDataService.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryTable.js +0 -2
- package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
- 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/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/components/QueryIndexesTable.js +1 -7
- 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/backend/sales/channels/offers/page.js +0 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +0 -2
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +0 -53
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +0 -26
- 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 +0 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js +0 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js +1 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +0 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- 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 +0 -79
- package/dist/modules/staff/commands/leave-requests.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/page.js +0 -5
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.js +0 -3
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +0 -3
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/lib/transition-handler.js +6 -14
- package/dist/modules/workflows/lib/transition-handler.js.map +2 -2
- package/generated/entities.ids.generated.ts +1 -5
- package/generated/entity-fields-registry.ts +0 -2
- package/package.json +2 -2
- package/src/modules/api_docs/frontend/docs/api/page.tsx +2 -3
- package/src/modules/api_keys/backend/api-keys/page.tsx +1 -1
- package/src/modules/attachments/components/AttachmentLibrary.tsx +0 -4
- package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +0 -2
- 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/admin/nav.ts +6 -10
- package/src/modules/auth/api/reset/confirm.ts +2 -25
- package/src/modules/auth/api/reset.ts +0 -23
- package/src/modules/auth/api/sidebar/preferences/route.ts +12 -21
- package/src/modules/auth/api/users/route.ts +2 -5
- package/src/modules/auth/backend/roles/[id]/edit/page.tsx +1 -4
- package/src/modules/auth/backend/roles/page.tsx +3 -3
- package/src/modules/auth/backend/users/[id]/edit/page.tsx +3 -22
- package/src/modules/auth/backend/users/create/page.tsx +2 -19
- package/src/modules/auth/backend/users/page.tsx +3 -3
- package/src/modules/auth/cli.ts +11 -38
- package/src/modules/auth/commands/users.ts +2 -73
- package/src/modules/auth/data/validators.ts +2 -5
- package/src/modules/auth/frontend/reset/[token]/page.tsx +11 -24
- package/src/modules/auth/i18n/de.json +1 -43
- package/src/modules/auth/i18n/en.json +1 -43
- package/src/modules/auth/i18n/es.json +1 -43
- package/src/modules/auth/i18n/pl.json +1 -43
- package/src/modules/auth/lib/setup-app.ts +0 -1
- package/src/modules/auth/services/authService.ts +4 -4
- package/src/modules/business_rules/api/execute/route.ts +1 -8
- package/src/modules/business_rules/backend/rules/page.tsx +0 -4
- package/src/modules/business_rules/backend/sets/page.tsx +0 -3
- package/src/modules/business_rules/i18n/en.json +1 -3
- package/src/modules/business_rules/lib/__tests__/rule-engine.test.ts +0 -51
- package/src/modules/business_rules/lib/rule-engine.ts +3 -57
- package/src/modules/catalog/components/PriceKindSettings.tsx +0 -2
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +2 -2
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +0 -2
- package/src/modules/catalog/i18n/en.json +1 -3
- package/src/modules/configs/cli.ts +0 -6
- package/src/modules/configs/components/CachePanel.tsx +4 -4
- package/src/modules/configs/i18n/en.json +2 -12
- package/src/modules/configs/i18n/pl.json +2 -12
- package/src/modules/configs/lib/system-status.ts +1 -48
- package/src/modules/configs/lib/system-status.types.ts +0 -1
- package/src/modules/configs/lib/upgrade-actions.ts +0 -18
- package/src/modules/currencies/backend/currencies/page.tsx +0 -3
- package/src/modules/currencies/backend/exchange-rates/page.tsx +0 -2
- package/src/modules/customers/backend/customers/companies/page.tsx +0 -3
- package/src/modules/customers/backend/customers/deals/page.tsx +0 -3
- package/src/modules/customers/backend/customers/people/page.tsx +0 -3
- package/src/modules/customers/commands/deals.ts +0 -39
- package/src/modules/customers/components/CustomerTodosTable.tsx +0 -1
- package/src/modules/customers/i18n/en.json +1 -5
- package/src/modules/dashboards/cli.ts +5 -55
- package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +11 -22
- package/src/modules/dashboards/services/widgetDataService.ts +4 -157
- package/src/modules/dictionaries/components/DictionaryTable.tsx +0 -2
- 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 +4 -3
- package/src/modules/feature_toggles/components/OverridesTable.tsx +1 -1
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +2 -2
- package/src/modules/query_index/components/QueryIndexesTable.tsx +2 -8
- 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/backend/sales/channels/offers/page.tsx +0 -2
- package/src/modules/sales/backend/sales/channels/page.tsx +0 -2
- package/src/modules/sales/commands/documents.ts +0 -65
- package/src/modules/sales/commands/payments.ts +0 -33
- 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 +0 -2
- package/src/modules/sales/components/documents/AdjustmentsSection.tsx +0 -2
- package/src/modules/sales/components/documents/PaymentsSection.tsx +1 -2
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +0 -2
- package/src/modules/sales/i18n/de.json +0 -20
- package/src/modules/sales/i18n/en.json +1 -25
- package/src/modules/sales/i18n/es.json +0 -20
- package/src/modules/sales/i18n/pl.json +0 -20
- 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 +0 -94
- package/src/modules/staff/i18n/de.json +0 -4
- package/src/modules/staff/i18n/en.json +1 -9
- package/src/modules/staff/i18n/es.json +0 -4
- package/src/modules/staff/i18n/pl.json +0 -4
- package/src/modules/workflows/backend/definitions/page.tsx +0 -5
- package/src/modules/workflows/backend/instances/page.tsx +1 -4
- package/src/modules/workflows/backend/tasks/page.tsx +1 -4
- package/src/modules/workflows/i18n/en.json +1 -3
- package/src/modules/workflows/lib/transition-handler.ts +6 -18
- package/dist/generated/entities/notification/index.js +0 -57
- package/dist/generated/entities/notification/index.js.map +0 -7
- package/dist/modules/auth/api/profile/route.js +0 -157
- package/dist/modules/auth/api/profile/route.js.map +0 -7
- package/dist/modules/auth/backend/auth/profile/page.js +0 -141
- package/dist/modules/auth/backend/auth/profile/page.js.map +0 -7
- package/dist/modules/auth/backend/auth/profile/page.meta.js +0 -13
- package/dist/modules/auth/backend/auth/profile/page.meta.js.map +0 -7
- package/dist/modules/auth/notifications.js +0 -112
- package/dist/modules/auth/notifications.js.map +0 -7
- package/dist/modules/business_rules/notifications.js +0 -28
- package/dist/modules/business_rules/notifications.js.map +0 -7
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js +0 -37
- package/dist/modules/business_rules/subscribers/rule-execution-failed-notification.js.map +0 -7
- package/dist/modules/catalog/notifications.js +0 -28
- package/dist/modules/catalog/notifications.js.map +0 -7
- package/dist/modules/catalog/subscribers/low-stock-notification.js +0 -38
- package/dist/modules/catalog/subscribers/low-stock-notification.js.map +0 -7
- package/dist/modules/customers/notifications.js +0 -48
- package/dist/modules/customers/notifications.js.map +0 -7
- package/dist/modules/dashboards/lib/role-widgets.js +0 -58
- package/dist/modules/dashboards/lib/role-widgets.js.map +0 -7
- package/dist/modules/notifications/acl.js +0 -11
- package/dist/modules/notifications/acl.js.map +0 -7
- package/dist/modules/notifications/api/[id]/action/route.js +0 -74
- package/dist/modules/notifications/api/[id]/action/route.js.map +0 -7
- package/dist/modules/notifications/api/[id]/dismiss/route.js +0 -15
- package/dist/modules/notifications/api/[id]/dismiss/route.js.map +0 -7
- package/dist/modules/notifications/api/[id]/read/route.js +0 -15
- package/dist/modules/notifications/api/[id]/read/route.js.map +0 -7
- package/dist/modules/notifications/api/[id]/restore/route.js +0 -53
- package/dist/modules/notifications/api/[id]/restore/route.js.map +0 -7
- package/dist/modules/notifications/api/batch/route.js +0 -17
- package/dist/modules/notifications/api/batch/route.js.map +0 -7
- package/dist/modules/notifications/api/feature/route.js +0 -17
- package/dist/modules/notifications/api/feature/route.js.map +0 -7
- package/dist/modules/notifications/api/mark-all-read/route.js +0 -35
- package/dist/modules/notifications/api/mark-all-read/route.js.map +0 -7
- package/dist/modules/notifications/api/openapi.js +0 -76
- package/dist/modules/notifications/api/openapi.js.map +0 -7
- package/dist/modules/notifications/api/role/route.js +0 -17
- package/dist/modules/notifications/api/role/route.js.map +0 -7
- package/dist/modules/notifications/api/route.js +0 -85
- package/dist/modules/notifications/api/route.js.map +0 -7
- package/dist/modules/notifications/api/settings/route.js +0 -155
- package/dist/modules/notifications/api/settings/route.js.map +0 -7
- package/dist/modules/notifications/api/unread-count/route.js +0 -38
- package/dist/modules/notifications/api/unread-count/route.js.map +0 -7
- package/dist/modules/notifications/backend/config/notifications/page.js +0 -10
- package/dist/modules/notifications/backend/config/notifications/page.js.map +0 -7
- package/dist/modules/notifications/backend/config/notifications/page.meta.js +0 -24
- package/dist/modules/notifications/backend/config/notifications/page.meta.js.map +0 -7
- package/dist/modules/notifications/cli.js +0 -16
- package/dist/modules/notifications/cli.js.map +0 -7
- package/dist/modules/notifications/data/entities.js +0 -112
- package/dist/modules/notifications/data/entities.js.map +0 -7
- package/dist/modules/notifications/data/validators.js +0 -98
- package/dist/modules/notifications/data/validators.js.map +0 -7
- package/dist/modules/notifications/di.js +0 -13
- package/dist/modules/notifications/di.js.map +0 -7
- package/dist/modules/notifications/emails/NotificationEmail.js +0 -58
- package/dist/modules/notifications/emails/NotificationEmail.js.map +0 -7
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js +0 -44
- package/dist/modules/notifications/frontend/NotificationInboxPageClient.js.map +0 -7
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js +0 -220
- package/dist/modules/notifications/frontend/NotificationSettingsPageClient.js.map +0 -7
- package/dist/modules/notifications/index.js +0 -14
- package/dist/modules/notifications/index.js.map +0 -7
- package/dist/modules/notifications/lib/deliveryConfig.js +0 -107
- package/dist/modules/notifications/lib/deliveryConfig.js.map +0 -7
- package/dist/modules/notifications/lib/deliveryStrategies.js +0 -14
- package/dist/modules/notifications/lib/deliveryStrategies.js.map +0 -7
- package/dist/modules/notifications/lib/events.js +0 -12
- package/dist/modules/notifications/lib/events.js.map +0 -7
- package/dist/modules/notifications/lib/notificationBuilder.js +0 -66
- package/dist/modules/notifications/lib/notificationBuilder.js.map +0 -7
- package/dist/modules/notifications/lib/notificationFactory.js +0 -54
- package/dist/modules/notifications/lib/notificationFactory.js.map +0 -7
- package/dist/modules/notifications/lib/notificationMapper.js +0 -34
- package/dist/modules/notifications/lib/notificationMapper.js.map +0 -7
- package/dist/modules/notifications/lib/notificationRecipients.js +0 -35
- package/dist/modules/notifications/lib/notificationRecipients.js.map +0 -7
- package/dist/modules/notifications/lib/notificationService.js +0 -279
- package/dist/modules/notifications/lib/notificationService.js.map +0 -7
- package/dist/modules/notifications/lib/routeHelpers.js +0 -101
- package/dist/modules/notifications/lib/routeHelpers.js.map +0 -7
- package/dist/modules/notifications/lib/safeHref.js +0 -24
- package/dist/modules/notifications/lib/safeHref.js.map +0 -7
- package/dist/modules/notifications/migrations/Migration20260123000001.js +0 -70
- package/dist/modules/notifications/migrations/Migration20260123000001.js.map +0 -7
- package/dist/modules/notifications/migrations/Migration20260126150000.js +0 -37
- package/dist/modules/notifications/migrations/Migration20260126150000.js.map +0 -7
- package/dist/modules/notifications/subscribers/deliver-notification.js +0 -165
- package/dist/modules/notifications/subscribers/deliver-notification.js.map +0 -7
- package/dist/modules/notifications/workers/create-notification.worker.js +0 -70
- package/dist/modules/notifications/workers/create-notification.worker.js.map +0 -7
- package/dist/modules/sales/notifications.client.js +0 -51
- package/dist/modules/sales/notifications.client.js.map +0 -7
- package/dist/modules/sales/notifications.js +0 -88
- package/dist/modules/sales/notifications.js.map +0 -7
- package/dist/modules/sales/subscribers/quote-expiring-notification.js +0 -38
- package/dist/modules/sales/subscribers/quote-expiring-notification.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +0 -137
- package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +0 -137
- package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/index.js +0 -7
- package/dist/modules/sales/widgets/notifications/index.js.map +0 -7
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js +0 -60
- package/dist/modules/sales/widgets/notifications/useSalesDocumentTotals.js.map +0 -7
- package/dist/modules/staff/notifications.js +0 -75
- package/dist/modules/staff/notifications.js.map +0 -7
- package/dist/modules/workflows/notifications.js +0 -28
- package/dist/modules/workflows/notifications.js.map +0 -7
- package/dist/modules/workflows/subscribers/task-assigned-notification.js +0 -38
- package/dist/modules/workflows/subscribers/task-assigned-notification.js.map +0 -7
- package/generated/entities/notification/index.ts +0 -27
- package/src/modules/auth/api/profile/route.ts +0 -163
- package/src/modules/auth/backend/auth/profile/page.meta.ts +0 -9
- package/src/modules/auth/backend/auth/profile/page.tsx +0 -174
- package/src/modules/auth/notifications.ts +0 -109
- package/src/modules/business_rules/notifications.ts +0 -25
- package/src/modules/business_rules/subscribers/rule-execution-failed-notification.ts +0 -50
- package/src/modules/catalog/notifications.ts +0 -25
- package/src/modules/catalog/subscribers/low-stock-notification.ts +0 -52
- package/src/modules/customers/notifications.ts +0 -44
- package/src/modules/dashboards/lib/role-widgets.ts +0 -80
- package/src/modules/notifications/__tests__/deliver-notification.test.ts +0 -195
- package/src/modules/notifications/__tests__/deliveryStrategies.test.ts +0 -19
- package/src/modules/notifications/__tests__/notificationService.test.ts +0 -208
- package/src/modules/notifications/acl.ts +0 -7
- package/src/modules/notifications/api/[id]/action/route.ts +0 -75
- package/src/modules/notifications/api/[id]/dismiss/route.ts +0 -12
- package/src/modules/notifications/api/[id]/read/route.ts +0 -12
- package/src/modules/notifications/api/[id]/restore/route.ts +0 -53
- package/src/modules/notifications/api/batch/route.ts +0 -14
- package/src/modules/notifications/api/feature/route.ts +0 -14
- package/src/modules/notifications/api/mark-all-read/route.ts +0 -34
- package/src/modules/notifications/api/openapi.ts +0 -76
- package/src/modules/notifications/api/role/route.ts +0 -14
- package/src/modules/notifications/api/route.ts +0 -92
- package/src/modules/notifications/api/settings/route.ts +0 -157
- package/src/modules/notifications/api/unread-count/route.ts +0 -38
- package/src/modules/notifications/backend/config/notifications/page.meta.ts +0 -22
- package/src/modules/notifications/backend/config/notifications/page.tsx +0 -12
- package/src/modules/notifications/cli.ts +0 -18
- package/src/modules/notifications/data/entities.ts +0 -99
- package/src/modules/notifications/data/validators.ts +0 -115
- package/src/modules/notifications/di.ts +0 -11
- package/src/modules/notifications/emails/NotificationEmail.tsx +0 -98
- package/src/modules/notifications/frontend/NotificationInboxPageClient.tsx +0 -42
- package/src/modules/notifications/frontend/NotificationSettingsPageClient.tsx +0 -233
- package/src/modules/notifications/i18n/de.json +0 -50
- package/src/modules/notifications/i18n/en.json +0 -50
- package/src/modules/notifications/i18n/es.json +0 -50
- package/src/modules/notifications/i18n/pl.json +0 -50
- package/src/modules/notifications/index.ts +0 -12
- package/src/modules/notifications/lib/deliveryConfig.ts +0 -153
- package/src/modules/notifications/lib/deliveryStrategies.ts +0 -50
- package/src/modules/notifications/lib/events.ts +0 -48
- package/src/modules/notifications/lib/notificationBuilder.ts +0 -121
- package/src/modules/notifications/lib/notificationFactory.ts +0 -76
- package/src/modules/notifications/lib/notificationMapper.ts +0 -33
- package/src/modules/notifications/lib/notificationRecipients.ts +0 -83
- package/src/modules/notifications/lib/notificationService.ts +0 -414
- package/src/modules/notifications/lib/routeHelpers.ts +0 -151
- package/src/modules/notifications/lib/safeHref.ts +0 -29
- package/src/modules/notifications/migrations/.snapshot-open-mercato.json +0 -300
- package/src/modules/notifications/migrations/Migration20260123000001.ts +0 -73
- package/src/modules/notifications/migrations/Migration20260126150000.ts +0 -39
- package/src/modules/notifications/subscribers/deliver-notification.ts +0 -204
- package/src/modules/notifications/workers/create-notification.worker.ts +0 -122
- package/src/modules/sales/notifications.client.ts +0 -65
- package/src/modules/sales/notifications.ts +0 -82
- package/src/modules/sales/subscribers/quote-expiring-notification.ts +0 -53
- package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +0 -156
- package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +0 -156
- package/src/modules/sales/widgets/notifications/index.ts +0 -2
- package/src/modules/sales/widgets/notifications/useSalesDocumentTotals.ts +0 -81
- package/src/modules/staff/notifications.ts +0 -71
- package/src/modules/workflows/notifications.ts +0 -25
- package/src/modules/workflows/subscribers/task-assigned-notification.ts +0 -53
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/auth/backend/roles/%5Bid%5D/edit/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { AclEditor, type AclData } from '@open-mercato/core/modules/auth/components/AclEditor'\nimport { WidgetVisibilityEditor
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { AclEditor, type AclData } from '@open-mercato/core/modules/auth/components/AclEditor'\nimport { WidgetVisibilityEditor } from '@open-mercato/core/modules/dashboards/components/WidgetVisibilityEditor'\nimport { E } from '#generated/entities.ids.generated'\nimport { TenantSelect } from '@open-mercato/core/modules/directory/components/TenantSelect'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype EditRoleFormValues = {\n name?: string\n tenantId?: string | null\n} & Record<string, unknown>\n\ntype RoleRecord = {\n id: string\n name: string\n tenantId: string | null\n tenantName?: string | null\n usersCount?: number | null\n} & Record<string, unknown>\n\ntype RoleListResponse = {\n items?: RoleRecord[]\n isSuperAdmin?: boolean\n}\n\nexport default function EditRolePage({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const [initial, setInitial] = React.useState<RoleRecord | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [aclData, setAclData] = React.useState<AclData>({ isSuperAdmin: false, features: [], organizations: null })\n const [actorIsSuperAdmin, setActorIsSuperAdmin] = React.useState(false)\n const [selectedTenantId, setSelectedTenantId] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n if (!id) return\n const roleId = id\n let cancelled = false\n async function load() {\n try {\n const { ok, result } = await apiCall<RoleListResponse>(`/api/auth/roles?id=${encodeURIComponent(roleId)}`)\n if (!ok) throw new Error(t('auth.roles.form.errors.load', 'Failed to load role'))\n const foundList = Array.isArray(result?.items) ? result?.items : []\n const found = (foundList?.[0] ?? null) as RoleRecord | null\n if (!cancelled) {\n setActorIsSuperAdmin(Boolean(result?.isSuperAdmin))\n setInitial(found || null)\n const tenant = found && typeof found.tenantId === 'string' ? found.tenantId : null\n setSelectedTenantId(tenant)\n }\n } catch {\n if (!cancelled) {\n setInitial(null)\n setSelectedTenantId(null)\n }\n }\n if (!cancelled) setLoading(false)\n }\n load()\n return () => { cancelled = true }\n }, [id, t])\n\n const preloadedTenants = React.useMemo(() => {\n if (!selectedTenantId) return null\n const name = initial?.tenantId === selectedTenantId\n ? (initial?.tenantName ?? selectedTenantId)\n : selectedTenantId\n return [{ id: selectedTenantId, name, isActive: true }]\n }, [initial, selectedTenantId])\n\n const fields = React.useMemo<CrudField[]>(() => {\n const disabled = !!(initial && typeof initial.usersCount === 'number' && initial.usersCount > 0)\n const list: CrudField[] = [\n {\n id: 'name',\n label: t('auth.roles.form.field.name', 'Name'),\n type: 'text',\n required: true,\n disabled,\n },\n ]\n if (actorIsSuperAdmin) {\n list.push({\n id: 'tenantId',\n label: t('auth.roles.form.field.tenant', 'Tenant'),\n type: 'custom',\n required: true,\n component: ({ value, setValue }) => {\n const normalizedValue = typeof value === 'string'\n ? value\n : (typeof selectedTenantId === 'string' ? selectedTenantId : null)\n return (\n <TenantSelect\n id=\"tenantId\"\n value={normalizedValue}\n onChange={(next) => {\n const resolved = next ?? null\n setValue(resolved)\n setSelectedTenantId(resolved)\n setAclData({ isSuperAdmin: false, features: [], organizations: null })\n }}\n includeEmptyOption\n className=\"w-full h-9 rounded border px-2 text-sm\"\n tenants={preloadedTenants}\n />\n )\n },\n })\n }\n return list\n }, [actorIsSuperAdmin, initial, preloadedTenants, selectedTenantId, t])\n\n const detailFieldIds = React.useMemo(() => {\n const base = ['name']\n if (actorIsSuperAdmin) base.push('tenantId')\n return base\n }, [actorIsSuperAdmin])\n\n const groups: CrudFormGroup[] = React.useMemo(() => ([\n { id: 'details', title: t('auth.roles.form.group.details', 'Details'), column: 1, fields: detailFieldIds },\n { id: 'customFields', title: t('entities.customFields.title', 'Custom Fields'), column: 2, kind: 'customFields' },\n {\n id: 'acl',\n title: t('auth.roles.form.group.access', 'Access'),\n column: 1,\n component: () => (id\n ? (\n <AclEditor\n kind=\"role\"\n targetId={String(id)}\n canEditOrganizations\n value={aclData}\n onChange={setAclData}\n currentUserIsSuperAdmin={actorIsSuperAdmin}\n tenantId={selectedTenantId ?? null}\n />\n )\n : null),\n },\n {\n id: 'dashboardWidgets',\n title: t('auth.roles.form.group.widgets', 'Dashboard Widgets'),\n column: 2,\n component: () => (id && !loading\n ? (\n <WidgetVisibilityEditor\n kind=\"role\"\n targetId={String(id)}\n tenantId={selectedTenantId ?? (initial?.tenantId ?? null)}\n />\n )\n : null),\n },\n ]), [aclData, actorIsSuperAdmin, detailFieldIds, id, initial, loading, selectedTenantId, t])\n\n if (!id) return null\n return (\n <Page>\n <PageBody>\n <CrudForm<EditRoleFormValues>\n title={t('auth.roles.form.title.edit', 'Edit Role')}\n backHref=\"/backend/roles\"\n entityId={E.auth.role}\n fields={fields}\n groups={groups}\n initialValues={initial || { id, tenantId: null }}\n isLoading={loading}\n loadingMessage={t('auth.roles.form.loading', 'Loading data...')}\n cancelHref=\"/backend/roles\"\n successRedirect={`/backend/roles?flash=${encodeURIComponent(t('auth.roles.flash.updated', 'Role saved'))}&type=success`}\n onSubmit={async (values) => {\n const customFields = collectCustomFieldValues(values)\n const payload: Record<string, unknown> = { id }\n if (values.name !== undefined) payload.name = values.name\n let effectiveTenantId: string | null = selectedTenantId ?? (initial?.tenantId ?? null)\n if (actorIsSuperAdmin) {\n const rawTenant = typeof values.tenantId === 'string' ? values.tenantId.trim() : selectedTenantId\n effectiveTenantId = rawTenant && rawTenant.length ? rawTenant : null\n payload.tenantId = effectiveTenantId\n }\n if (Object.keys(customFields).length) {\n payload.customFields = customFields\n }\n await updateCrud('auth/roles', payload)\n await updateCrud('auth/roles/acl', { roleId: id, tenantId: effectiveTenantId, ...aclData }, {\n errorMessage: t('auth.roles.form.errors.aclUpdate', 'Failed to update role access control'),\n })\n try { window.dispatchEvent(new Event('om:refresh-sidebar')) } catch {}\n }}\n onDelete={async () => {\n await deleteCrud('auth/roles', String(id), {\n errorMessage: t('auth.roles.form.errors.delete', 'Failed to delete role'),\n })\n }}\n deleteRedirect={`/backend/roles?flash=${encodeURIComponent(t('auth.roles.flash.deleted', 'Role deleted'))}&type=success`}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -97,9 +97,9 @@ function RolesListPage() {
|
|
|
97
97
|
setPage(1);
|
|
98
98
|
},
|
|
99
99
|
rowActions: (row) => /* @__PURE__ */ jsx(RowActions, { items: [
|
|
100
|
-
{
|
|
101
|
-
{
|
|
102
|
-
{
|
|
100
|
+
{ label: t("common.edit", "Edit"), href: `/backend/roles/${row.id}/edit` },
|
|
101
|
+
{ label: t("auth.roles.list.actions.showUsers", "Show users"), href: `/backend/users?roleId=${encodeURIComponent(row.id)}` },
|
|
102
|
+
{ label: t("common.delete", "Delete"), destructive: true, onSelect: () => {
|
|
103
103
|
void handleDelete(row);
|
|
104
104
|
} }
|
|
105
105
|
] }),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/auth/backend/roles/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\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 Row = {\n id: string\n name: string\n usersCount: number\n tenantId?: string | null\n tenantIds?: string[]\n tenantName?: string | null\n}\n\nexport default function RolesListPage() {\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'name', desc: false }])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [rows, setRows] = React.useState<Row[]>([])\n const [isLoading, setIsLoading] = React.useState(true)\n const [reloadToken, setReloadToken] = React.useState(0)\n const [isSuperAdmin, setIsSuperAdmin] = React.useState(false)\n const scopeVersion = useOrganizationScopeVersion()\n const t = useT()\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setIsLoading(true)\n try {\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', '50')\n if (search) params.set('search', search)\n const fallback = { items: [], total: 0, totalPages: 1, isSuperAdmin: false }\n const j = await readApiResultOrThrow<{\n items?: Row[]\n total?: number\n totalPages?: number\n isSuperAdmin?: boolean\n }>(\n `/api/auth/roles?${params.toString()}`,\n undefined,\n { errorMessage: t('auth.roles.list.error.load', 'Failed to load roles'), fallback },\n )\n if (!cancelled) {\n setRows(j.items || [])\n setTotal(j.total || 0)\n setTotalPages(j.totalPages || 1)\n setIsSuperAdmin(!!j.isSuperAdmin)\n }\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [page, search, reloadToken, scopeVersion, t])\n\n const handleDelete = React.useCallback(async (row: Row) => {\n if (!window.confirm(t('auth.roles.list.confirmDelete', 'Delete role \"{{name}}\"?').replace('{{name}}', row.name))) return\n try {\n const call = await apiCall(\n `/api/auth/roles?id=${encodeURIComponent(row.id)}`,\n { method: 'DELETE' },\n )\n if (!call.ok) {\n await raiseCrudError(call.response, t('auth.roles.list.error.delete', 'Failed to delete role'))\n }\n flash(t('auth.roles.list.success.delete', 'Role deleted'), 'success')\n setReloadToken((token) => token + 1)\n } catch (error) {\n const message = error instanceof Error ? error.message : t('auth.roles.list.error.delete', 'Failed to delete role')\n flash(message, 'error')\n }\n }, [t])\n\n const showTenantColumn = React.useMemo(\n () => isSuperAdmin && rows.some((row) => row.tenantName),\n [isSuperAdmin, rows],\n )\n const columns = React.useMemo<ColumnDef<Row>[]>(() => {\n const base: ColumnDef<Row>[] = [\n { accessorKey: 'name', header: t('auth.roles.list.columns.role', 'Role') },\n { accessorKey: 'usersCount', header: t('auth.roles.list.columns.users', 'Users') },\n ]\n if (showTenantColumn) {\n base.splice(1, 0, { accessorKey: 'tenantName', header: t('auth.roles.list.columns.tenant', 'Tenant') })\n }\n return base\n }, [showTenantColumn, t])\n\n return (\n <Page>\n <PageBody>\n <DataTable\n title={t('auth.roles.list.title', 'Roles')}\n actions={(\n <Button asChild>\n <Link href=\"/backend/roles/create\">{t('auth.roles.list.actions.create', 'Create')}</Link>\n </Button>\n )}\n columns={columns}\n data={rows}\n searchValue={search}\n onSearchChange={(v) => { setSearch(v); setPage(1) }}\n rowActions={(row) => (\n <RowActions items={[\n {
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport Link from 'next/link'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\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 Row = {\n id: string\n name: string\n usersCount: number\n tenantId?: string | null\n tenantIds?: string[]\n tenantName?: string | null\n}\n\nexport default function RolesListPage() {\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'name', desc: false }])\n const [page, setPage] = React.useState(1)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [rows, setRows] = React.useState<Row[]>([])\n const [isLoading, setIsLoading] = React.useState(true)\n const [reloadToken, setReloadToken] = React.useState(0)\n const [isSuperAdmin, setIsSuperAdmin] = React.useState(false)\n const scopeVersion = useOrganizationScopeVersion()\n const t = useT()\n\n React.useEffect(() => {\n let cancelled = false\n async function load() {\n setIsLoading(true)\n try {\n const params = new URLSearchParams()\n params.set('page', String(page))\n params.set('pageSize', '50')\n if (search) params.set('search', search)\n const fallback = { items: [], total: 0, totalPages: 1, isSuperAdmin: false }\n const j = await readApiResultOrThrow<{\n items?: Row[]\n total?: number\n totalPages?: number\n isSuperAdmin?: boolean\n }>(\n `/api/auth/roles?${params.toString()}`,\n undefined,\n { errorMessage: t('auth.roles.list.error.load', 'Failed to load roles'), fallback },\n )\n if (!cancelled) {\n setRows(j.items || [])\n setTotal(j.total || 0)\n setTotalPages(j.totalPages || 1)\n setIsSuperAdmin(!!j.isSuperAdmin)\n }\n } finally {\n if (!cancelled) setIsLoading(false)\n }\n }\n load()\n return () => { cancelled = true }\n }, [page, search, reloadToken, scopeVersion, t])\n\n const handleDelete = React.useCallback(async (row: Row) => {\n if (!window.confirm(t('auth.roles.list.confirmDelete', 'Delete role \"{{name}}\"?').replace('{{name}}', row.name))) return\n try {\n const call = await apiCall(\n `/api/auth/roles?id=${encodeURIComponent(row.id)}`,\n { method: 'DELETE' },\n )\n if (!call.ok) {\n await raiseCrudError(call.response, t('auth.roles.list.error.delete', 'Failed to delete role'))\n }\n flash(t('auth.roles.list.success.delete', 'Role deleted'), 'success')\n setReloadToken((token) => token + 1)\n } catch (error) {\n const message = error instanceof Error ? error.message : t('auth.roles.list.error.delete', 'Failed to delete role')\n flash(message, 'error')\n }\n }, [t])\n\n const showTenantColumn = React.useMemo(\n () => isSuperAdmin && rows.some((row) => row.tenantName),\n [isSuperAdmin, rows],\n )\n const columns = React.useMemo<ColumnDef<Row>[]>(() => {\n const base: ColumnDef<Row>[] = [\n { accessorKey: 'name', header: t('auth.roles.list.columns.role', 'Role') },\n { accessorKey: 'usersCount', header: t('auth.roles.list.columns.users', 'Users') },\n ]\n if (showTenantColumn) {\n base.splice(1, 0, { accessorKey: 'tenantName', header: t('auth.roles.list.columns.tenant', 'Tenant') })\n }\n return base\n }, [showTenantColumn, t])\n\n return (\n <Page>\n <PageBody>\n <DataTable\n title={t('auth.roles.list.title', 'Roles')}\n actions={(\n <Button asChild>\n <Link href=\"/backend/roles/create\">{t('auth.roles.list.actions.create', 'Create')}</Link>\n </Button>\n )}\n columns={columns}\n data={rows}\n searchValue={search}\n onSearchChange={(v) => { setSearch(v); setPage(1) }}\n rowActions={(row) => (\n <RowActions items={[\n { label: t('common.edit', 'Edit'), href: `/backend/roles/${row.id}/edit` },\n { label: t('auth.roles.list.actions.showUsers', 'Show users'), href: `/backend/users?roleId=${encodeURIComponent(row.id)}` },\n { label: t('common.delete', 'Delete'), destructive: true, onSelect: () => { void handleDelete(row) } },\n ]} />\n )}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n perspective={{ tableId: 'auth.roles.list' }}\n pagination={{ page, pageSize: 50, 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
|
}
|
|
@@ -13,7 +13,6 @@ import { TenantSelect } from "@open-mercato/core/modules/directory/components/Te
|
|
|
13
13
|
import { fetchRoleOptions } from "@open-mercato/core/modules/auth/backend/users/roleOptions";
|
|
14
14
|
import { WidgetVisibilityEditor } from "@open-mercato/core/modules/dashboards/components/WidgetVisibilityEditor";
|
|
15
15
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
16
|
-
import { formatPasswordRequirements, getPasswordPolicy } from "@open-mercato/shared/lib/auth/passwordPolicy";
|
|
17
16
|
function TenantAwareOrganizationSelectInput({
|
|
18
17
|
fieldId,
|
|
19
18
|
value,
|
|
@@ -62,13 +61,6 @@ function EditUserPage({ params }) {
|
|
|
62
61
|
const [aclData, setAclData] = React.useState({ isSuperAdmin: false, features: [], organizations: null });
|
|
63
62
|
const [customFieldValues, setCustomFieldValues] = React.useState({});
|
|
64
63
|
const [actorIsSuperAdmin, setActorIsSuperAdmin] = React.useState(false);
|
|
65
|
-
const widgetEditorRef = React.useRef(null);
|
|
66
|
-
const passwordPolicy = React.useMemo(() => getPasswordPolicy(), []);
|
|
67
|
-
const passwordRequirements = React.useMemo(
|
|
68
|
-
() => formatPasswordRequirements(passwordPolicy, t),
|
|
69
|
-
[passwordPolicy, t]
|
|
70
|
-
);
|
|
71
|
-
const passwordDescription = React.useMemo(() => passwordRequirements ? t("auth.password.requirements.help", "Password requirements: {requirements}", { requirements: passwordRequirements }) : void 0, [passwordRequirements, t]);
|
|
72
64
|
React.useEffect(() => {
|
|
73
65
|
if (!id) {
|
|
74
66
|
setLoading(false);
|
|
@@ -154,12 +146,7 @@ function EditUserPage({ params }) {
|
|
|
154
146
|
const fields = React.useMemo(() => {
|
|
155
147
|
const items = [
|
|
156
148
|
{ id: "email", label: t("auth.users.form.field.email", "Email"), type: "text", required: true },
|
|
157
|
-
{
|
|
158
|
-
id: "password",
|
|
159
|
-
label: t("auth.users.form.field.password", "Password"),
|
|
160
|
-
type: "text",
|
|
161
|
-
description: passwordDescription
|
|
162
|
-
}
|
|
149
|
+
{ id: "password", label: t("auth.users.form.field.password", "Password"), type: "text" }
|
|
163
150
|
];
|
|
164
151
|
if (actorIsSuperAdmin) {
|
|
165
152
|
items.push({
|
|
@@ -209,7 +196,7 @@ function EditUserPage({ params }) {
|
|
|
209
196
|
});
|
|
210
197
|
items.push({ id: "roles", label: t("auth.users.form.field.roles", "Roles"), type: "tags", loadOptions: loadRoleOptions });
|
|
211
198
|
return items;
|
|
212
|
-
}, [actorIsSuperAdmin, loadRoleOptions,
|
|
199
|
+
}, [actorIsSuperAdmin, loadRoleOptions, preloadedTenants, selectedOrgId, selectedTenantId, t]);
|
|
213
200
|
const detailFieldIds = React.useMemo(() => {
|
|
214
201
|
const base = ["email", "password", "organizationId", "roles"];
|
|
215
202
|
if (actorIsSuperAdmin) base.splice(2, 0, "tenantId");
|
|
@@ -246,8 +233,7 @@ function EditUserPage({ params }) {
|
|
|
246
233
|
kind: "user",
|
|
247
234
|
targetId: String(id),
|
|
248
235
|
tenantId: selectedTenantId ?? null,
|
|
249
|
-
organizationId: initialUser?.organizationId ?? null
|
|
250
|
-
ref: widgetEditorRef
|
|
236
|
+
organizationId: initialUser?.organizationId ?? null
|
|
251
237
|
}
|
|
252
238
|
) : null
|
|
253
239
|
}
|
|
@@ -303,7 +289,6 @@ function EditUserPage({ params }) {
|
|
|
303
289
|
await updateCrud("auth/users/acl", { userId: id, ...aclData }, {
|
|
304
290
|
errorMessage: t("auth.users.form.errors.aclUpdate", "Failed to update user access control")
|
|
305
291
|
});
|
|
306
|
-
await widgetEditorRef.current?.save();
|
|
307
292
|
try {
|
|
308
293
|
window.dispatchEvent(new Event("om:refresh-sidebar"));
|
|
309
294
|
} catch {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/modules/auth/backend/users/%5Bid%5D/edit/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { E } from '#generated/entities.ids.generated'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm, type CrudField, type CrudFormGroup, type CrudFieldOption } from '@open-mercato/ui/backend/CrudForm'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { AclEditor, type AclData } from '@open-mercato/core/modules/auth/components/AclEditor'\nimport { OrganizationSelect } from '@open-mercato/core/modules/directory/components/OrganizationSelect'\nimport { TenantSelect } from '@open-mercato/core/modules/directory/components/TenantSelect'\nimport { fetchRoleOptions } from '@open-mercato/core/modules/auth/backend/users/roleOptions'\nimport { WidgetVisibilityEditor, type WidgetVisibilityEditorHandle } from '@open-mercato/core/modules/dashboards/components/WidgetVisibilityEditor'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { formatPasswordRequirements, getPasswordPolicy } from '@open-mercato/shared/lib/auth/passwordPolicy'\n\ntype EditUserFormValues = {\n email: string\n password: string\n tenantId: string | null\n organizationId: string | null\n roles: string[]\n} & Record<string, unknown>\n\ntype LoadedUser = {\n id: string\n email: string\n organizationId: string | null\n tenantId: string | null\n tenantName: string | null\n organizationName: string | null\n roles: string[]\n}\n\ntype UserApiItem = {\n id?: string | null\n email?: string | null\n organizationId?: string | null\n tenantId?: string | null\n tenantName?: string | null\n organizationName?: string | null\n roles?: unknown\n}\n\ntype UserListResponse = {\n items?: UserApiItem[]\n isSuperAdmin?: boolean\n}\n\ntype FeatureCheckResponse = {\n ok?: boolean\n}\n\ntype TenantAwareOrganizationSelectProps = {\n fieldId: string\n value: string | null\n setValue: (value: string | null) => void\n tenantId: string | null\n includeInactiveIds?: Iterable<string | null | undefined>\n}\n\nfunction TenantAwareOrganizationSelectInput({\n fieldId,\n value,\n setValue,\n tenantId,\n includeInactiveIds,\n}: TenantAwareOrganizationSelectProps) {\n const prevTenantRef = React.useRef<string | null>(tenantId)\n const hydratedRef = React.useRef(false)\n const handleChange = React.useCallback((next: string | null) => {\n setValue(next ?? null)\n }, [setValue])\n\n React.useEffect(() => {\n if (!hydratedRef.current) {\n hydratedRef.current = true\n prevTenantRef.current = tenantId\n return\n }\n if (prevTenantRef.current !== tenantId) {\n prevTenantRef.current = tenantId\n setValue(null)\n }\n }, [tenantId, setValue])\n\n return (\n <OrganizationSelect\n id={fieldId}\n value={value}\n onChange={handleChange}\n required\n includeEmptyOption\n className=\"w-full h-9 rounded border px-2 text-sm\"\n includeInactiveIds={includeInactiveIds}\n tenantId={tenantId}\n />\n )\n}\n\nexport default function EditUserPage({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const [initialUser, setInitialUser] = React.useState<LoadedUser | null>(null)\n const [selectedTenantId, setSelectedTenantId] = React.useState<string | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [canEditOrgs, setCanEditOrgs] = React.useState(false)\n const [aclData, setAclData] = React.useState<AclData>({ isSuperAdmin: false, features: [], organizations: null })\n const [customFieldValues, setCustomFieldValues] = React.useState<Record<string, unknown>>({})\n const [actorIsSuperAdmin, setActorIsSuperAdmin] = React.useState(false)\n const widgetEditorRef = React.useRef<WidgetVisibilityEditorHandle | null>(null)\n const passwordPolicy = React.useMemo(() => getPasswordPolicy(), [])\n const passwordRequirements = React.useMemo(\n () => formatPasswordRequirements(passwordPolicy, t),\n [passwordPolicy, t],\n )\n const passwordDescription = React.useMemo(() => (\n passwordRequirements\n ? t('auth.password.requirements.help', 'Password requirements: {requirements}', { requirements: passwordRequirements })\n : undefined\n ), [passwordRequirements, t])\n\n React.useEffect(() => {\n if (!id) {\n setLoading(false)\n setError(t('auth.users.form.errors.noId', 'No user ID provided'))\n return\n }\n let cancelled = false\n async function load() {\n setLoading(true)\n setError(null)\n setCustomFieldValues({})\n try {\n const { ok, result } = await apiCall<UserListResponse>(\n `/api/auth/users?id=${encodeURIComponent(String(id))}&page=1&pageSize=1`,\n )\n if (!ok) throw new Error('load_failed')\n const item = Array.isArray(result?.items) ? result?.items?.[0] : undefined\n if (!cancelled) {\n setActorIsSuperAdmin(Boolean(result?.isSuperAdmin))\n if (!item) {\n setError(t('auth.users.form.errors.notFound', 'User not found'))\n setCustomFieldValues({})\n setInitialUser(null)\n setSelectedTenantId(null)\n } else {\n setInitialUser({\n id: item.id ? String(item.id) : String(id),\n email: item.email ? String(item.email) : '',\n organizationId: item.organizationId ? String(item.organizationId) : null,\n tenantId: item.tenantId ? String(item.tenantId) : null,\n tenantName: item.tenantName ? String(item.tenantName) : null,\n organizationName: item.organizationName ? String(item.organizationName) : null,\n roles: Array.isArray(item.roles)\n ? item.roles\n .map((role) => (typeof role === 'string' ? role : role == null ? '' : String(role)))\n .filter((role) => role.trim().length > 0)\n : [],\n })\n setSelectedTenantId(item.tenantId ? String(item.tenantId) : null)\n const custom: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(item)) {\n if (key.startsWith('cf_')) custom[key] = value as unknown\n else if (key.startsWith('cf:')) custom[`cf_${key.slice(3)}`] = value as unknown\n }\n setCustomFieldValues(custom)\n }\n }\n } catch (err) {\n console.error('Failed to load user:', err)\n if (!cancelled) setError(t('auth.users.form.errors.load', 'Failed to load user data'))\n if (!cancelled) setCustomFieldValues({})\n }\n try {\n const featureCheck = await apiCall<FeatureCheckResponse>(\n '/api/auth/feature-check',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ features: ['directory.organizations.view'] }),\n },\n { fallback: { ok: false } },\n )\n if (!cancelled) setCanEditOrgs(Boolean(featureCheck.result?.ok))\n } catch (err) {\n console.error('Failed to check features:', err)\n }\n if (!cancelled) setLoading(false)\n }\n load()\n return () => { cancelled = true }\n }, [id, t])\n\n const selectedOrgId = initialUser?.organizationId ? String(initialUser.organizationId) : null\n const preloadedTenants = React.useMemo(() => {\n if (!selectedTenantId) return null\n const name = initialUser?.tenantId === selectedTenantId\n ? (initialUser?.tenantName ?? selectedTenantId)\n : selectedTenantId\n return [{ id: selectedTenantId, name, isActive: true }]\n }, [initialUser, selectedTenantId])\n\n const loadRoleOptions = React.useCallback(async (query?: string): Promise<CrudFieldOption[]> => {\n if (actorIsSuperAdmin) {\n if (!selectedTenantId) return []\n return fetchRoleOptions(query, { tenantId: selectedTenantId })\n }\n return fetchRoleOptions(query)\n }, [actorIsSuperAdmin, selectedTenantId])\n\n const fields: CrudField[] = React.useMemo(() => {\n const items: CrudField[] = [\n { id: 'email', label: t('auth.users.form.field.email', 'Email'), type: 'text', required: true },\n {\n id: 'password',\n label: t('auth.users.form.field.password', 'Password'),\n type: 'text',\n description: passwordDescription,\n },\n ]\n if (actorIsSuperAdmin) {\n items.push({\n id: 'tenantId',\n label: t('auth.users.form.field.tenant', 'Tenant'),\n type: 'custom',\n required: true,\n component: ({ value, setValue }) => {\n const normalizedValue = typeof value === 'string'\n ? value\n : (typeof selectedTenantId === 'string' ? selectedTenantId : null)\n return (\n <TenantSelect\n id=\"tenantId\"\n value={normalizedValue}\n onChange={(next) => {\n const resolved = next ?? null\n setValue(resolved)\n setSelectedTenantId(resolved)\n setAclData({ isSuperAdmin: false, features: [], organizations: null })\n }}\n includeEmptyOption\n className=\"w-full h-9 rounded border px-2 text-sm\"\n required\n tenants={preloadedTenants}\n />\n )\n },\n })\n }\n items.push({\n id: 'organizationId',\n label: t('auth.users.form.field.organization', 'Organization'),\n type: 'custom',\n component: ({ id, value, setValue }) => {\n const normalizedValue = typeof value === 'string' ? (value.length > 0 ? value : null) : null\n return (\n <TenantAwareOrganizationSelectInput\n fieldId={id}\n value={normalizedValue}\n setValue={(next) => setValue(next ?? null)}\n tenantId={selectedTenantId}\n includeInactiveIds={selectedOrgId ? [selectedOrgId] : undefined}\n />\n )\n },\n })\n items.push({ id: 'roles', label: t('auth.users.form.field.roles', 'Roles'), type: 'tags', loadOptions: loadRoleOptions })\n return items\n }, [actorIsSuperAdmin, loadRoleOptions, passwordDescription, preloadedTenants, selectedOrgId, selectedTenantId, t])\n\n const detailFieldIds = React.useMemo(() => {\n const base: string[] = ['email', 'password', 'organizationId', 'roles']\n if (actorIsSuperAdmin) base.splice(2, 0, 'tenantId')\n return base\n }, [actorIsSuperAdmin])\n\n const groups: CrudFormGroup[] = React.useMemo(() => [\n { id: 'details', title: t('auth.users.form.group.details', 'Details'), column: 1, fields: detailFieldIds },\n { id: 'custom', title: t('auth.users.form.group.customFields', 'Custom Data'), column: 2, kind: 'customFields' },\n {\n id: 'acl',\n title: t('auth.users.form.group.access', 'Access'),\n column: 1,\n component: () => (id\n ? (\n <AclEditor\n kind=\"user\"\n targetId={String(id)}\n canEditOrganizations={canEditOrgs}\n value={aclData}\n onChange={setAclData}\n userRoles={initialUser?.roles || []}\n currentUserIsSuperAdmin={actorIsSuperAdmin}\n tenantId={selectedTenantId ?? null}\n />\n )\n : null),\n },\n {\n id: 'dashboardWidgets',\n title: t('auth.users.form.group.widgets', 'Dashboard Widgets'),\n column: 2,\n component: () => (id && initialUser\n ? (\n <WidgetVisibilityEditor\n kind=\"user\"\n targetId={String(id)}\n tenantId={selectedTenantId ?? null}\n organizationId={initialUser?.organizationId ?? null}\n ref={widgetEditorRef}\n />\n ) : null\n ),\n },\n ], [aclData, actorIsSuperAdmin, canEditOrgs, detailFieldIds, id, initialUser, selectedTenantId, t])\n\n const initialValues = React.useMemo(() => {\n if (initialUser) {\n return {\n email: initialUser.email,\n password: '',\n tenantId: initialUser.tenantId,\n organizationId: initialUser.organizationId,\n roles: initialUser.roles,\n ...customFieldValues,\n }\n }\n return {\n email: '',\n password: '',\n tenantId: selectedTenantId ?? null,\n organizationId: null,\n roles: [],\n ...customFieldValues,\n }\n }, [initialUser, customFieldValues, selectedTenantId])\n\n return (\n <Page>\n <PageBody>\n {error && (\n <div className=\"p-4 mb-4 bg-red-50 border border-red-200 rounded text-red-800\">\n {error}\n </div>\n )}\n <CrudForm<EditUserFormValues>\n title={t('auth.users.form.title.edit', 'Edit User')}\n backHref=\"/backend/users\"\n fields={fields}\n groups={groups}\n entityId={E.auth.user}\n initialValues={initialValues}\n isLoading={loading}\n loadingMessage={t('auth.users.form.loading', 'Loading user data...')}\n submitLabel={t('auth.users.form.action.save', 'Save')}\n cancelHref=\"/backend/users\"\n successRedirect={`/backend/users?flash=${encodeURIComponent(t('auth.users.flash.updated', 'User saved'))}&type=success`}\n onSubmit={async (values) => {\n if (!id) return\n const customFields = collectCustomFieldValues(values)\n const payload = {\n id: id ? String(id) : '',\n email: values.email,\n password: values.password && values.password.trim() ? values.password : undefined,\n organizationId: values.organizationId ? values.organizationId : undefined,\n roles: Array.isArray(values.roles) ? values.roles : [],\n ...(Object.keys(customFields).length ? { customFields } : {}),\n }\n await updateCrud('auth/users', payload)\n await updateCrud('auth/users/acl', { userId: id, ...aclData }, {\n errorMessage: t('auth.users.form.errors.aclUpdate', 'Failed to update user access control'),\n })\n await widgetEditorRef.current?.save()\n try { window.dispatchEvent(new Event('om:refresh-sidebar')) } catch {}\n }}\n onDelete={async () => {\n await deleteCrud('auth/users', String(id), {\n errorMessage: t('auth.users.form.errors.delete', 'Failed to delete user'),\n })\n }}\n deleteRedirect={`/backend/users?flash=${encodeURIComponent(t('auth.users.flash.deleted', 'User deleted'))}&type=success`}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { E } from '#generated/entities.ids.generated'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm, type CrudField, type CrudFormGroup, type CrudFieldOption } from '@open-mercato/ui/backend/CrudForm'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { deleteCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { AclEditor, type AclData } from '@open-mercato/core/modules/auth/components/AclEditor'\nimport { OrganizationSelect } from '@open-mercato/core/modules/directory/components/OrganizationSelect'\nimport { TenantSelect } from '@open-mercato/core/modules/directory/components/TenantSelect'\nimport { fetchRoleOptions } from '@open-mercato/core/modules/auth/backend/users/roleOptions'\nimport { WidgetVisibilityEditor } from '@open-mercato/core/modules/dashboards/components/WidgetVisibilityEditor'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype EditUserFormValues = {\n email: string\n password: string\n tenantId: string | null\n organizationId: string | null\n roles: string[]\n} & Record<string, unknown>\n\ntype LoadedUser = {\n id: string\n email: string\n organizationId: string | null\n tenantId: string | null\n tenantName: string | null\n organizationName: string | null\n roles: string[]\n}\n\ntype UserApiItem = {\n id?: string | null\n email?: string | null\n organizationId?: string | null\n tenantId?: string | null\n tenantName?: string | null\n organizationName?: string | null\n roles?: unknown\n}\n\ntype UserListResponse = {\n items?: UserApiItem[]\n isSuperAdmin?: boolean\n}\n\ntype FeatureCheckResponse = {\n ok?: boolean\n}\n\ntype TenantAwareOrganizationSelectProps = {\n fieldId: string\n value: string | null\n setValue: (value: string | null) => void\n tenantId: string | null\n includeInactiveIds?: Iterable<string | null | undefined>\n}\n\nfunction TenantAwareOrganizationSelectInput({\n fieldId,\n value,\n setValue,\n tenantId,\n includeInactiveIds,\n}: TenantAwareOrganizationSelectProps) {\n const prevTenantRef = React.useRef<string | null>(tenantId)\n const hydratedRef = React.useRef(false)\n const handleChange = React.useCallback((next: string | null) => {\n setValue(next ?? null)\n }, [setValue])\n\n React.useEffect(() => {\n if (!hydratedRef.current) {\n hydratedRef.current = true\n prevTenantRef.current = tenantId\n return\n }\n if (prevTenantRef.current !== tenantId) {\n prevTenantRef.current = tenantId\n setValue(null)\n }\n }, [tenantId, setValue])\n\n return (\n <OrganizationSelect\n id={fieldId}\n value={value}\n onChange={handleChange}\n required\n includeEmptyOption\n className=\"w-full h-9 rounded border px-2 text-sm\"\n includeInactiveIds={includeInactiveIds}\n tenantId={tenantId}\n />\n )\n}\n\nexport default function EditUserPage({ params }: { params?: { id?: string } }) {\n const id = params?.id\n const t = useT()\n const [initialUser, setInitialUser] = React.useState<LoadedUser | null>(null)\n const [selectedTenantId, setSelectedTenantId] = React.useState<string | null>(null)\n const [loading, setLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [canEditOrgs, setCanEditOrgs] = React.useState(false)\n const [aclData, setAclData] = React.useState<AclData>({ isSuperAdmin: false, features: [], organizations: null })\n const [customFieldValues, setCustomFieldValues] = React.useState<Record<string, unknown>>({})\n const [actorIsSuperAdmin, setActorIsSuperAdmin] = React.useState(false)\n\n React.useEffect(() => {\n if (!id) {\n setLoading(false)\n setError(t('auth.users.form.errors.noId', 'No user ID provided'))\n return\n }\n let cancelled = false\n async function load() {\n setLoading(true)\n setError(null)\n setCustomFieldValues({})\n try {\n const { ok, result } = await apiCall<UserListResponse>(\n `/api/auth/users?id=${encodeURIComponent(String(id))}&page=1&pageSize=1`,\n )\n if (!ok) throw new Error('load_failed')\n const item = Array.isArray(result?.items) ? result?.items?.[0] : undefined\n if (!cancelled) {\n setActorIsSuperAdmin(Boolean(result?.isSuperAdmin))\n if (!item) {\n setError(t('auth.users.form.errors.notFound', 'User not found'))\n setCustomFieldValues({})\n setInitialUser(null)\n setSelectedTenantId(null)\n } else {\n setInitialUser({\n id: item.id ? String(item.id) : String(id),\n email: item.email ? String(item.email) : '',\n organizationId: item.organizationId ? String(item.organizationId) : null,\n tenantId: item.tenantId ? String(item.tenantId) : null,\n tenantName: item.tenantName ? String(item.tenantName) : null,\n organizationName: item.organizationName ? String(item.organizationName) : null,\n roles: Array.isArray(item.roles)\n ? item.roles\n .map((role) => (typeof role === 'string' ? role : role == null ? '' : String(role)))\n .filter((role) => role.trim().length > 0)\n : [],\n })\n setSelectedTenantId(item.tenantId ? String(item.tenantId) : null)\n const custom: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(item)) {\n if (key.startsWith('cf_')) custom[key] = value as unknown\n else if (key.startsWith('cf:')) custom[`cf_${key.slice(3)}`] = value as unknown\n }\n setCustomFieldValues(custom)\n }\n }\n } catch (err) {\n console.error('Failed to load user:', err)\n if (!cancelled) setError(t('auth.users.form.errors.load', 'Failed to load user data'))\n if (!cancelled) setCustomFieldValues({})\n }\n try {\n const featureCheck = await apiCall<FeatureCheckResponse>(\n '/api/auth/feature-check',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ features: ['directory.organizations.view'] }),\n },\n { fallback: { ok: false } },\n )\n if (!cancelled) setCanEditOrgs(Boolean(featureCheck.result?.ok))\n } catch (err) {\n console.error('Failed to check features:', err)\n }\n if (!cancelled) setLoading(false)\n }\n load()\n return () => { cancelled = true }\n }, [id, t])\n\n const selectedOrgId = initialUser?.organizationId ? String(initialUser.organizationId) : null\n const preloadedTenants = React.useMemo(() => {\n if (!selectedTenantId) return null\n const name = initialUser?.tenantId === selectedTenantId\n ? (initialUser?.tenantName ?? selectedTenantId)\n : selectedTenantId\n return [{ id: selectedTenantId, name, isActive: true }]\n }, [initialUser, selectedTenantId])\n\n const loadRoleOptions = React.useCallback(async (query?: string): Promise<CrudFieldOption[]> => {\n if (actorIsSuperAdmin) {\n if (!selectedTenantId) return []\n return fetchRoleOptions(query, { tenantId: selectedTenantId })\n }\n return fetchRoleOptions(query)\n }, [actorIsSuperAdmin, selectedTenantId])\n\n const fields: CrudField[] = React.useMemo(() => {\n const items: CrudField[] = [\n { id: 'email', label: t('auth.users.form.field.email', 'Email'), type: 'text', required: true },\n { id: 'password', label: t('auth.users.form.field.password', 'Password'), type: 'text' },\n ]\n if (actorIsSuperAdmin) {\n items.push({\n id: 'tenantId',\n label: t('auth.users.form.field.tenant', 'Tenant'),\n type: 'custom',\n required: true,\n component: ({ value, setValue }) => {\n const normalizedValue = typeof value === 'string'\n ? value\n : (typeof selectedTenantId === 'string' ? selectedTenantId : null)\n return (\n <TenantSelect\n id=\"tenantId\"\n value={normalizedValue}\n onChange={(next) => {\n const resolved = next ?? null\n setValue(resolved)\n setSelectedTenantId(resolved)\n setAclData({ isSuperAdmin: false, features: [], organizations: null })\n }}\n includeEmptyOption\n className=\"w-full h-9 rounded border px-2 text-sm\"\n required\n tenants={preloadedTenants}\n />\n )\n },\n })\n }\n items.push({\n id: 'organizationId',\n label: t('auth.users.form.field.organization', 'Organization'),\n type: 'custom',\n component: ({ id, value, setValue }) => {\n const normalizedValue = typeof value === 'string' ? (value.length > 0 ? value : null) : null\n return (\n <TenantAwareOrganizationSelectInput\n fieldId={id}\n value={normalizedValue}\n setValue={(next) => setValue(next ?? null)}\n tenantId={selectedTenantId}\n includeInactiveIds={selectedOrgId ? [selectedOrgId] : undefined}\n />\n )\n },\n })\n items.push({ id: 'roles', label: t('auth.users.form.field.roles', 'Roles'), type: 'tags', loadOptions: loadRoleOptions })\n return items\n }, [actorIsSuperAdmin, loadRoleOptions, preloadedTenants, selectedOrgId, selectedTenantId, t])\n\n const detailFieldIds = React.useMemo(() => {\n const base: string[] = ['email', 'password', 'organizationId', 'roles']\n if (actorIsSuperAdmin) base.splice(2, 0, 'tenantId')\n return base\n }, [actorIsSuperAdmin])\n\n const groups: CrudFormGroup[] = React.useMemo(() => [\n { id: 'details', title: t('auth.users.form.group.details', 'Details'), column: 1, fields: detailFieldIds },\n { id: 'custom', title: t('auth.users.form.group.customFields', 'Custom Data'), column: 2, kind: 'customFields' },\n {\n id: 'acl',\n title: t('auth.users.form.group.access', 'Access'),\n column: 1,\n component: () => (id\n ? (\n <AclEditor\n kind=\"user\"\n targetId={String(id)}\n canEditOrganizations={canEditOrgs}\n value={aclData}\n onChange={setAclData}\n userRoles={initialUser?.roles || []}\n currentUserIsSuperAdmin={actorIsSuperAdmin}\n tenantId={selectedTenantId ?? null}\n />\n )\n : null),\n },\n {\n id: 'dashboardWidgets',\n title: t('auth.users.form.group.widgets', 'Dashboard Widgets'),\n column: 2,\n component: () => (id && initialUser\n ? (\n <WidgetVisibilityEditor\n kind=\"user\"\n targetId={String(id)}\n tenantId={selectedTenantId ?? null}\n organizationId={initialUser?.organizationId ?? null}\n />\n ) : null\n ),\n },\n ], [aclData, actorIsSuperAdmin, canEditOrgs, detailFieldIds, id, initialUser, selectedTenantId, t])\n\n const initialValues = React.useMemo(() => {\n if (initialUser) {\n return {\n email: initialUser.email,\n password: '',\n tenantId: initialUser.tenantId,\n organizationId: initialUser.organizationId,\n roles: initialUser.roles,\n ...customFieldValues,\n }\n }\n return {\n email: '',\n password: '',\n tenantId: selectedTenantId ?? null,\n organizationId: null,\n roles: [],\n ...customFieldValues,\n }\n }, [initialUser, customFieldValues, selectedTenantId])\n\n return (\n <Page>\n <PageBody>\n {error && (\n <div className=\"p-4 mb-4 bg-red-50 border border-red-200 rounded text-red-800\">\n {error}\n </div>\n )}\n <CrudForm<EditUserFormValues>\n title={t('auth.users.form.title.edit', 'Edit User')}\n backHref=\"/backend/users\"\n fields={fields}\n groups={groups}\n entityId={E.auth.user}\n initialValues={initialValues}\n isLoading={loading}\n loadingMessage={t('auth.users.form.loading', 'Loading user data...')}\n submitLabel={t('auth.users.form.action.save', 'Save')}\n cancelHref=\"/backend/users\"\n successRedirect={`/backend/users?flash=${encodeURIComponent(t('auth.users.flash.updated', 'User saved'))}&type=success`}\n onSubmit={async (values) => {\n if (!id) return\n const customFields = collectCustomFieldValues(values)\n const payload = {\n id: id ? String(id) : '',\n email: values.email,\n password: values.password && values.password.trim() ? values.password : undefined,\n organizationId: values.organizationId ? values.organizationId : undefined,\n roles: Array.isArray(values.roles) ? values.roles : [],\n ...(Object.keys(customFields).length ? { customFields } : {}),\n }\n await updateCrud('auth/users', payload)\n await updateCrud('auth/users/acl', { userId: id, ...aclData }, {\n errorMessage: t('auth.users.form.errors.aclUpdate', 'Failed to update user access control'),\n })\n try { window.dispatchEvent(new Event('om:refresh-sidebar')) } catch {}\n }}\n onDelete={async () => {\n await deleteCrud('auth/users', String(id), {\n errorMessage: t('auth.users.form.errors.delete', 'Failed to delete user'),\n })\n }}\n deleteRedirect={`/backend/users?flash=${encodeURIComponent(t('auth.users.flash.deleted', 'User deleted'))}&type=success`}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["id"]
|
|
7
7
|
}
|
|
@@ -12,7 +12,6 @@ import { TenantSelect } from "@open-mercato/core/modules/directory/components/Te
|
|
|
12
12
|
import { fetchRoleOptions } from "@open-mercato/core/modules/auth/backend/users/roleOptions";
|
|
13
13
|
import { Spinner } from "@open-mercato/ui/primitives/spinner";
|
|
14
14
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
15
|
-
import { formatPasswordRequirements, getPasswordPolicy } from "@open-mercato/shared/lib/auth/passwordPolicy";
|
|
16
15
|
function TenantAwareOrganizationSelectInput({
|
|
17
16
|
fieldId,
|
|
18
17
|
value,
|
|
@@ -59,12 +58,6 @@ function CreateUserPage() {
|
|
|
59
58
|
const [selectedWidgets, setSelectedWidgets] = React.useState([]);
|
|
60
59
|
const [selectedTenantId, setSelectedTenantId] = React.useState(null);
|
|
61
60
|
const [actorIsSuperAdmin, setActorIsSuperAdmin] = React.useState(false);
|
|
62
|
-
const passwordPolicy = React.useMemo(() => getPasswordPolicy(), []);
|
|
63
|
-
const passwordRequirements = React.useMemo(
|
|
64
|
-
() => formatPasswordRequirements(passwordPolicy, t),
|
|
65
|
-
[passwordPolicy, t]
|
|
66
|
-
);
|
|
67
|
-
const passwordDescription = React.useMemo(() => passwordRequirements ? t("auth.password.requirements.help", "Password requirements: {requirements}", { requirements: passwordRequirements }) : void 0, [passwordRequirements, t]);
|
|
68
61
|
React.useEffect(() => {
|
|
69
62
|
let cancelled = false;
|
|
70
63
|
async function loadCatalog() {
|
|
@@ -134,13 +127,7 @@ function CreateUserPage() {
|
|
|
134
127
|
const fields = React.useMemo(() => {
|
|
135
128
|
const items = [
|
|
136
129
|
{ id: "email", label: t("auth.users.form.field.email", "Email"), type: "text", required: true },
|
|
137
|
-
{
|
|
138
|
-
id: "password",
|
|
139
|
-
label: t("auth.users.form.field.password", "Password"),
|
|
140
|
-
type: "text",
|
|
141
|
-
required: true,
|
|
142
|
-
description: passwordDescription
|
|
143
|
-
}
|
|
130
|
+
{ id: "password", label: t("auth.users.form.field.password", "Password"), type: "text", required: true }
|
|
144
131
|
];
|
|
145
132
|
if (actorIsSuperAdmin) {
|
|
146
133
|
items.push({
|
|
@@ -187,7 +174,7 @@ function CreateUserPage() {
|
|
|
187
174
|
});
|
|
188
175
|
items.push({ id: "roles", label: t("auth.users.form.field.roles", "Roles"), type: "tags", loadOptions: loadRoleOptions });
|
|
189
176
|
return items;
|
|
190
|
-
}, [actorIsSuperAdmin, loadRoleOptions,
|
|
177
|
+
}, [actorIsSuperAdmin, loadRoleOptions, selectedTenantId, t]);
|
|
191
178
|
const detailFieldIds = React.useMemo(() => {
|
|
192
179
|
const base = ["email", "password", "organizationId", "roles"];
|
|
193
180
|
if (actorIsSuperAdmin) base.splice(2, 0, "tenantId");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/auth/backend/users/create/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { E } from '#generated/entities.ids.generated'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm, type CrudField, type CrudFormGroup, type CrudFieldOption } from '@open-mercato/ui/backend/CrudForm'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { OrganizationSelect } from '@open-mercato/core/modules/directory/components/OrganizationSelect'\nimport { TenantSelect } from '@open-mercato/core/modules/directory/components/TenantSelect'\nimport { fetchRoleOptions } from '@open-mercato/core/modules/auth/backend/users/roleOptions'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { formatPasswordRequirements, getPasswordPolicy } from '@open-mercato/shared/lib/auth/passwordPolicy'\n\ntype CreateUserFormValues = {\n email: string\n password: string\n tenantId: string | null\n organizationId: string | null\n roles: string[]\n} & Record<string, unknown>\n\ntype UserListResponse = {\n isSuperAdmin?: boolean\n}\n\ntype WidgetCatalogResponse = {\n items?: Array<{ id?: string | null; title?: string | null; description?: string | null }>\n}\n\ntype TenantAwareOrganizationSelectProps = {\n fieldId: string\n value: string | null\n setValue: (value: string | null) => void\n tenantId: string | null\n includeInactiveIds?: Iterable<string | null | undefined>\n}\n\nfunction TenantAwareOrganizationSelectInput({\n fieldId,\n value,\n setValue,\n tenantId,\n includeInactiveIds,\n}: TenantAwareOrganizationSelectProps) {\n const prevTenantRef = React.useRef<string | null>(tenantId)\n const hydratedRef = React.useRef(false)\n const handleChange = React.useCallback((next: string | null) => {\n setValue(next ?? null)\n }, [setValue])\n\n React.useEffect(() => {\n if (!hydratedRef.current) {\n hydratedRef.current = true\n prevTenantRef.current = tenantId\n return\n }\n if (prevTenantRef.current !== tenantId) {\n prevTenantRef.current = tenantId\n setValue(null)\n }\n }, [tenantId, setValue])\n\n return (\n <OrganizationSelect\n id={fieldId}\n value={value}\n onChange={handleChange}\n required\n includeEmptyOption\n className=\"w-full h-9 rounded border px-2 text-sm\"\n tenantId={tenantId}\n includeInactiveIds={includeInactiveIds}\n />\n )\n}\n\nexport default function CreateUserPage() {\n const t = useT()\n const [widgetCatalog, setWidgetCatalog] = React.useState<Array<{ id: string; title: string; description: string | null }>>([])\n const [widgetLoading, setWidgetLoading] = React.useState(true)\n const [widgetError, setWidgetError] = React.useState<string | null>(null)\n const [widgetMode, setWidgetMode] = React.useState<'inherit' | 'override'>('inherit')\n const [selectedWidgets, setSelectedWidgets] = React.useState<string[]>([])\n const [selectedTenantId, setSelectedTenantId] = React.useState<string | null>(null)\n const [actorIsSuperAdmin, setActorIsSuperAdmin] = React.useState(false)\n const passwordPolicy = React.useMemo(() => getPasswordPolicy(), [])\n const passwordRequirements = React.useMemo(\n () => formatPasswordRequirements(passwordPolicy, t),\n [passwordPolicy, t],\n )\n const passwordDescription = React.useMemo(() => (\n passwordRequirements\n ? t('auth.password.requirements.help', 'Password requirements: {requirements}', { requirements: passwordRequirements })\n : undefined\n ), [passwordRequirements, t])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadCatalog() {\n setWidgetLoading(true)\n setWidgetError(null)\n try {\n const { ok, result } = await apiCall<WidgetCatalogResponse>('/api/dashboards/widgets/catalog')\n if (!ok) throw new Error('request_failed')\n if (!cancelled) {\n const rawItems: unknown[] = Array.isArray(result?.items) ? result?.items ?? [] : []\n const normalized = rawItems\n .map((item: unknown) => {\n if (!item || typeof item !== 'object') return null\n const entry = item as Record<string, unknown>\n const idValue = entry.id\n const titleValue = entry.title\n const descriptionValue = entry.description\n const id = typeof idValue === 'string' ? idValue : null\n if (!id || !id.length) return null\n const title = typeof titleValue === 'string' && titleValue.length > 0 ? titleValue : id\n const description = typeof descriptionValue === 'string' && descriptionValue.length > 0 ? descriptionValue : null\n return { id, title, description }\n })\n .filter((item): item is { id: string; title: string; description: string | null } => item !== null)\n setWidgetCatalog(normalized)\n }\n } catch (err) {\n console.error('Failed to load dashboard widget catalog', err)\n if (!cancelled) {\n setWidgetError(t(\n 'auth.users.widgets.errors.load',\n 'Unable to load dashboard widgets. You can configure them later from the user page.',\n ))\n }\n } finally {\n if (!cancelled) setWidgetLoading(false)\n }\n }\n loadCatalog()\n return () => { cancelled = true }\n }, [t])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadActor() {\n try {\n const { ok, result } = await apiCall<UserListResponse>('/api/auth/users?page=1&pageSize=1')\n if (!cancelled && ok) setActorIsSuperAdmin(Boolean(result?.isSuperAdmin))\n } catch (err) {\n console.error('Failed to resolve actor super admin flag', err)\n }\n }\n loadActor()\n return () => { cancelled = true }\n }, [])\n\n const toggleWidget = React.useCallback((id: string) => {\n setSelectedWidgets((prev) => (prev.includes(id) ? prev.filter((value) => value !== id) : [...prev, id]))\n }, [])\n\n const loadRoleOptions = React.useCallback(async (query?: string): Promise<CrudFieldOption[]> => {\n if (actorIsSuperAdmin) {\n if (!selectedTenantId) return []\n return fetchRoleOptions(query, { tenantId: selectedTenantId })\n }\n return fetchRoleOptions(query)\n }, [actorIsSuperAdmin, selectedTenantId])\n\n const fields: CrudField[] = React.useMemo(() => {\n const items: CrudField[] = [\n { id: 'email', label: t('auth.users.form.field.email', 'Email'), type: 'text', required: true },\n {\n id: 'password',\n label: t('auth.users.form.field.password', 'Password'),\n type: 'text',\n required: true,\n description: passwordDescription,\n },\n ]\n if (actorIsSuperAdmin) {\n items.push({\n id: 'tenantId',\n label: t('auth.users.form.field.tenant', 'Tenant'),\n type: 'custom',\n required: true,\n component: ({ value, setValue }) => {\n const normalizedValue = typeof value === 'string'\n ? value\n : (typeof selectedTenantId === 'string' ? selectedTenantId : null)\n return (\n <TenantSelect\n id=\"tenantId\"\n value={normalizedValue}\n onChange={(next) => {\n const resolved = next ?? null\n setValue(resolved)\n setSelectedTenantId(resolved)\n }}\n includeEmptyOption\n className=\"w-full h-9 rounded border px-2 text-sm\"\n required\n />\n )\n },\n })\n }\n items.push({\n id: 'organizationId',\n label: t('auth.users.form.field.organization', 'Organization'),\n type: 'custom',\n component: ({ id, value, setValue }) => {\n const normalizedValue = typeof value === 'string' ? value : null\n return (\n <TenantAwareOrganizationSelectInput\n fieldId={id}\n value={normalizedValue}\n setValue={(next) => setValue(next ?? null)}\n tenantId={selectedTenantId}\n />\n )\n },\n })\n items.push({ id: 'roles', label: t('auth.users.form.field.roles', 'Roles'), type: 'tags', loadOptions: loadRoleOptions })\n return items\n }, [actorIsSuperAdmin, loadRoleOptions, passwordDescription, selectedTenantId, t])\n\n const detailFieldIds = React.useMemo(() => {\n const base: string[] = ['email', 'password', 'organizationId', 'roles']\n if (actorIsSuperAdmin) base.splice(2, 0, 'tenantId')\n return base\n }, [actorIsSuperAdmin])\n\n const groups: CrudFormGroup[] = React.useMemo(() => [\n { id: 'details', title: t('auth.users.form.group.details', 'Details'), column: 1, fields: detailFieldIds },\n {\n id: 'acl',\n title: t('auth.users.form.group.access', 'Access'),\n column: 1,\n component: () => (\n <div className=\"text-sm text-muted-foreground\">\n {t('auth.users.form.aclHint', 'ACL can be edited after creating the user.')}\n </div>\n ),\n },\n { id: 'custom', title: t('auth.users.form.group.customFields', 'Custom Data'), column: 2, kind: 'customFields' },\n {\n id: 'dashboardWidgets',\n title: t('auth.users.form.group.widgets', 'Dashboard Widgets'),\n column: 2,\n component: () => (\n <DashboardWidgetSelector\n catalog={widgetCatalog}\n loading={widgetLoading}\n error={widgetError}\n mode={widgetMode}\n onModeChange={setWidgetMode}\n selected={selectedWidgets}\n onToggle={toggleWidget}\n />\n ),\n },\n ], [detailFieldIds, t, widgetCatalog, widgetError, widgetLoading, widgetMode, selectedWidgets, toggleWidget])\n\n const initialValues = React.useMemo<Partial<CreateUserFormValues>>(\n () => ({\n email: '',\n password: '',\n tenantId: null,\n organizationId: null,\n roles: [],\n }),\n [],\n )\n\n return (\n <Page>\n <PageBody>\n <CrudForm<CreateUserFormValues>\n title={t('auth.users.form.title.create', 'Create User')}\n backHref=\"/backend/users\"\n fields={fields}\n groups={groups}\n entityId={E.auth.user}\n initialValues={initialValues}\n submitLabel={t('auth.users.form.action.create', 'Create')}\n cancelHref=\"/backend/users\"\n successRedirect={`/backend/users?flash=${encodeURIComponent(t('auth.users.flash.created', 'User created'))}&type=success`}\n onSubmit={async (values) => {\n const customFields = collectCustomFieldValues(values)\n const payload: Record<string, unknown> = {\n email: values.email,\n password: values.password,\n organizationId: values.organizationId ? values.organizationId : null,\n roles: Array.isArray(values.roles) ? values.roles : [],\n ...(Object.keys(customFields).length ? { customFields } : {}),\n }\n if (actorIsSuperAdmin) {\n const rawTenant = typeof values.tenantId === 'string' ? values.tenantId.trim() : null\n payload.tenantId = rawTenant && rawTenant.length ? rawTenant : null\n }\n const { result: created } = await createCrud<{ id?: string }>('auth/users', payload)\n const newUserId = typeof created?.id === 'string' ? created.id : null\n\n if (widgetMode === 'override' && newUserId) {\n await updateCrud('dashboards/users/widgets', {\n userId: newUserId,\n mode: 'override',\n widgetIds: selectedWidgets,\n organizationId: values.organizationId ? values.organizationId : null,\n tenantId: actorIsSuperAdmin\n ? (typeof values.tenantId === 'string' && values.tenantId.length ? values.tenantId : null)\n : null,\n }, {\n errorMessage: t('auth.users.form.errors.widgetsAssign', 'Failed to assign dashboard widgets to the new user'),\n })\n }\n }}\n />\n </PageBody>\n </Page>\n )\n}\n\nfunction DashboardWidgetSelector({\n catalog,\n loading,\n error,\n mode,\n onModeChange,\n selected,\n onToggle,\n}: {\n catalog: Array<{ id: string; title: string; description: string | null }>\n loading: boolean\n error: string | null\n mode: 'inherit' | 'override'\n onModeChange: (mode: 'inherit' | 'override') => void\n selected: string[]\n onToggle: (id: string) => void\n}) {\n const t = useT()\n if (loading) {\n return (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner size=\"sm\" /> {t('auth.users.widgets.loading', 'Loading widgets\u2026')}\n </div>\n )\n }\n\n return (\n <div className=\"space-y-3\">\n {error && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">{error}</div>\n )}\n {!error && (\n <>\n <div className=\"flex items-center gap-3 rounded-md border bg-muted/30 px-3 py-2\">\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"radio\"\n value=\"inherit\"\n checked={mode === 'inherit'}\n onChange={() => onModeChange('inherit')}\n />\n {t('auth.users.widgets.mode.inherit', 'Inherit from roles')}\n </label>\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"radio\"\n value=\"override\"\n checked={mode === 'override'}\n onChange={() => onModeChange('override')}\n />\n {t('auth.users.widgets.mode.override', 'Override for this user')}\n </label>\n </div>\n {mode === 'override' && (\n <div className=\"space-y-2\">\n {catalog.map((widget) => (\n <label key={widget.id} className=\"flex items-start gap-3 rounded-md border px-3 py-2 hover:border-primary/40\">\n <input\n type=\"checkbox\"\n className=\"mt-1 size-4\"\n checked={selected.includes(widget.id)}\n onChange={() => onToggle(widget.id)}\n />\n <div>\n <div className=\"text-sm font-medium leading-none\">{widget.title}</div>\n {widget.description ? <div className=\"text-xs text-muted-foreground\">{widget.description}</div> : null}\n </div>\n </label>\n ))}\n </div>\n )}\n {mode === 'inherit' && (\n <div className=\"rounded-md border bg-muted/20 px-3 py-2 text-xs text-muted-foreground\">\n {t('auth.users.widgets.mode.hint', 'New users inherit widgets from their assigned roles. Override to pick a custom set.')}\n </div>\n )}\n </>\n )}\n </div>\n )\n}\n"],
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { E } from '#generated/entities.ids.generated'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm, type CrudField, type CrudFormGroup, type CrudFieldOption } from '@open-mercato/ui/backend/CrudForm'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { createCrud, updateCrud } from '@open-mercato/ui/backend/utils/crud'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { OrganizationSelect } from '@open-mercato/core/modules/directory/components/OrganizationSelect'\nimport { TenantSelect } from '@open-mercato/core/modules/directory/components/TenantSelect'\nimport { fetchRoleOptions } from '@open-mercato/core/modules/auth/backend/users/roleOptions'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\ntype CreateUserFormValues = {\n email: string\n password: string\n tenantId: string | null\n organizationId: string | null\n roles: string[]\n} & Record<string, unknown>\n\ntype UserListResponse = {\n isSuperAdmin?: boolean\n}\n\ntype WidgetCatalogResponse = {\n items?: Array<{ id?: string | null; title?: string | null; description?: string | null }>\n}\n\ntype TenantAwareOrganizationSelectProps = {\n fieldId: string\n value: string | null\n setValue: (value: string | null) => void\n tenantId: string | null\n includeInactiveIds?: Iterable<string | null | undefined>\n}\n\nfunction TenantAwareOrganizationSelectInput({\n fieldId,\n value,\n setValue,\n tenantId,\n includeInactiveIds,\n}: TenantAwareOrganizationSelectProps) {\n const prevTenantRef = React.useRef<string | null>(tenantId)\n const hydratedRef = React.useRef(false)\n const handleChange = React.useCallback((next: string | null) => {\n setValue(next ?? null)\n }, [setValue])\n\n React.useEffect(() => {\n if (!hydratedRef.current) {\n hydratedRef.current = true\n prevTenantRef.current = tenantId\n return\n }\n if (prevTenantRef.current !== tenantId) {\n prevTenantRef.current = tenantId\n setValue(null)\n }\n }, [tenantId, setValue])\n\n return (\n <OrganizationSelect\n id={fieldId}\n value={value}\n onChange={handleChange}\n required\n includeEmptyOption\n className=\"w-full h-9 rounded border px-2 text-sm\"\n tenantId={tenantId}\n includeInactiveIds={includeInactiveIds}\n />\n )\n}\n\nexport default function CreateUserPage() {\n const t = useT()\n const [widgetCatalog, setWidgetCatalog] = React.useState<Array<{ id: string; title: string; description: string | null }>>([])\n const [widgetLoading, setWidgetLoading] = React.useState(true)\n const [widgetError, setWidgetError] = React.useState<string | null>(null)\n const [widgetMode, setWidgetMode] = React.useState<'inherit' | 'override'>('inherit')\n const [selectedWidgets, setSelectedWidgets] = React.useState<string[]>([])\n const [selectedTenantId, setSelectedTenantId] = React.useState<string | null>(null)\n const [actorIsSuperAdmin, setActorIsSuperAdmin] = React.useState(false)\n\n React.useEffect(() => {\n let cancelled = false\n async function loadCatalog() {\n setWidgetLoading(true)\n setWidgetError(null)\n try {\n const { ok, result } = await apiCall<WidgetCatalogResponse>('/api/dashboards/widgets/catalog')\n if (!ok) throw new Error('request_failed')\n if (!cancelled) {\n const rawItems: unknown[] = Array.isArray(result?.items) ? result?.items ?? [] : []\n const normalized = rawItems\n .map((item: unknown) => {\n if (!item || typeof item !== 'object') return null\n const entry = item as Record<string, unknown>\n const idValue = entry.id\n const titleValue = entry.title\n const descriptionValue = entry.description\n const id = typeof idValue === 'string' ? idValue : null\n if (!id || !id.length) return null\n const title = typeof titleValue === 'string' && titleValue.length > 0 ? titleValue : id\n const description = typeof descriptionValue === 'string' && descriptionValue.length > 0 ? descriptionValue : null\n return { id, title, description }\n })\n .filter((item): item is { id: string; title: string; description: string | null } => item !== null)\n setWidgetCatalog(normalized)\n }\n } catch (err) {\n console.error('Failed to load dashboard widget catalog', err)\n if (!cancelled) {\n setWidgetError(t(\n 'auth.users.widgets.errors.load',\n 'Unable to load dashboard widgets. You can configure them later from the user page.',\n ))\n }\n } finally {\n if (!cancelled) setWidgetLoading(false)\n }\n }\n loadCatalog()\n return () => { cancelled = true }\n }, [t])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadActor() {\n try {\n const { ok, result } = await apiCall<UserListResponse>('/api/auth/users?page=1&pageSize=1')\n if (!cancelled && ok) setActorIsSuperAdmin(Boolean(result?.isSuperAdmin))\n } catch (err) {\n console.error('Failed to resolve actor super admin flag', err)\n }\n }\n loadActor()\n return () => { cancelled = true }\n }, [])\n\n const toggleWidget = React.useCallback((id: string) => {\n setSelectedWidgets((prev) => (prev.includes(id) ? prev.filter((value) => value !== id) : [...prev, id]))\n }, [])\n\n const loadRoleOptions = React.useCallback(async (query?: string): Promise<CrudFieldOption[]> => {\n if (actorIsSuperAdmin) {\n if (!selectedTenantId) return []\n return fetchRoleOptions(query, { tenantId: selectedTenantId })\n }\n return fetchRoleOptions(query)\n }, [actorIsSuperAdmin, selectedTenantId])\n\n const fields: CrudField[] = React.useMemo(() => {\n const items: CrudField[] = [\n { id: 'email', label: t('auth.users.form.field.email', 'Email'), type: 'text', required: true },\n { id: 'password', label: t('auth.users.form.field.password', 'Password'), type: 'text', required: true },\n ]\n if (actorIsSuperAdmin) {\n items.push({\n id: 'tenantId',\n label: t('auth.users.form.field.tenant', 'Tenant'),\n type: 'custom',\n required: true,\n component: ({ value, setValue }) => {\n const normalizedValue = typeof value === 'string'\n ? value\n : (typeof selectedTenantId === 'string' ? selectedTenantId : null)\n return (\n <TenantSelect\n id=\"tenantId\"\n value={normalizedValue}\n onChange={(next) => {\n const resolved = next ?? null\n setValue(resolved)\n setSelectedTenantId(resolved)\n }}\n includeEmptyOption\n className=\"w-full h-9 rounded border px-2 text-sm\"\n required\n />\n )\n },\n })\n }\n items.push({\n id: 'organizationId',\n label: t('auth.users.form.field.organization', 'Organization'),\n type: 'custom',\n component: ({ id, value, setValue }) => {\n const normalizedValue = typeof value === 'string' ? value : null\n return (\n <TenantAwareOrganizationSelectInput\n fieldId={id}\n value={normalizedValue}\n setValue={(next) => setValue(next ?? null)}\n tenantId={selectedTenantId}\n />\n )\n },\n })\n items.push({ id: 'roles', label: t('auth.users.form.field.roles', 'Roles'), type: 'tags', loadOptions: loadRoleOptions })\n return items\n }, [actorIsSuperAdmin, loadRoleOptions, selectedTenantId, t])\n\n const detailFieldIds = React.useMemo(() => {\n const base: string[] = ['email', 'password', 'organizationId', 'roles']\n if (actorIsSuperAdmin) base.splice(2, 0, 'tenantId')\n return base\n }, [actorIsSuperAdmin])\n\n const groups: CrudFormGroup[] = React.useMemo(() => [\n { id: 'details', title: t('auth.users.form.group.details', 'Details'), column: 1, fields: detailFieldIds },\n {\n id: 'acl',\n title: t('auth.users.form.group.access', 'Access'),\n column: 1,\n component: () => (\n <div className=\"text-sm text-muted-foreground\">\n {t('auth.users.form.aclHint', 'ACL can be edited after creating the user.')}\n </div>\n ),\n },\n { id: 'custom', title: t('auth.users.form.group.customFields', 'Custom Data'), column: 2, kind: 'customFields' },\n {\n id: 'dashboardWidgets',\n title: t('auth.users.form.group.widgets', 'Dashboard Widgets'),\n column: 2,\n component: () => (\n <DashboardWidgetSelector\n catalog={widgetCatalog}\n loading={widgetLoading}\n error={widgetError}\n mode={widgetMode}\n onModeChange={setWidgetMode}\n selected={selectedWidgets}\n onToggle={toggleWidget}\n />\n ),\n },\n ], [detailFieldIds, t, widgetCatalog, widgetError, widgetLoading, widgetMode, selectedWidgets, toggleWidget])\n\n const initialValues = React.useMemo<Partial<CreateUserFormValues>>(\n () => ({\n email: '',\n password: '',\n tenantId: null,\n organizationId: null,\n roles: [],\n }),\n [],\n )\n\n return (\n <Page>\n <PageBody>\n <CrudForm<CreateUserFormValues>\n title={t('auth.users.form.title.create', 'Create User')}\n backHref=\"/backend/users\"\n fields={fields}\n groups={groups}\n entityId={E.auth.user}\n initialValues={initialValues}\n submitLabel={t('auth.users.form.action.create', 'Create')}\n cancelHref=\"/backend/users\"\n successRedirect={`/backend/users?flash=${encodeURIComponent(t('auth.users.flash.created', 'User created'))}&type=success`}\n onSubmit={async (values) => {\n const customFields = collectCustomFieldValues(values)\n const payload: Record<string, unknown> = {\n email: values.email,\n password: values.password,\n organizationId: values.organizationId ? values.organizationId : null,\n roles: Array.isArray(values.roles) ? values.roles : [],\n ...(Object.keys(customFields).length ? { customFields } : {}),\n }\n if (actorIsSuperAdmin) {\n const rawTenant = typeof values.tenantId === 'string' ? values.tenantId.trim() : null\n payload.tenantId = rawTenant && rawTenant.length ? rawTenant : null\n }\n const { result: created } = await createCrud<{ id?: string }>('auth/users', payload)\n const newUserId = typeof created?.id === 'string' ? created.id : null\n\n if (widgetMode === 'override' && newUserId) {\n await updateCrud('dashboards/users/widgets', {\n userId: newUserId,\n mode: 'override',\n widgetIds: selectedWidgets,\n organizationId: values.organizationId ? values.organizationId : null,\n tenantId: actorIsSuperAdmin\n ? (typeof values.tenantId === 'string' && values.tenantId.length ? values.tenantId : null)\n : null,\n }, {\n errorMessage: t('auth.users.form.errors.widgetsAssign', 'Failed to assign dashboard widgets to the new user'),\n })\n }\n }}\n />\n </PageBody>\n </Page>\n )\n}\n\nfunction DashboardWidgetSelector({\n catalog,\n loading,\n error,\n mode,\n onModeChange,\n selected,\n onToggle,\n}: {\n catalog: Array<{ id: string; title: string; description: string | null }>\n loading: boolean\n error: string | null\n mode: 'inherit' | 'override'\n onModeChange: (mode: 'inherit' | 'override') => void\n selected: string[]\n onToggle: (id: string) => void\n}) {\n const t = useT()\n if (loading) {\n return (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner size=\"sm\" /> {t('auth.users.widgets.loading', 'Loading widgets\u2026')}\n </div>\n )\n }\n\n return (\n <div className=\"space-y-3\">\n {error && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/10 p-3 text-sm text-destructive\">{error}</div>\n )}\n {!error && (\n <>\n <div className=\"flex items-center gap-3 rounded-md border bg-muted/30 px-3 py-2\">\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"radio\"\n value=\"inherit\"\n checked={mode === 'inherit'}\n onChange={() => onModeChange('inherit')}\n />\n {t('auth.users.widgets.mode.inherit', 'Inherit from roles')}\n </label>\n <label className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"radio\"\n value=\"override\"\n checked={mode === 'override'}\n onChange={() => onModeChange('override')}\n />\n {t('auth.users.widgets.mode.override', 'Override for this user')}\n </label>\n </div>\n {mode === 'override' && (\n <div className=\"space-y-2\">\n {catalog.map((widget) => (\n <label key={widget.id} className=\"flex items-start gap-3 rounded-md border px-3 py-2 hover:border-primary/40\">\n <input\n type=\"checkbox\"\n className=\"mt-1 size-4\"\n checked={selected.includes(widget.id)}\n onChange={() => onToggle(widget.id)}\n />\n <div>\n <div className=\"text-sm font-medium leading-none\">{widget.title}</div>\n {widget.description ? <div className=\"text-xs text-muted-foreground\">{widget.description}</div> : null}\n </div>\n </label>\n ))}\n </div>\n )}\n {mode === 'inherit' && (\n <div className=\"rounded-md border bg-muted/20 px-3 py-2 text-xs text-muted-foreground\">\n {t('auth.users.widgets.mode.hint', 'New users inherit widgets from their assigned roles. Override to pick a custom set.')}\n </div>\n )}\n </>\n )}\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -334,9 +334,9 @@ function UsersListPage() {
|
|
|
334
334
|
onSortingChange: setSorting,
|
|
335
335
|
perspective: { tableId: "auth.users.list" },
|
|
336
336
|
rowActions: (row) => /* @__PURE__ */ jsx(RowActions, { items: [
|
|
337
|
-
{
|
|
338
|
-
{
|
|
339
|
-
{
|
|
337
|
+
{ label: t("common.edit", "Edit"), href: `/backend/users/${row.id}/edit` },
|
|
338
|
+
{ label: t("auth.users.list.actions.showRoles", "Show roles"), href: `/backend/roles?userId=${encodeURIComponent(row.id)}` },
|
|
339
|
+
{ label: t("common.delete", "Delete"), destructive: true, onSelect: () => {
|
|
340
340
|
void handleDelete(row);
|
|
341
341
|
} }
|
|
342
342
|
] }),
|