@open-mercato/core 0.4.7-develop-0a657b411f → 0.4.7-develop-e249d3e7d0
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/carrier_shipment/index.js +37 -0
- package/dist/generated/entities/carrier_shipment/index.js.map +7 -0
- package/dist/generated/entities/gateway_transaction/index.js +47 -0
- package/dist/generated/entities/gateway_transaction/index.js.map +7 -0
- package/dist/generated/entities/webhook_processed_event/index.js +17 -0
- package/dist/generated/entities/webhook_processed_event/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +10 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +6 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/data_sync/api/runs/[id]/cancel.js +14 -5
- package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.meta.js +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.meta.js.map +1 -1
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +37 -12
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +2 -2
- package/dist/modules/directory/api/get/tenants/lookup.js +1 -0
- package/dist/modules/directory/api/get/tenants/lookup.js.map +2 -2
- package/dist/modules/integrations/api/[id]/route.js +38 -11
- package/dist/modules/integrations/api/[id]/route.js.map +2 -2
- package/dist/modules/integrations/api/logs/route.js +52 -26
- package/dist/modules/integrations/api/logs/route.js.map +2 -2
- package/dist/modules/integrations/api/route.js +37 -7
- package/dist/modules/integrations/api/route.js.map +2 -2
- package/dist/modules/integrations/api/umes-read.js +121 -0
- package/dist/modules/integrations/api/umes-read.js.map +7 -0
- package/dist/modules/integrations/backend/integrations/[id]/page.js +715 -183
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +30 -9
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/detail-page-widgets.js +46 -0
- package/dist/modules/integrations/backend/integrations/detail-page-widgets.js.map +7 -0
- package/dist/modules/integrations/backend/integrations/page.js +78 -62
- package/dist/modules/integrations/backend/integrations/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/page.meta.js +2 -2
- package/dist/modules/integrations/backend/integrations/page.meta.js.map +1 -1
- package/dist/modules/integrations/setup.js +2 -2
- package/dist/modules/integrations/setup.js.map +2 -2
- package/dist/modules/payment_gateways/acl.js +12 -0
- package/dist/modules/payment_gateways/acl.js.map +7 -0
- package/dist/modules/payment_gateways/api/cancel/route.js +55 -0
- package/dist/modules/payment_gateways/api/cancel/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/capture/route.js +55 -0
- package/dist/modules/payment_gateways/api/capture/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/interceptors.js +24 -0
- package/dist/modules/payment_gateways/api/interceptors.js.map +7 -0
- package/dist/modules/payment_gateways/api/openapi.js +5 -0
- package/dist/modules/payment_gateways/api/openapi.js.map +7 -0
- package/dist/modules/payment_gateways/api/refund/route.js +56 -0
- package/dist/modules/payment_gateways/api/refund/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/sessions/route.js +74 -0
- package/dist/modules/payment_gateways/api/sessions/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/status/route.js +66 -0
- package/dist/modules/payment_gateways/api/status/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/transactions/[id]/route.js +118 -0
- package/dist/modules/payment_gateways/api/transactions/[id]/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/transactions/route.js +113 -0
- package/dist/modules/payment_gateways/api/transactions/route.js.map +7 -0
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +136 -0
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +7 -0
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js +496 -0
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +7 -0
- package/dist/modules/payment_gateways/backend/payment-gateways/page.meta.js +23 -0
- package/dist/modules/payment_gateways/backend/payment-gateways/page.meta.js.map +7 -0
- package/dist/modules/payment_gateways/data/enrichers.js +5 -0
- package/dist/modules/payment_gateways/data/enrichers.js.map +7 -0
- package/dist/modules/payment_gateways/data/entities.js +131 -0
- package/dist/modules/payment_gateways/data/entities.js.map +7 -0
- package/dist/modules/payment_gateways/data/validators.js +57 -0
- package/dist/modules/payment_gateways/data/validators.js.map +7 -0
- package/dist/modules/payment_gateways/di.js +16 -0
- package/dist/modules/payment_gateways/di.js.map +7 -0
- package/dist/modules/payment_gateways/events.js +21 -0
- package/dist/modules/payment_gateways/events.js.map +7 -0
- package/dist/modules/payment_gateways/i18n/en.js +6 -0
- package/dist/modules/payment_gateways/i18n/en.js.map +7 -0
- package/dist/modules/payment_gateways/i18n/pl.js +6 -0
- package/dist/modules/payment_gateways/i18n/pl.js.map +7 -0
- package/dist/modules/payment_gateways/index.js +9 -0
- package/dist/modules/payment_gateways/index.js.map +7 -0
- package/dist/modules/payment_gateways/lib/gateway-service.js +378 -0
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +7 -0
- package/dist/modules/payment_gateways/lib/queue.js +17 -0
- package/dist/modules/payment_gateways/lib/queue.js.map +7 -0
- package/dist/modules/payment_gateways/lib/status-machine.js +29 -0
- package/dist/modules/payment_gateways/lib/status-machine.js.map +7 -0
- package/dist/modules/payment_gateways/lib/webhook-processor.js +88 -0
- package/dist/modules/payment_gateways/lib/webhook-processor.js.map +7 -0
- package/dist/modules/payment_gateways/lib/webhook-utils.js +42 -0
- package/dist/modules/payment_gateways/lib/webhook-utils.js.map +7 -0
- package/dist/modules/payment_gateways/migrations/Migration20260305122155.js +19 -0
- package/dist/modules/payment_gateways/migrations/Migration20260305122155.js.map +7 -0
- package/dist/modules/payment_gateways/setup.js +13 -0
- package/dist/modules/payment_gateways/setup.js.map +7 -0
- package/dist/modules/payment_gateways/widgets/injection-table.js +7 -0
- package/dist/modules/payment_gateways/widgets/injection-table.js.map +7 -0
- package/dist/modules/payment_gateways/workers/status-poller.js +44 -0
- package/dist/modules/payment_gateways/workers/status-poller.js.map +7 -0
- package/dist/modules/payment_gateways/workers/webhook-processor.js +20 -0
- package/dist/modules/payment_gateways/workers/webhook-processor.js.map +7 -0
- package/dist/modules/sales/data/enrichers.js +72 -0
- package/dist/modules/sales/data/enrichers.js.map +7 -0
- package/dist/modules/sales/lib/makeSalesLineRoute.js +3 -0
- package/dist/modules/sales/lib/makeSalesLineRoute.js.map +2 -2
- package/dist/modules/sales/widgets/injection/payment-gateway-config-field/widget.js +29 -0
- package/dist/modules/sales/widgets/injection/payment-gateway-config-field/widget.js.map +7 -0
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js +23 -0
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js.map +7 -0
- package/dist/modules/sales/widgets/injection-table.js +13 -1
- package/dist/modules/sales/widgets/injection-table.js.map +2 -2
- package/dist/modules/shipping_carriers/acl.js +10 -0
- package/dist/modules/shipping_carriers/acl.js.map +7 -0
- package/dist/modules/shipping_carriers/api/cancel/route.js +55 -0
- package/dist/modules/shipping_carriers/api/cancel/route.js.map +7 -0
- package/dist/modules/shipping_carriers/api/interceptors.js +21 -0
- package/dist/modules/shipping_carriers/api/interceptors.js.map +7 -0
- package/dist/modules/shipping_carriers/api/openapi.js +5 -0
- package/dist/modules/shipping_carriers/api/openapi.js.map +7 -0
- package/dist/modules/shipping_carriers/api/rates/route.js +55 -0
- package/dist/modules/shipping_carriers/api/rates/route.js.map +7 -0
- package/dist/modules/shipping_carriers/api/shipments/route.js +61 -0
- package/dist/modules/shipping_carriers/api/shipments/route.js.map +7 -0
- package/dist/modules/shipping_carriers/api/tracking/route.js +58 -0
- package/dist/modules/shipping_carriers/api/tracking/route.js.map +7 -0
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +119 -0
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +7 -0
- package/dist/modules/shipping_carriers/data/enrichers.js +82 -0
- package/dist/modules/shipping_carriers/data/enrichers.js.map +7 -0
- package/dist/modules/shipping_carriers/data/entities.js +80 -0
- package/dist/modules/shipping_carriers/data/entities.js.map +7 -0
- package/dist/modules/shipping_carriers/data/validators.js +49 -0
- package/dist/modules/shipping_carriers/data/validators.js.map +7 -0
- package/dist/modules/shipping_carriers/di.js +15 -0
- package/dist/modules/shipping_carriers/di.js.map +7 -0
- package/dist/modules/shipping_carriers/events.js +19 -0
- package/dist/modules/shipping_carriers/events.js.map +7 -0
- package/dist/modules/shipping_carriers/i18n/en.js +11 -0
- package/dist/modules/shipping_carriers/i18n/en.js.map +7 -0
- package/dist/modules/shipping_carriers/i18n/pl.js +11 -0
- package/dist/modules/shipping_carriers/i18n/pl.js.map +7 -0
- package/dist/modules/shipping_carriers/index.js +9 -0
- package/dist/modules/shipping_carriers/index.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/adapter-registry.js +29 -0
- package/dist/modules/shipping_carriers/lib/adapter-registry.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/adapter.js +1 -0
- package/dist/modules/shipping_carriers/lib/adapter.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/queue.js +17 -0
- package/dist/modules/shipping_carriers/lib/queue.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/shipping-service.js +155 -0
- package/dist/modules/shipping_carriers/lib/shipping-service.js.map +7 -0
- package/dist/modules/shipping_carriers/lib/status-sync.js +37 -0
- package/dist/modules/shipping_carriers/lib/status-sync.js.map +7 -0
- package/dist/modules/shipping_carriers/migrations/Migration20260305170000.js +16 -0
- package/dist/modules/shipping_carriers/migrations/Migration20260305170000.js.map +7 -0
- package/dist/modules/shipping_carriers/setup.js +13 -0
- package/dist/modules/shipping_carriers/setup.js.map +7 -0
- package/dist/modules/shipping_carriers/widgets/injection/create-shipment-button/widget.js +25 -0
- package/dist/modules/shipping_carriers/widgets/injection/create-shipment-button/widget.js.map +7 -0
- package/dist/modules/shipping_carriers/widgets/injection/tracking-column/widget.js +23 -0
- package/dist/modules/shipping_carriers/widgets/injection/tracking-column/widget.js.map +7 -0
- package/dist/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.js +40 -0
- package/dist/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.js.map +7 -0
- package/dist/modules/shipping_carriers/widgets/injection-table.js +24 -0
- package/dist/modules/shipping_carriers/widgets/injection-table.js.map +7 -0
- package/dist/modules/shipping_carriers/workers/status-poller.js +21 -0
- package/dist/modules/shipping_carriers/workers/status-poller.js.map +7 -0
- package/dist/modules/shipping_carriers/workers/webhook-processor.js +54 -0
- package/dist/modules/shipping_carriers/workers/webhook-processor.js.map +7 -0
- package/dist/modules/translations/api/get/locales.js +1 -0
- package/dist/modules/translations/api/get/locales.js.map +2 -2
- package/dist/modules/translations/api/put/locales.js +1 -0
- package/dist/modules/translations/api/put/locales.js.map +2 -2
- package/generated/entities/carrier_shipment/index.ts +17 -0
- package/generated/entities/gateway_transaction/index.ts +22 -0
- package/generated/entities/webhook_processed_event/index.ts +7 -0
- package/generated/entities.ids.generated.ts +10 -1
- package/generated/entity-fields-registry.ts +6 -0
- package/jest.config.cjs +1 -0
- package/package.json +5 -2
- package/src/modules/auth/i18n/de.json +1 -0
- package/src/modules/auth/i18n/en.json +1 -0
- package/src/modules/auth/i18n/es.json +1 -0
- package/src/modules/auth/i18n/pl.json +1 -0
- package/src/modules/data_sync/api/runs/[id]/cancel.ts +18 -5
- package/src/modules/data_sync/backend/data-sync/page.meta.ts +2 -2
- package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +50 -12
- package/src/modules/directory/api/get/tenants/lookup.ts +1 -0
- package/src/modules/integrations/AGENTS.md +31 -0
- package/src/modules/integrations/api/[id]/route.ts +38 -11
- package/src/modules/integrations/api/logs/route.ts +53 -27
- package/src/modules/integrations/api/route.ts +31 -1
- package/src/modules/integrations/api/umes-read.ts +177 -0
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +902 -202
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +43 -9
- package/src/modules/integrations/backend/integrations/detail-page-widgets.ts +74 -0
- package/src/modules/integrations/backend/integrations/page.meta.ts +2 -2
- package/src/modules/integrations/backend/integrations/page.tsx +65 -54
- package/src/modules/integrations/i18n/de.json +15 -0
- package/src/modules/integrations/i18n/en.json +15 -0
- package/src/modules/integrations/i18n/es.json +15 -0
- package/src/modules/integrations/i18n/pl.json +15 -0
- package/src/modules/integrations/setup.ts +2 -2
- package/src/modules/payment_gateways/acl.ts +8 -0
- package/src/modules/payment_gateways/api/cancel/route.ts +56 -0
- package/src/modules/payment_gateways/api/capture/route.ts +56 -0
- package/src/modules/payment_gateways/api/interceptors.ts +22 -0
- package/src/modules/payment_gateways/api/openapi.ts +1 -0
- package/src/modules/payment_gateways/api/refund/route.ts +57 -0
- package/src/modules/payment_gateways/api/sessions/route.ts +76 -0
- package/src/modules/payment_gateways/api/status/route.ts +69 -0
- package/src/modules/payment_gateways/api/transactions/[id]/route.ts +123 -0
- package/src/modules/payment_gateways/api/transactions/route.ts +120 -0
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +161 -0
- package/src/modules/payment_gateways/backend/payment-gateways/page.meta.ts +19 -0
- package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +660 -0
- package/src/modules/payment_gateways/data/enrichers.ts +8 -0
- package/src/modules/payment_gateways/data/entities.ts +106 -0
- package/src/modules/payment_gateways/data/validators.ts +67 -0
- package/src/modules/payment_gateways/di.ts +26 -0
- package/src/modules/payment_gateways/events.ts +17 -0
- package/src/modules/payment_gateways/i18n/de.json +77 -0
- package/src/modules/payment_gateways/i18n/en.json +77 -0
- package/src/modules/payment_gateways/i18n/en.ts +4 -0
- package/src/modules/payment_gateways/i18n/es.json +77 -0
- package/src/modules/payment_gateways/i18n/pl.json +77 -0
- package/src/modules/payment_gateways/i18n/pl.ts +4 -0
- package/src/modules/payment_gateways/index.ts +5 -0
- package/src/modules/payment_gateways/lib/gateway-service.ts +486 -0
- package/src/modules/payment_gateways/lib/queue.ts +19 -0
- package/src/modules/payment_gateways/lib/status-machine.ts +28 -0
- package/src/modules/payment_gateways/lib/webhook-processor.ts +133 -0
- package/src/modules/payment_gateways/lib/webhook-utils.ts +52 -0
- package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +373 -0
- package/src/modules/payment_gateways/migrations/Migration20260305122155.ts +20 -0
- package/src/modules/payment_gateways/setup.ts +11 -0
- package/src/modules/payment_gateways/widgets/injection-table.ts +9 -0
- package/src/modules/payment_gateways/workers/status-poller.ts +58 -0
- package/src/modules/payment_gateways/workers/webhook-processor.ts +30 -0
- package/src/modules/sales/data/enrichers.ts +120 -0
- package/src/modules/sales/lib/makeSalesLineRoute.ts +3 -0
- package/src/modules/sales/widgets/injection/payment-gateway-config-field/widget.ts +28 -0
- package/src/modules/sales/widgets/injection/payment-gateway-status-column/widget.ts +22 -0
- package/src/modules/sales/widgets/injection-table.ts +12 -0
- package/src/modules/shipping_carriers/acl.ts +6 -0
- package/src/modules/shipping_carriers/api/cancel/route.ts +53 -0
- package/src/modules/shipping_carriers/api/interceptors.ts +19 -0
- package/src/modules/shipping_carriers/api/openapi.ts +1 -0
- package/src/modules/shipping_carriers/api/rates/route.ts +53 -0
- package/src/modules/shipping_carriers/api/shipments/route.ts +59 -0
- package/src/modules/shipping_carriers/api/tracking/route.ts +56 -0
- package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +134 -0
- package/src/modules/shipping_carriers/data/enrichers.ts +89 -0
- package/src/modules/shipping_carriers/data/entities.ts +60 -0
- package/src/modules/shipping_carriers/data/validators.ts +48 -0
- package/src/modules/shipping_carriers/di.ts +20 -0
- package/src/modules/shipping_carriers/events.ts +16 -0
- package/src/modules/shipping_carriers/i18n/de.json +7 -0
- package/src/modules/shipping_carriers/i18n/en.json +7 -0
- package/src/modules/shipping_carriers/i18n/en.ts +7 -0
- package/src/modules/shipping_carriers/i18n/es.json +7 -0
- package/src/modules/shipping_carriers/i18n/pl.json +7 -0
- package/src/modules/shipping_carriers/i18n/pl.ts +7 -0
- package/src/modules/shipping_carriers/index.ts +5 -0
- package/src/modules/shipping_carriers/lib/adapter-registry.ts +33 -0
- package/src/modules/shipping_carriers/lib/adapter.ts +93 -0
- package/src/modules/shipping_carriers/lib/queue.ts +19 -0
- package/src/modules/shipping_carriers/lib/shipping-service.ts +204 -0
- package/src/modules/shipping_carriers/lib/status-sync.ts +38 -0
- package/src/modules/shipping_carriers/migrations/Migration20260305170000.ts +14 -0
- package/src/modules/shipping_carriers/setup.ts +11 -0
- package/src/modules/shipping_carriers/widgets/injection/create-shipment-button/widget.ts +24 -0
- package/src/modules/shipping_carriers/widgets/injection/tracking-column/widget.ts +22 -0
- package/src/modules/shipping_carriers/widgets/injection/tracking-status-badge/widget.tsx +44 -0
- package/src/modules/shipping_carriers/widgets/injection-table.ts +22 -0
- package/src/modules/shipping_carriers/workers/status-poller.ts +33 -0
- package/src/modules/shipping_carriers/workers/webhook-processor.ts +79 -0
- package/src/modules/translations/api/get/locales.ts +1 -0
- package/src/modules/translations/api/put/locales.ts +1 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
import * as React from 'react'
|
|
3
3
|
import Link from 'next/link'
|
|
4
|
-
import {
|
|
4
|
+
import { usePathname } from 'next/navigation'
|
|
5
5
|
import { Page, PageBody } from '@open-mercato/ui/backend/Page'
|
|
6
6
|
import { Card, CardHeader, CardTitle, CardContent } from '@open-mercato/ui/primitives/card'
|
|
7
7
|
import { Badge } from '@open-mercato/ui/primitives/badge'
|
|
@@ -50,9 +50,27 @@ type BundleDetail = {
|
|
|
50
50
|
hasCredentials: boolean
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
type BundleConfigPageProps = {
|
|
54
|
+
params?: {
|
|
55
|
+
id?: string | string[]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function resolveRouteId(value: string | string[] | undefined): string | undefined {
|
|
60
|
+
if (Array.isArray(value)) return value[0]
|
|
61
|
+
return value
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function resolvePathnameId(pathname: string): string | undefined {
|
|
65
|
+
const parts = pathname.split('/').filter(Boolean)
|
|
66
|
+
const bundleId = parts.at(-1)
|
|
67
|
+
if (!bundleId || bundleId === 'bundle' || bundleId === 'integrations') return undefined
|
|
68
|
+
return decodeURIComponent(bundleId)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export default function BundleConfigPage({ params }: BundleConfigPageProps) {
|
|
72
|
+
const pathname = usePathname()
|
|
73
|
+
const bundleId = resolveRouteId(params?.id) ?? resolvePathnameId(pathname)
|
|
56
74
|
const t = useT()
|
|
57
75
|
|
|
58
76
|
const [detail, setDetail] = React.useState<BundleDetail | null>(null)
|
|
@@ -62,11 +80,25 @@ export default function BundleConfigPage() {
|
|
|
62
80
|
const [isSavingCreds, setIsSavingCreds] = React.useState(false)
|
|
63
81
|
const [togglingIds, setTogglingIds] = React.useState<Set<string>>(new Set())
|
|
64
82
|
|
|
83
|
+
const resolveCurrentBundleId = React.useCallback(() => {
|
|
84
|
+
return bundleId ?? (
|
|
85
|
+
typeof window !== 'undefined'
|
|
86
|
+
? resolvePathnameId(window.location.pathname)
|
|
87
|
+
: undefined
|
|
88
|
+
)
|
|
89
|
+
}, [bundleId])
|
|
90
|
+
|
|
65
91
|
const load = React.useCallback(async () => {
|
|
92
|
+
const currentBundleId = resolveCurrentBundleId()
|
|
93
|
+
if (!currentBundleId) {
|
|
94
|
+
setError(t('integrations.detail.loadError'))
|
|
95
|
+
setIsLoading(false)
|
|
96
|
+
return
|
|
97
|
+
}
|
|
66
98
|
setIsLoading(true)
|
|
67
99
|
setError(null)
|
|
68
100
|
const call = await apiCall<BundleDetail>(
|
|
69
|
-
`/api/integrations/${encodeURIComponent(
|
|
101
|
+
`/api/integrations/${encodeURIComponent(currentBundleId)}`,
|
|
70
102
|
undefined,
|
|
71
103
|
{ fallback: null },
|
|
72
104
|
)
|
|
@@ -78,7 +110,7 @@ export default function BundleConfigPage() {
|
|
|
78
110
|
setDetail(call.result)
|
|
79
111
|
|
|
80
112
|
const credCall = await apiCall<{ credentials: Record<string, unknown> }>(
|
|
81
|
-
`/api/integrations/${encodeURIComponent(
|
|
113
|
+
`/api/integrations/${encodeURIComponent(currentBundleId)}/credentials`,
|
|
82
114
|
undefined,
|
|
83
115
|
{ fallback: null },
|
|
84
116
|
)
|
|
@@ -86,13 +118,15 @@ export default function BundleConfigPage() {
|
|
|
86
118
|
setCredValues(credCall.result.credentials)
|
|
87
119
|
}
|
|
88
120
|
setIsLoading(false)
|
|
89
|
-
}, [
|
|
121
|
+
}, [resolveCurrentBundleId, t])
|
|
90
122
|
|
|
91
123
|
React.useEffect(() => { void load() }, [load])
|
|
92
124
|
|
|
93
125
|
const handleSaveCredentials = React.useCallback(async () => {
|
|
126
|
+
const currentBundleId = resolveCurrentBundleId()
|
|
127
|
+
if (!currentBundleId) return
|
|
94
128
|
setIsSavingCreds(true)
|
|
95
|
-
const call = await apiCall(`/api/integrations/${encodeURIComponent(
|
|
129
|
+
const call = await apiCall(`/api/integrations/${encodeURIComponent(currentBundleId)}/credentials`, {
|
|
96
130
|
method: 'PUT',
|
|
97
131
|
headers: { 'Content-Type': 'application/json' },
|
|
98
132
|
body: JSON.stringify({ credentials: credValues }),
|
|
@@ -103,7 +137,7 @@ export default function BundleConfigPage() {
|
|
|
103
137
|
flash(t('integrations.detail.credentials.saveError'), 'error')
|
|
104
138
|
}
|
|
105
139
|
setIsSavingCreds(false)
|
|
106
|
-
}, [
|
|
140
|
+
}, [resolveCurrentBundleId, credValues, t])
|
|
107
141
|
|
|
108
142
|
const handleToggle = React.useCallback(async (integrationId: string, enabled: boolean) => {
|
|
109
143
|
setTogglingIds((prev) => new Set(prev).add(integrationId))
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { type IntegrationDefinition, LEGACY_INTEGRATION_DETAIL_TABS_SPOT_ID } from '@open-mercato/shared/modules/integrations/types'
|
|
2
|
+
import type { LoadedInjectionSpotWidget } from '@open-mercato/ui/backend/injection/InjectionSpot'
|
|
3
|
+
|
|
4
|
+
type IntegrationDetailPlacementKind = 'tab' | 'group' | 'stack'
|
|
5
|
+
|
|
6
|
+
export type IntegrationDetailInjectedTab = {
|
|
7
|
+
id: string
|
|
8
|
+
label: string
|
|
9
|
+
priority: number
|
|
10
|
+
widgets: LoadedInjectionSpotWidget[]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function resolveIntegrationDetailWidgetSpotId(
|
|
14
|
+
integration: Pick<IntegrationDefinition, 'detailPage'> | null | undefined,
|
|
15
|
+
legacySpotId: typeof LEGACY_INTEGRATION_DETAIL_TABS_SPOT_ID,
|
|
16
|
+
): string {
|
|
17
|
+
const widgetSpotId = integration?.detailPage?.widgetSpotId?.trim()
|
|
18
|
+
return widgetSpotId && widgetSpotId.length > 0 ? widgetSpotId : legacySpotId
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function resolveRequestedIntegrationDetailTab(
|
|
22
|
+
value: string | null | undefined,
|
|
23
|
+
hasVersions: boolean,
|
|
24
|
+
customTabIds: readonly string[],
|
|
25
|
+
): string {
|
|
26
|
+
if (value && customTabIds.includes(value)) return value
|
|
27
|
+
if (value === 'health' || value === 'logs') return value
|
|
28
|
+
if (value === 'version' && hasVersions) return 'version'
|
|
29
|
+
return 'credentials'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function filterIntegrationDetailWidgetsByKind(
|
|
33
|
+
widgets: readonly LoadedInjectionSpotWidget[],
|
|
34
|
+
kind: IntegrationDetailPlacementKind,
|
|
35
|
+
): LoadedInjectionSpotWidget[] {
|
|
36
|
+
return widgets
|
|
37
|
+
.filter((widget) => (widget.placement?.kind ?? 'stack') === kind)
|
|
38
|
+
.sort((left, right) => {
|
|
39
|
+
const leftPriority = typeof left.placement?.priority === 'number' ? left.placement.priority : 0
|
|
40
|
+
const rightPriority = typeof right.placement?.priority === 'number' ? right.placement.priority : 0
|
|
41
|
+
return rightPriority - leftPriority
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function buildIntegrationDetailInjectedTabs(
|
|
46
|
+
widgets: readonly LoadedInjectionSpotWidget[],
|
|
47
|
+
resolveLabel: (widget: LoadedInjectionSpotWidget) => string,
|
|
48
|
+
): IntegrationDetailInjectedTab[] {
|
|
49
|
+
const groupedTabs = new Map<string, IntegrationDetailInjectedTab>()
|
|
50
|
+
|
|
51
|
+
for (const widget of widgets) {
|
|
52
|
+
if ((widget.placement?.kind ?? 'stack') !== 'tab') continue
|
|
53
|
+
|
|
54
|
+
const id = widget.placement?.groupId ?? widget.widgetId
|
|
55
|
+
const label = resolveLabel(widget)
|
|
56
|
+
const priority = typeof widget.placement?.priority === 'number' ? widget.placement.priority : 0
|
|
57
|
+
const existing = groupedTabs.get(id)
|
|
58
|
+
|
|
59
|
+
if (existing) {
|
|
60
|
+
existing.widgets.push(widget)
|
|
61
|
+
existing.priority = Math.max(existing.priority, priority)
|
|
62
|
+
continue
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
groupedTabs.set(id, {
|
|
66
|
+
id,
|
|
67
|
+
label,
|
|
68
|
+
priority,
|
|
69
|
+
widgets: [widget],
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return Array.from(groupedTabs.values()).sort((left, right) => right.priority - left.priority)
|
|
74
|
+
}
|
|
@@ -9,8 +9,8 @@ export const metadata = {
|
|
|
9
9
|
requireFeatures: ['integrations.view'],
|
|
10
10
|
pageTitle: 'Integrations',
|
|
11
11
|
pageTitleKey: 'integrations.nav.title',
|
|
12
|
-
pageGroup: '
|
|
13
|
-
pageGroupKey: '
|
|
12
|
+
pageGroup: 'External systems',
|
|
13
|
+
pageGroupKey: 'backend.nav.externalSystems',
|
|
14
14
|
pageOrder: 50,
|
|
15
15
|
icon: puzzleIcon,
|
|
16
16
|
pageContext: 'settings' as const,
|
|
@@ -3,7 +3,6 @@ import * as React from 'react'
|
|
|
3
3
|
import Link from 'next/link'
|
|
4
4
|
import { Page, PageBody } from '@open-mercato/ui/backend/Page'
|
|
5
5
|
import { Card, CardHeader, CardTitle, CardContent } from '@open-mercato/ui/primitives/card'
|
|
6
|
-
import { Badge } from '@open-mercato/ui/primitives/badge'
|
|
7
6
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
8
7
|
import { Switch } from '@open-mercato/ui/primitives/switch'
|
|
9
8
|
import { Input } from '@open-mercato/ui/primitives/input'
|
|
@@ -13,7 +12,7 @@ import { flash } from '@open-mercato/ui/backend/FlashMessages'
|
|
|
13
12
|
import { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
|
|
14
13
|
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
15
14
|
import { FilterBar, type FilterValues } from '@open-mercato/ui/backend/FilterBar'
|
|
16
|
-
import { Bell, CreditCard, HardDrive, LayoutGrid, MessageSquare, RefreshCw, Truck, Webhook } from 'lucide-react'
|
|
15
|
+
import { Bell, Cog, CreditCard, HardDrive, LayoutGrid, MessageSquare, RefreshCw, Search, Truck, Webhook } from 'lucide-react'
|
|
17
16
|
import {
|
|
18
17
|
buildIntegrationMarketplaceFilterDefs,
|
|
19
18
|
getIntegrationMarketplaceCategory,
|
|
@@ -28,6 +27,9 @@ type IntegrationItem = {
|
|
|
28
27
|
category?: string
|
|
29
28
|
icon?: string
|
|
30
29
|
bundleId?: string
|
|
30
|
+
author?: string
|
|
31
|
+
company?: string
|
|
32
|
+
version?: string
|
|
31
33
|
isEnabled: boolean
|
|
32
34
|
hasCredentials: boolean
|
|
33
35
|
}
|
|
@@ -57,11 +59,6 @@ const CATEGORY_ICONS: Record<string, React.ElementType> = {
|
|
|
57
59
|
webhook: Webhook,
|
|
58
60
|
}
|
|
59
61
|
|
|
60
|
-
function categoryBadgeVariant(category: string | undefined): 'default' | 'secondary' | 'outline' {
|
|
61
|
-
if (!category) return 'outline'
|
|
62
|
-
return 'secondary'
|
|
63
|
-
}
|
|
64
|
-
|
|
65
62
|
export default function IntegrationsMarketplacePage() {
|
|
66
63
|
const [data, setData] = React.useState<ListResponse | null>(null)
|
|
67
64
|
const [isLoading, setIsLoading] = React.useState(true)
|
|
@@ -144,6 +141,13 @@ export default function IntegrationsMarketplacePage() {
|
|
|
144
141
|
return { bundles, standalone }
|
|
145
142
|
}, [data, search, selectedCategory])
|
|
146
143
|
|
|
144
|
+
const renderCategoryIcon = React.useCallback((category: string | undefined, className: string) => {
|
|
145
|
+
if (!category) return null
|
|
146
|
+
const Icon = CATEGORY_ICONS[category]
|
|
147
|
+
if (!Icon) return null
|
|
148
|
+
return <Icon className={className} />
|
|
149
|
+
}, [])
|
|
150
|
+
|
|
147
151
|
if (isLoading) {
|
|
148
152
|
return (
|
|
149
153
|
<Page>
|
|
@@ -160,13 +164,22 @@ export default function IntegrationsMarketplacePage() {
|
|
|
160
164
|
<Page>
|
|
161
165
|
<PageBody className="space-y-6">
|
|
162
166
|
<section className="space-y-6 rounded-lg border bg-background p-6">
|
|
163
|
-
<header className="flex
|
|
164
|
-
<div className="space-y-
|
|
167
|
+
<header className="flex items-center justify-between gap-4">
|
|
168
|
+
<div className="space-y-0.5">
|
|
165
169
|
<h2 className="text-lg font-semibold">{t('integrations.marketplace.title')}</h2>
|
|
166
170
|
<p className="text-sm text-muted-foreground">
|
|
167
171
|
{t('integrations.marketplace.description')}
|
|
168
172
|
</p>
|
|
169
173
|
</div>
|
|
174
|
+
<div className="relative w-64 shrink-0 hidden lg:block">
|
|
175
|
+
<Search className="absolute left-2.5 top-1/2 -translate-y-1/2 size-4 text-muted-foreground pointer-events-none" />
|
|
176
|
+
<Input
|
|
177
|
+
placeholder={t('integrations.marketplace.search')}
|
|
178
|
+
value={search}
|
|
179
|
+
onChange={(e) => setSearch(e.target.value)}
|
|
180
|
+
className="pl-8"
|
|
181
|
+
/>
|
|
182
|
+
</div>
|
|
170
183
|
</header>
|
|
171
184
|
|
|
172
185
|
<div className="lg:hidden">
|
|
@@ -182,32 +195,22 @@ export default function IntegrationsMarketplacePage() {
|
|
|
182
195
|
/>
|
|
183
196
|
</div>
|
|
184
197
|
|
|
185
|
-
<div className="hidden lg:flex
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
size="sm"
|
|
202
|
-
onClick={() => setFilterValues(normalizeIntegrationMarketplaceFilterValues({ category }))}
|
|
203
|
-
>
|
|
204
|
-
{Icon ? <Icon className="mr-1.5 h-3.5 w-3.5" /> : null}
|
|
205
|
-
{t(`integrations.marketplace.categories.${category}`)}
|
|
206
|
-
</Button>
|
|
207
|
-
)
|
|
208
|
-
})}
|
|
209
|
-
</div>
|
|
210
|
-
</div>
|
|
198
|
+
<div className="hidden lg:flex flex-wrap gap-1.5">
|
|
199
|
+
{INTEGRATION_MARKETPLACE_CATEGORIES.map((category) => {
|
|
200
|
+
const Icon = CATEGORY_ICONS[category]
|
|
201
|
+
return (
|
|
202
|
+
<Button
|
|
203
|
+
key={category}
|
|
204
|
+
type="button"
|
|
205
|
+
variant={selectedCategory === category ? 'default' : 'outline'}
|
|
206
|
+
size="sm"
|
|
207
|
+
onClick={() => setFilterValues(normalizeIntegrationMarketplaceFilterValues({ category }))}
|
|
208
|
+
>
|
|
209
|
+
{Icon ? <Icon className="mr-1.5 h-3.5 w-3.5" /> : null}
|
|
210
|
+
{t(`integrations.marketplace.categories.${category}`)}
|
|
211
|
+
</Button>
|
|
212
|
+
)
|
|
213
|
+
})}
|
|
211
214
|
</div>
|
|
212
215
|
|
|
213
216
|
{filteredItems.bundles.map((bundle) => (
|
|
@@ -225,6 +228,7 @@ export default function IntegrationsMarketplacePage() {
|
|
|
225
228
|
</div>
|
|
226
229
|
<Button asChild variant="outline" size="sm">
|
|
227
230
|
<Link href={`/backend/integrations/bundle/${encodeURIComponent(bundle.id)}`}>
|
|
231
|
+
<Cog className="mr-1.5 h-4 w-4" />
|
|
228
232
|
{t('integrations.marketplace.configure')}
|
|
229
233
|
</Link>
|
|
230
234
|
</Button>
|
|
@@ -237,18 +241,21 @@ export default function IntegrationsMarketplacePage() {
|
|
|
237
241
|
key={item.id}
|
|
238
242
|
className="flex items-center justify-between rounded-lg border p-3"
|
|
239
243
|
>
|
|
240
|
-
<div className="min-w-0">
|
|
241
|
-
<
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
244
|
+
<div className="min-w-0 space-y-1">
|
|
245
|
+
<div className="flex items-center gap-2">
|
|
246
|
+
{renderCategoryIcon(item.category, 'h-4 w-4 text-muted-foreground')}
|
|
247
|
+
<Link
|
|
248
|
+
href={`/backend/integrations/${encodeURIComponent(item.id)}`}
|
|
249
|
+
className="truncate text-sm font-medium hover:underline"
|
|
250
|
+
>
|
|
251
|
+
{item.title}
|
|
252
|
+
</Link>
|
|
253
|
+
</div>
|
|
254
|
+
{(item.company || item.author || item.version) ? (
|
|
255
|
+
<p className="text-xs text-muted-foreground">
|
|
256
|
+
{[item.company || item.author, item.version ? `v${item.version}` : null].filter(Boolean).join(' · ')}
|
|
257
|
+
</p>
|
|
258
|
+
) : null}
|
|
252
259
|
</div>
|
|
253
260
|
<Switch
|
|
254
261
|
checked={item.isEnabled}
|
|
@@ -268,27 +275,31 @@ export default function IntegrationsMarketplacePage() {
|
|
|
268
275
|
<Card key={item.id} className="flex flex-col">
|
|
269
276
|
<CardHeader>
|
|
270
277
|
<div className="flex items-center justify-between">
|
|
271
|
-
<
|
|
278
|
+
<div className="flex items-center gap-2">
|
|
279
|
+
{renderCategoryIcon(item.category, 'h-4 w-4 text-muted-foreground')}
|
|
280
|
+
<CardTitle className="text-base">{item.title}</CardTitle>
|
|
281
|
+
</div>
|
|
272
282
|
<Switch
|
|
273
283
|
checked={item.isEnabled}
|
|
274
284
|
disabled={togglingIds.has(item.id)}
|
|
275
285
|
onCheckedChange={(checked) => void handleToggle(item.id, checked)}
|
|
276
286
|
/>
|
|
277
287
|
</div>
|
|
278
|
-
{item.category && (
|
|
279
|
-
<Badge variant={categoryBadgeVariant(item.category)} className="w-fit text-xs">
|
|
280
|
-
{item.category}
|
|
281
|
-
</Badge>
|
|
282
|
-
)}
|
|
283
288
|
</CardHeader>
|
|
284
|
-
<CardContent className="flex-1">
|
|
289
|
+
<CardContent className="flex-1 space-y-2">
|
|
285
290
|
{item.description && (
|
|
286
291
|
<p className="text-muted-foreground text-sm">{item.description}</p>
|
|
287
292
|
)}
|
|
293
|
+
{(item.company || item.author || item.version) && (
|
|
294
|
+
<p className="text-muted-foreground text-xs">
|
|
295
|
+
{[item.company || item.author, item.version ? `v${item.version}` : null].filter(Boolean).join(' · ')}
|
|
296
|
+
</p>
|
|
297
|
+
)}
|
|
288
298
|
</CardContent>
|
|
289
299
|
<div className="px-6 pb-4">
|
|
290
300
|
<Button asChild variant="outline" size="sm" className="w-full">
|
|
291
301
|
<Link href={`/backend/integrations/${encodeURIComponent(item.id)}`}>
|
|
302
|
+
<Cog className="mr-1.5 h-4 w-4" />
|
|
292
303
|
{t('integrations.marketplace.configure')}
|
|
293
304
|
</Link>
|
|
294
305
|
</Button>
|
|
@@ -85,28 +85,43 @@
|
|
|
85
85
|
"integrations.detail.credentials.save": "Zugangsdaten speichern",
|
|
86
86
|
"integrations.detail.credentials.saveError": "Zugangsdaten konnten nicht gespeichert werden",
|
|
87
87
|
"integrations.detail.credentials.saved": "Zugangsdaten gespeichert",
|
|
88
|
+
"integrations.detail.credentials.validation.boolean": "Select a valid value.",
|
|
89
|
+
"integrations.detail.credentials.validation.option": "Select one of the available options.",
|
|
90
|
+
"integrations.detail.credentials.validation.required": "{field} is required.",
|
|
91
|
+
"integrations.detail.credentials.validation.text": "Enter a valid value.",
|
|
92
|
+
"integrations.detail.credentials.validation.tooLong": "Value is too long.",
|
|
88
93
|
"integrations.detail.disable": "Deaktivieren",
|
|
89
94
|
"integrations.detail.enable": "Aktivieren",
|
|
90
95
|
"integrations.detail.health.check": "Prüfung ausführen",
|
|
91
96
|
"integrations.detail.health.checkError": "Statusprüfung fehlgeschlagen",
|
|
92
97
|
"integrations.detail.health.checking": "Prüfe…",
|
|
93
98
|
"integrations.detail.health.degraded": "Beeinträchtigt",
|
|
99
|
+
"integrations.detail.health.details": "Details",
|
|
94
100
|
"integrations.detail.health.healthy": "Gesund",
|
|
95
101
|
"integrations.detail.health.lastChecked": "Zuletzt geprüft: {date}",
|
|
102
|
+
"integrations.detail.health.lastResult": "Last result",
|
|
96
103
|
"integrations.detail.health.neverChecked": "Nie geprüft",
|
|
97
104
|
"integrations.detail.health.title": "Gesundheitsstatus",
|
|
98
105
|
"integrations.detail.health.unhealthy": "Nicht gesund",
|
|
99
106
|
"integrations.detail.health.unknown": "Unbekannt",
|
|
107
|
+
"integrations.detail.hub.label": "Hub",
|
|
100
108
|
"integrations.detail.loadError": "Integration konnte nicht geladen werden",
|
|
101
109
|
"integrations.detail.logs.columns.level": "Stufe",
|
|
102
110
|
"integrations.detail.logs.columns.message": "Nachricht",
|
|
103
111
|
"integrations.detail.logs.columns.time": "Zeit",
|
|
112
|
+
"integrations.detail.logs.details.fields": "Fields",
|
|
113
|
+
"integrations.detail.logs.details.noPayload": "No structured payload was stored for this log entry.",
|
|
114
|
+
"integrations.detail.logs.details.payload": "Payload",
|
|
115
|
+
"integrations.detail.logs.details.summary": "Summary",
|
|
104
116
|
"integrations.detail.logs.empty": "Noch keine Protokolleinträge",
|
|
105
117
|
"integrations.detail.logs.level.all": "Alle Stufen",
|
|
106
118
|
"integrations.detail.logs.level.error": "Fehler",
|
|
107
119
|
"integrations.detail.logs.level.info": "Info",
|
|
108
120
|
"integrations.detail.logs.level.warn": "Warnung",
|
|
109
121
|
"integrations.detail.logs.title": "Betriebsprotokolle",
|
|
122
|
+
"integrations.detail.state.disabled": "Disabled",
|
|
123
|
+
"integrations.detail.state.enabled": "Enabled",
|
|
124
|
+
"integrations.detail.state.label": "State",
|
|
110
125
|
"integrations.detail.stateError": "Status konnte nicht aktualisiert werden",
|
|
111
126
|
"integrations.detail.stateUpdated": "Integrationsstatus aktualisiert",
|
|
112
127
|
"integrations.detail.tabs.credentials": "Zugangsdaten",
|
|
@@ -85,28 +85,43 @@
|
|
|
85
85
|
"integrations.detail.credentials.save": "Save Credentials",
|
|
86
86
|
"integrations.detail.credentials.saveError": "Failed to save credentials",
|
|
87
87
|
"integrations.detail.credentials.saved": "Credentials saved",
|
|
88
|
+
"integrations.detail.credentials.validation.boolean": "Select a valid value.",
|
|
89
|
+
"integrations.detail.credentials.validation.option": "Select one of the available options.",
|
|
90
|
+
"integrations.detail.credentials.validation.required": "{field} is required.",
|
|
91
|
+
"integrations.detail.credentials.validation.text": "Enter a valid value.",
|
|
92
|
+
"integrations.detail.credentials.validation.tooLong": "Value is too long.",
|
|
88
93
|
"integrations.detail.disable": "Disable",
|
|
89
94
|
"integrations.detail.enable": "Enable",
|
|
90
95
|
"integrations.detail.health.check": "Run Check",
|
|
91
96
|
"integrations.detail.health.checkError": "Health check failed",
|
|
92
97
|
"integrations.detail.health.checking": "Checking…",
|
|
93
98
|
"integrations.detail.health.degraded": "Degraded",
|
|
99
|
+
"integrations.detail.health.details": "Details",
|
|
94
100
|
"integrations.detail.health.healthy": "Healthy",
|
|
95
101
|
"integrations.detail.health.lastChecked": "Last checked: {date}",
|
|
102
|
+
"integrations.detail.health.lastResult": "Last result",
|
|
96
103
|
"integrations.detail.health.neverChecked": "Never checked",
|
|
97
104
|
"integrations.detail.health.title": "Health Status",
|
|
98
105
|
"integrations.detail.health.unhealthy": "Unhealthy",
|
|
99
106
|
"integrations.detail.health.unknown": "Unknown",
|
|
107
|
+
"integrations.detail.hub.label": "Hub",
|
|
100
108
|
"integrations.detail.loadError": "Failed to load integration",
|
|
101
109
|
"integrations.detail.logs.columns.level": "Level",
|
|
102
110
|
"integrations.detail.logs.columns.message": "Message",
|
|
103
111
|
"integrations.detail.logs.columns.time": "Time",
|
|
112
|
+
"integrations.detail.logs.details.fields": "Fields",
|
|
113
|
+
"integrations.detail.logs.details.noPayload": "No structured payload was stored for this log entry.",
|
|
114
|
+
"integrations.detail.logs.details.payload": "Payload",
|
|
115
|
+
"integrations.detail.logs.details.summary": "Summary",
|
|
104
116
|
"integrations.detail.logs.empty": "No log entries yet",
|
|
105
117
|
"integrations.detail.logs.level.all": "All Levels",
|
|
106
118
|
"integrations.detail.logs.level.error": "Error",
|
|
107
119
|
"integrations.detail.logs.level.info": "Info",
|
|
108
120
|
"integrations.detail.logs.level.warn": "Warning",
|
|
109
121
|
"integrations.detail.logs.title": "Operation Logs",
|
|
122
|
+
"integrations.detail.state.disabled": "Disabled",
|
|
123
|
+
"integrations.detail.state.enabled": "Enabled",
|
|
124
|
+
"integrations.detail.state.label": "State",
|
|
110
125
|
"integrations.detail.stateError": "Failed to update state",
|
|
111
126
|
"integrations.detail.stateUpdated": "Integration state updated",
|
|
112
127
|
"integrations.detail.tabs.credentials": "Credentials",
|
|
@@ -85,28 +85,43 @@
|
|
|
85
85
|
"integrations.detail.credentials.save": "Guardar credenciales",
|
|
86
86
|
"integrations.detail.credentials.saveError": "No se pudieron guardar las credenciales",
|
|
87
87
|
"integrations.detail.credentials.saved": "Credenciales guardadas",
|
|
88
|
+
"integrations.detail.credentials.validation.boolean": "Select a valid value.",
|
|
89
|
+
"integrations.detail.credentials.validation.option": "Select one of the available options.",
|
|
90
|
+
"integrations.detail.credentials.validation.required": "{field} is required.",
|
|
91
|
+
"integrations.detail.credentials.validation.text": "Enter a valid value.",
|
|
92
|
+
"integrations.detail.credentials.validation.tooLong": "Value is too long.",
|
|
88
93
|
"integrations.detail.disable": "Desactivar",
|
|
89
94
|
"integrations.detail.enable": "Activar",
|
|
90
95
|
"integrations.detail.health.check": "Ejecutar verificación",
|
|
91
96
|
"integrations.detail.health.checkError": "La verificación de estado falló",
|
|
92
97
|
"integrations.detail.health.checking": "Verificando…",
|
|
93
98
|
"integrations.detail.health.degraded": "Degradado",
|
|
99
|
+
"integrations.detail.health.details": "Details",
|
|
94
100
|
"integrations.detail.health.healthy": "Saludable",
|
|
95
101
|
"integrations.detail.health.lastChecked": "Última verificación: {date}",
|
|
102
|
+
"integrations.detail.health.lastResult": "Last result",
|
|
96
103
|
"integrations.detail.health.neverChecked": "Nunca verificado",
|
|
97
104
|
"integrations.detail.health.title": "Estado de salud",
|
|
98
105
|
"integrations.detail.health.unhealthy": "No saludable",
|
|
99
106
|
"integrations.detail.health.unknown": "Desconocido",
|
|
107
|
+
"integrations.detail.hub.label": "Hub",
|
|
100
108
|
"integrations.detail.loadError": "No se pudo cargar la integración",
|
|
101
109
|
"integrations.detail.logs.columns.level": "Nivel",
|
|
102
110
|
"integrations.detail.logs.columns.message": "Mensaje",
|
|
103
111
|
"integrations.detail.logs.columns.time": "Hora",
|
|
112
|
+
"integrations.detail.logs.details.fields": "Fields",
|
|
113
|
+
"integrations.detail.logs.details.noPayload": "No structured payload was stored for this log entry.",
|
|
114
|
+
"integrations.detail.logs.details.payload": "Payload",
|
|
115
|
+
"integrations.detail.logs.details.summary": "Summary",
|
|
104
116
|
"integrations.detail.logs.empty": "Sin entradas de registro",
|
|
105
117
|
"integrations.detail.logs.level.all": "Todos los niveles",
|
|
106
118
|
"integrations.detail.logs.level.error": "Error",
|
|
107
119
|
"integrations.detail.logs.level.info": "Info",
|
|
108
120
|
"integrations.detail.logs.level.warn": "Advertencia",
|
|
109
121
|
"integrations.detail.logs.title": "Registros de operación",
|
|
122
|
+
"integrations.detail.state.disabled": "Disabled",
|
|
123
|
+
"integrations.detail.state.enabled": "Enabled",
|
|
124
|
+
"integrations.detail.state.label": "State",
|
|
110
125
|
"integrations.detail.stateError": "No se pudo actualizar el estado",
|
|
111
126
|
"integrations.detail.stateUpdated": "Estado de integración actualizado",
|
|
112
127
|
"integrations.detail.tabs.credentials": "Credenciales",
|
|
@@ -85,28 +85,43 @@
|
|
|
85
85
|
"integrations.detail.credentials.save": "Zapisz dane",
|
|
86
86
|
"integrations.detail.credentials.saveError": "Nie udało się zapisać danych",
|
|
87
87
|
"integrations.detail.credentials.saved": "Dane zapisane",
|
|
88
|
+
"integrations.detail.credentials.validation.boolean": "Select a valid value.",
|
|
89
|
+
"integrations.detail.credentials.validation.option": "Select one of the available options.",
|
|
90
|
+
"integrations.detail.credentials.validation.required": "{field} is required.",
|
|
91
|
+
"integrations.detail.credentials.validation.text": "Enter a valid value.",
|
|
92
|
+
"integrations.detail.credentials.validation.tooLong": "Value is too long.",
|
|
88
93
|
"integrations.detail.disable": "Wyłącz",
|
|
89
94
|
"integrations.detail.enable": "Włącz",
|
|
90
95
|
"integrations.detail.health.check": "Sprawdź",
|
|
91
96
|
"integrations.detail.health.checkError": "Sprawdzenie stanu nie powiodło się",
|
|
92
97
|
"integrations.detail.health.checking": "Sprawdzanie…",
|
|
93
98
|
"integrations.detail.health.degraded": "Pogorszony",
|
|
99
|
+
"integrations.detail.health.details": "Details",
|
|
94
100
|
"integrations.detail.health.healthy": "Zdrowy",
|
|
95
101
|
"integrations.detail.health.lastChecked": "Ostatnie sprawdzenie: {date}",
|
|
102
|
+
"integrations.detail.health.lastResult": "Last result",
|
|
96
103
|
"integrations.detail.health.neverChecked": "Nigdy nie sprawdzano",
|
|
97
104
|
"integrations.detail.health.title": "Stan zdrowia",
|
|
98
105
|
"integrations.detail.health.unhealthy": "Niezdrowy",
|
|
99
106
|
"integrations.detail.health.unknown": "Nieznany",
|
|
107
|
+
"integrations.detail.hub.label": "Hub",
|
|
100
108
|
"integrations.detail.loadError": "Nie udało się załadować integracji",
|
|
101
109
|
"integrations.detail.logs.columns.level": "Poziom",
|
|
102
110
|
"integrations.detail.logs.columns.message": "Wiadomość",
|
|
103
111
|
"integrations.detail.logs.columns.time": "Czas",
|
|
112
|
+
"integrations.detail.logs.details.fields": "Fields",
|
|
113
|
+
"integrations.detail.logs.details.noPayload": "No structured payload was stored for this log entry.",
|
|
114
|
+
"integrations.detail.logs.details.payload": "Payload",
|
|
115
|
+
"integrations.detail.logs.details.summary": "Summary",
|
|
104
116
|
"integrations.detail.logs.empty": "Brak wpisów w logach",
|
|
105
117
|
"integrations.detail.logs.level.all": "Wszystkie poziomy",
|
|
106
118
|
"integrations.detail.logs.level.error": "Błąd",
|
|
107
119
|
"integrations.detail.logs.level.info": "Info",
|
|
108
120
|
"integrations.detail.logs.level.warn": "Ostrzeżenie",
|
|
109
121
|
"integrations.detail.logs.title": "Logi operacji",
|
|
122
|
+
"integrations.detail.state.disabled": "Disabled",
|
|
123
|
+
"integrations.detail.state.enabled": "Enabled",
|
|
124
|
+
"integrations.detail.state.label": "State",
|
|
110
125
|
"integrations.detail.stateError": "Nie udało się zaktualizować stanu",
|
|
111
126
|
"integrations.detail.stateUpdated": "Stan integracji zaktualizowany",
|
|
112
127
|
"integrations.detail.tabs.credentials": "Dane uwierzytelniające",
|
|
@@ -2,8 +2,8 @@ import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
|
|
|
2
2
|
|
|
3
3
|
export const setup: ModuleSetupConfig = {
|
|
4
4
|
defaultRoleFeatures: {
|
|
5
|
-
superadmin: ['integrations.view', 'integrations.manage', 'integrations.credentials.manage'],
|
|
6
|
-
admin: ['integrations.view', 'integrations.manage', 'integrations.credentials.manage'],
|
|
5
|
+
superadmin: ['integrations.*', 'integrations.view', 'integrations.manage', 'integrations.credentials.manage'],
|
|
6
|
+
admin: ['integrations.*', 'integrations.view', 'integrations.manage', 'integrations.credentials.manage'],
|
|
7
7
|
employee: ['integrations.view'],
|
|
8
8
|
},
|
|
9
9
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const features = [
|
|
2
|
+
{ id: 'payment_gateways.view', title: 'View payment gateway transactions', module: 'payment_gateways' },
|
|
3
|
+
{ id: 'payment_gateways.manage', title: 'Create and manage payment sessions', module: 'payment_gateways' },
|
|
4
|
+
{ id: 'payment_gateways.capture', title: 'Capture authorized payments', module: 'payment_gateways' },
|
|
5
|
+
{ id: 'payment_gateways.refund', title: 'Refund captured payments', module: 'payment_gateways' },
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
export default features
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server'
|
|
2
|
+
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
3
|
+
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
4
|
+
import { readJsonSafe } from '@open-mercato/shared/lib/http/readJsonSafe'
|
|
5
|
+
import { cancelSchema } from '../../data/validators'
|
|
6
|
+
import type { PaymentGatewayService } from '../../lib/gateway-service'
|
|
7
|
+
import { paymentGatewaysTag } from '../openapi'
|
|
8
|
+
|
|
9
|
+
export const metadata = {
|
|
10
|
+
path: '/payment_gateways/cancel',
|
|
11
|
+
POST: { requireAuth: true, requireFeatures: ['payment_gateways.manage'] },
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function POST(req: Request) {
|
|
15
|
+
const auth = await getAuthFromRequest(req)
|
|
16
|
+
if (!auth?.tenantId || !auth.orgId) {
|
|
17
|
+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const payload = await readJsonSafe<unknown>(req)
|
|
21
|
+
const parsed = cancelSchema.safeParse(payload)
|
|
22
|
+
if (!parsed.success) {
|
|
23
|
+
return NextResponse.json({ error: 'Invalid payload', details: parsed.error.flatten() }, { status: 422 })
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const container = await createRequestContainer()
|
|
27
|
+
const service = container.resolve('paymentGatewayService') as PaymentGatewayService
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const result = await service.cancelPayment(
|
|
31
|
+
parsed.data.transactionId,
|
|
32
|
+
parsed.data.reason,
|
|
33
|
+
{ organizationId: auth.orgId as string, tenantId: auth.tenantId },
|
|
34
|
+
)
|
|
35
|
+
return NextResponse.json(result)
|
|
36
|
+
} catch (err: unknown) {
|
|
37
|
+
const message = err instanceof Error ? err.message : 'Cancel failed'
|
|
38
|
+
return NextResponse.json({ error: message }, { status: 502 })
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const openApi = {
|
|
43
|
+
tags: [paymentGatewaysTag],
|
|
44
|
+
summary: 'Cancel/void an authorized payment',
|
|
45
|
+
methods: {
|
|
46
|
+
POST: {
|
|
47
|
+
summary: 'Cancel payment',
|
|
48
|
+
tags: [paymentGatewaysTag],
|
|
49
|
+
responses: [
|
|
50
|
+
{ status: 200, description: 'Payment cancelled' },
|
|
51
|
+
{ status: 422, description: 'Invalid payload' },
|
|
52
|
+
{ status: 502, description: 'Gateway provider error' },
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
}
|