@open-mercato/core 0.6.6-develop.6228.1.cf483c68b5 → 0.6.6-develop.6241.1.47c01ad4ed
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/modules/auth/commands/users.js +1 -0
- package/dist/modules/auth/commands/users.js.map +2 -2
- package/dist/modules/communication_channels/data/enrichers.js +9 -1
- package/dist/modules/communication_channels/data/enrichers.js.map +2 -2
- package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.js +3 -5
- package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.js.map +2 -2
- package/dist/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.js.map +2 -2
- package/dist/modules/customers/api/pipeline-stages/reorder/route.js +39 -1
- package/dist/modules/customers/api/pipeline-stages/reorder/route.js.map +2 -2
- package/dist/modules/customers/api/pipeline-stages/route.js +107 -12
- package/dist/modules/customers/api/pipeline-stages/route.js.map +2 -2
- package/dist/modules/customers/api/pipelines/route.js +107 -12
- package/dist/modules/customers/api/pipelines/route.js.map +2 -2
- package/dist/modules/customers/api/settings/address-format/route.js +33 -1
- package/dist/modules/customers/api/settings/address-format/route.js.map +2 -2
- package/dist/modules/customers/api/tags/assign/route.js +37 -0
- package/dist/modules/customers/api/tags/assign/route.js.map +2 -2
- package/dist/modules/customers/api/tags/unassign/route.js +37 -0
- package/dist/modules/customers/api/tags/unassign/route.js.map +2 -2
- package/dist/modules/entities/api/encryption.js +109 -38
- package/dist/modules/entities/api/encryption.js.map +2 -2
- package/dist/modules/entities/components/EncryptionManager.js +22 -9
- package/dist/modules/entities/components/EncryptionManager.js.map +2 -2
- package/dist/modules/integrations/api/[id]/credentials/route.js +23 -1
- package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/route.js +10 -3
- package/dist/modules/integrations/api/[id]/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/state/route.js +20 -5
- package/dist/modules/integrations/api/[id]/state/route.js.map +2 -2
- package/dist/modules/integrations/api/[id]/version/route.js +17 -1
- package/dist/modules/integrations/api/[id]/version/route.js.map +2 -2
- package/dist/modules/integrations/api/route.js +2 -0
- package/dist/modules/integrations/api/route.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js +36 -19
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +13 -9
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/page.js +4 -3
- package/dist/modules/integrations/backend/integrations/page.js.map +2 -2
- package/dist/modules/integrations/data/entities.js +2 -2
- package/dist/modules/integrations/data/entities.js.map +2 -2
- package/dist/modules/integrations/lib/credentials-service.js +32 -0
- package/dist/modules/integrations/lib/credentials-service.js.map +2 -2
- package/dist/modules/integrations/lib/state-service.js +4 -2
- package/dist/modules/integrations/lib/state-service.js.map +2 -2
- package/dist/modules/notifications/lib/notificationService.js +42 -10
- package/dist/modules/notifications/lib/notificationService.js.map +2 -2
- package/dist/modules/payment_gateways/api/status/route.js +91 -6
- package/dist/modules/payment_gateways/api/status/route.js.map +2 -2
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js +25 -11
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +25 -7
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +25 -7
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/components/AdjustmentKindSettings.js +52 -24
- package/dist/modules/sales/components/AdjustmentKindSettings.js.map +2 -2
- package/dist/modules/sales/components/DocumentNumberSettings.js +26 -9
- package/dist/modules/sales/components/DocumentNumberSettings.js.map +2 -2
- package/dist/modules/sales/components/OrderEditingSettings.js +26 -9
- package/dist/modules/sales/components/OrderEditingSettings.js.map +2 -2
- package/dist/modules/sales/components/StatusSettings.js +66 -31
- package/dist/modules/sales/components/StatusSettings.js.map +2 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +25 -7
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/shipping_carriers/api/cancel/route.js +38 -0
- package/dist/modules/shipping_carriers/api/cancel/route.js.map +2 -2
- package/dist/modules/shipping_carriers/api/shipments/route.js +12 -5
- package/dist/modules/shipping_carriers/api/shipments/route.js.map +2 -2
- package/dist/modules/staff/lib/timesheets-ui/TimerBar.js +7 -8
- package/dist/modules/staff/lib/timesheets-ui/TimerBar.js.map +2 -2
- package/dist/modules/staff/lib/timesheets-ui/timerErrors.js +12 -0
- package/dist/modules/staff/lib/timesheets-ui/timerErrors.js.map +7 -0
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js +4 -3
- package/dist/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/page.js +19 -10
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/auth/commands/users.ts +1 -0
- package/src/modules/communication_channels/data/enrichers.ts +25 -0
- package/src/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.client.tsx +7 -6
- package/src/modules/communication_channels/widgets/injection/channel-payload-renderer/widget.ts +5 -2
- package/src/modules/customers/api/pipeline-stages/reorder/route.ts +41 -1
- package/src/modules/customers/api/pipeline-stages/route.ts +112 -13
- package/src/modules/customers/api/pipelines/route.ts +112 -13
- package/src/modules/customers/api/settings/address-format/route.ts +36 -1
- package/src/modules/customers/api/tags/assign/route.ts +39 -0
- package/src/modules/customers/api/tags/unassign/route.ts +39 -0
- package/src/modules/customers/i18n/de.json +1 -0
- package/src/modules/customers/i18n/en.json +1 -0
- package/src/modules/customers/i18n/es.json +1 -0
- package/src/modules/customers/i18n/pl.json +1 -0
- package/src/modules/entities/api/encryption.ts +122 -39
- package/src/modules/entities/components/EncryptionManager.tsx +28 -9
- package/src/modules/integrations/api/[id]/credentials/route.ts +23 -0
- package/src/modules/integrations/api/[id]/route.ts +8 -1
- package/src/modules/integrations/api/[id]/state/route.ts +20 -4
- package/src/modules/integrations/api/[id]/version/route.ts +18 -1
- package/src/modules/integrations/api/route.ts +3 -0
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +39 -20
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +19 -11
- package/src/modules/integrations/backend/integrations/page.tsx +8 -5
- package/src/modules/integrations/data/entities.ts +2 -2
- package/src/modules/integrations/lib/credentials-service.ts +35 -0
- package/src/modules/integrations/lib/state-service.ts +3 -0
- package/src/modules/notifications/lib/notificationService.ts +74 -11
- package/src/modules/payment_gateways/api/status/route.ts +97 -5
- package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +27 -11
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +31 -7
- package/src/modules/sales/backend/sales/channels/page.tsx +31 -7
- package/src/modules/sales/components/AdjustmentKindSettings.tsx +60 -24
- package/src/modules/sales/components/DocumentNumberSettings.tsx +32 -10
- package/src/modules/sales/components/OrderEditingSettings.tsx +32 -10
- package/src/modules/sales/components/StatusSettings.tsx +74 -33
- package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +30 -6
- package/src/modules/shipping_carriers/api/cancel/route.ts +46 -0
- package/src/modules/shipping_carriers/api/shipments/route.ts +21 -6
- package/src/modules/staff/i18n/de.json +5 -5
- package/src/modules/staff/i18n/es.json +5 -5
- package/src/modules/staff/i18n/pl.json +5 -5
- package/src/modules/staff/lib/timesheets-ui/TimerBar.tsx +7 -8
- package/src/modules/staff/lib/timesheets-ui/timerErrors.ts +23 -0
- package/src/modules/staff/widgets/dashboard/timesheets-time-reporting/widget.client.tsx +4 -3
- package/src/modules/workflows/backend/definitions/page.tsx +19 -10
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/integrations/backend/integrations/%5Bid%5D/page.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation'\nimport { z } from 'zod'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm, type CrudField } from '@open-mercato/ui/backend/CrudForm'\nimport { WebhookSetupGuide } from '@open-mercato/ui/backend/WebhookSetupGuide'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport { Card, CardHeader, CardTitle, CardContent } from '@open-mercato/ui/primitives/card'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { PasswordInput } from '@open-mercato/ui/primitives/password-input'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport {\n LEGACY_INTEGRATION_DETAIL_TABS_SPOT_ID,\n type CredentialFieldType,\n type IntegrationCredentialField,\n type IntegrationDetailBuiltInTab,\n} from '@open-mercato/shared/modules/integrations/types'\nimport { LoadingMessage, ErrorMessage, RecordNotFoundState } from '@open-mercato/ui/backend/detail'\nimport { LogList, type LogListEntry } from '@open-mercato/ui/backend/LogList'\nimport { Activity, AlertTriangle, Bell, Calendar, CheckCircle2, CreditCard, FileText, FileX, HardDrive, Key, MessageSquare, RefreshCw, Settings, Truck, Webhook, XCircle, Zap } from 'lucide-react'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { IntegrationScheduleTab } from '../../../../data_sync/components/IntegrationScheduleTab'\nimport {\n buildIntegrationDetailInjectedTabs,\n filterIntegrationDetailWidgetsByKind,\n type IntegrationDetailInjectedTab,\n resolveIntegrationDetailWidgetSpotId,\n resolveRequestedIntegrationDetailTab,\n} from '../detail-page-widgets'\nimport {\n refreshIntegrationDetailPanels,\n refreshIntegrationRunActivityPanels,\n} from '../detail-page-refresh'\nimport { isValidCredentialUrl } from '../../../lib/credentials-field-validation'\n\ntype CredentialField = IntegrationCredentialField\ntype BuiltInIntegrationDetailTab = 'credentials' | 'version' | 'health' | 'logs' | 'data-sync-schedule'\ntype IntegrationDetailTab = BuiltInIntegrationDetailTab | string\n\nconst UNSUPPORTED_CREDENTIAL_FIELD_TYPES = new Set<CredentialFieldType>(['oauth', 'ssh_keypair'])\n\nfunction isEditableCredentialField(field: CredentialField): boolean {\n return !UNSUPPORTED_CREDENTIAL_FIELD_TYPES.has(field.type)\n}\n\ntype ApiVersion = {\n id: string\n label?: string\n status: 'stable' | 'deprecated' | 'experimental'\n sunsetAt?: string\n migrationGuide?: string\n}\n\ntype IntegrationLogAnalytics = {\n lastActivityAt: string | null\n totalCount: number\n errorCount: number\n errorRate: number\n dailyCounts: number[]\n}\n\ntype IntegrationDetail = {\n integration: {\n id: string\n title: string\n description?: string\n category?: string\n hub?: string\n providerKey?: string | null\n bundleId?: string\n docsUrl?: string\n apiVersions?: ApiVersion[]\n detailPage?: {\n widgetSpotId?: string\n hiddenTabs?: IntegrationDetailBuiltInTab[]\n }\n credentials?: { fields: CredentialField[] }\n }\n bundle?: { id: string; title: string; credentials?: { fields: CredentialField[] } }\n state: {\n isEnabled: boolean\n apiVersion: string | null\n reauthRequired: boolean\n lastHealthStatus: string | null\n lastHealthCheckedAt: string | null\n lastHealthLatencyMs: number | null\n enabledAt: string | null\n }\n hasCredentials: boolean\n healthStatus: 'healthy' | 'degraded' | 'unhealthy' | 'unconfigured'\n analytics: IntegrationLogAnalytics\n}\n\ntype LogEntry = {\n id: string\n runId?: string | null\n scopeEntityType?: string | null\n scopeEntityId?: string | null\n level: 'info' | 'warn' | 'error'\n message: string\n createdAt: string\n code?: string | null\n payload?: Record<string, unknown> | null\n}\n\ntype IntegrationDetailPageProps = {\n params?: {\n id?: string | string[]\n }\n}\n\ntype HealthCheckResponse = {\n status: 'healthy' | 'degraded' | 'unhealthy' | 'unconfigured'\n message: string | null\n details: Record<string, unknown> | null\n checkedAt: string\n latencyMs: number | null\n}\n\ntype DataSyncRunDetail = {\n id: string\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'\n progressJobId?: string | null\n createdCount?: number\n updatedCount?: number\n skippedCount?: number\n failedCount?: number\n progressJob?: {\n progressPercent?: number | null\n processedCount?: number | null\n totalCount?: number | null\n } | null\n}\n\nconst LOG_LEVEL_STYLES: Record<string, string> = {\n info: 'bg-status-info-bg text-status-info-text',\n warn: 'bg-status-warning-bg text-status-warning-text',\n error: 'bg-status-error-bg text-status-error-text',\n}\n\nconst HEALTH_STATUS_STYLES: Record<string, string> = {\n healthy: 'bg-status-success-bg text-status-success-text',\n degraded: 'bg-status-warning-bg text-status-warning-text',\n unhealthy: 'bg-status-error-bg text-status-error-text',\n unconfigured: 'bg-status-neutral-bg text-status-neutral-text',\n}\n\nconst HEALTH_STATUS_ICONS: Record<string, React.ElementType> = {\n healthy: CheckCircle2,\n degraded: AlertTriangle,\n unhealthy: XCircle,\n unconfigured: AlertTriangle,\n}\n\nfunction formatRunStatusLabel(status: DataSyncRunDetail['status'], t: ReturnType<typeof useT>): string {\n switch (status) {\n case 'pending':\n return t('integrations.detail.runActivity.status.pending', 'Pending')\n case 'running':\n return t('integrations.detail.runActivity.status.running', 'Running')\n case 'completed':\n return t('integrations.detail.runActivity.status.completed', 'Completed')\n case 'failed':\n return t('integrations.detail.runActivity.status.failed', 'Failed')\n case 'cancelled':\n return t('integrations.detail.runActivity.status.cancelled', 'Cancelled')\n default:\n return status\n }\n}\n\nfunction RunActivityStrip({\n run,\n refreshedAt,\n isRefreshing,\n onRefresh,\n t,\n}: {\n run: DataSyncRunDetail | null\n refreshedAt: string | null\n isRefreshing: boolean\n onRefresh: () => void\n t: ReturnType<typeof useT>\n}) {\n if (!run) return null\n\n const progress = typeof run.progressJob?.progressPercent === 'number' ? run.progressJob.progressPercent : 0\n const processed = typeof run.progressJob?.processedCount === 'number' ? run.progressJob.processedCount : 0\n const total = typeof run.progressJob?.totalCount === 'number' ? run.progressJob.totalCount : null\n const statusClass = run.status === 'completed'\n ? 'border-status-success-border bg-status-success-bg text-status-success-text'\n : run.status === 'failed'\n ? 'border-status-error-border bg-status-error-bg text-status-error-text'\n : run.status === 'cancelled'\n ? 'border-status-neutral-border bg-status-neutral-bg text-status-neutral-text'\n : 'border-status-info-border bg-status-info-bg text-status-info-text'\n\n return (\n <div className=\"flex flex-wrap items-center gap-3 rounded-lg border bg-muted/20 px-4 py-3 text-sm\">\n <Badge variant=\"outline\" className={cn('gap-1.5', statusClass)}>\n <RefreshCw className={cn('h-3.5 w-3.5', run.status === 'running' ? 'animate-spin' : '')} />\n {formatRunStatusLabel(run.status, t)}\n </Badge>\n <span className=\"text-muted-foreground\">\n {t('integrations.detail.runActivity.processed', 'Processed')}: <span className=\"font-medium text-foreground\">{processed}{total !== null ? ` / ${total}` : ''}</span>\n </span>\n <span className=\"text-muted-foreground\">\n {t('integrations.detail.runActivity.progress', 'Progress')}: <span className=\"font-medium text-foreground\">{progress}%</span>\n </span>\n {refreshedAt ? (\n <span className=\"text-muted-foreground\">\n {t('integrations.detail.runActivity.lastRefreshed', 'Last refreshed')}: {new Date(refreshedAt).toLocaleTimeString()}\n </span>\n ) : null}\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"ml-auto\" onClick={onRefresh} disabled={isRefreshing}>\n {isRefreshing ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('integrations.detail.runActivity.refresh', 'Refresh')}\n </Button>\n </div>\n )\n}\n\nfunction DetailLogSparkline({ counts, className }: { counts: number[]; className?: string }) {\n const max = Math.max(1, ...counts)\n const w = 120\n const h = 36\n const step = counts.length > 1 ? w / (counts.length - 1) : w\n const points = counts.map((count, index) => {\n const x = index * step\n const y = h - (count / max) * (h - 4) - 2\n return `${x},${y}`\n }).join(' ')\n return (\n <svg width={w} height={h} className={className} aria-hidden>\n <polyline\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n points={points}\n className=\"text-muted-foreground/80\"\n />\n </svg>\n )\n}\n\nconst CATEGORY_ICONS: Record<string, React.ElementType> = {\n payment: CreditCard,\n shipping: Truck,\n data_sync: RefreshCw,\n communication: MessageSquare,\n notification: Bell,\n storage: HardDrive,\n webhook: Webhook,\n}\n\nfunction resolveRouteId(value: string | string[] | undefined): string | undefined {\n if (Array.isArray(value)) return value[0]\n return value\n}\n\nfunction resolvePathnameId(pathname: string): string | undefined {\n const parts = pathname.split('/').filter(Boolean)\n const integrationId = parts.at(-1)\n if (!integrationId || integrationId === 'integrations' || integrationId === 'bundle') return undefined\n return decodeURIComponent(integrationId)\n}\n\nfunction buildCredentialFields(credFields: CredentialField[]): CrudField[] {\n return credFields.map((field) => {\n const shared = {\n id: field.key,\n label: field.label,\n description: field.helpDetails ? (\n <div className=\"space-y-1\">\n {field.helpText ? <div>{field.helpText}</div> : null}\n <WebhookSetupGuide guide={field.helpDetails} buttonLabel=\"Show details\" />\n </div>\n ) : field.helpText,\n placeholder: field.placeholder,\n required: field.required,\n visibleWhen: field.visibleWhen,\n }\n\n if (field.type === 'secret') {\n return {\n ...shared,\n type: 'custom' as const,\n component: ({ id, value, setValue, disabled }) => (\n <PasswordInput\n id={id}\n placeholder={field.placeholder}\n value={typeof value === 'string' ? value : ''}\n onChange={(event) => setValue(event.target.value)}\n disabled={disabled}\n />\n ),\n }\n }\n\n if (field.type === 'select' && field.options) {\n return {\n ...shared,\n type: 'select' as const,\n options: field.options,\n }\n }\n\n if (field.type === 'boolean') {\n return {\n ...shared,\n type: 'checkbox' as const,\n }\n }\n\n return {\n ...shared,\n type: 'text' as const,\n }\n })\n}\n\nfunction isHealthLog(log: LogEntry): boolean {\n return log.message === 'Health check passed' || log.message.startsWith('Health check:')\n}\n\nfunction extractHealthDetails(payload: Record<string, unknown> | null | undefined): Record<string, unknown> {\n if (!payload) return {}\n return Object.fromEntries(\n Object.entries(payload).filter(([key, value]) => key !== 'status' && key !== 'message' && value !== undefined && value !== null),\n )\n}\n\nfunction formatHealthValue(value: unknown): string {\n if (typeof value === 'boolean') return value ? 'Yes' : 'No'\n if (typeof value === 'string') return value\n if (typeof value === 'number') return String(value)\n if (value instanceof Date) return value.toLocaleString()\n return JSON.stringify(value)\n}\n\nfunction formatTypeLabel(value: string): string {\n return value.split('_').filter(Boolean).map((part) => part[0]?.toUpperCase() + part.slice(1)).join(' ')\n}\n\nfunction isPrimitiveLogValue(value: unknown): value is string | number | boolean | null {\n return value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'\n}\n\nfunction formatLogDetailLabel(key: string): string {\n return key\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .split(' ')\n .filter(Boolean)\n .map((part) => part[0]?.toUpperCase() + part.slice(1))\n .join(' ')\n}\n\nfunction formatLogPrimitiveValue(value: string | number | boolean | null): string {\n if (value === null) return 'None'\n if (typeof value === 'boolean') return value ? 'Yes' : 'No'\n return String(value)\n}\n\nfunction isAkeneoSettingsTab(tab: IntegrationDetailInjectedTab): boolean {\n return tab.id.includes('sync_akeneo') || tab.label.toLowerCase().includes('akeneo')\n}\n\nfunction splitLogPayload(payload: Record<string, unknown> | null | undefined) {\n if (!payload) {\n return {\n inlineEntries: [] as Array<[string, string | number | boolean | null]>,\n nestedEntries: [] as Array<[string, unknown]>,\n }\n }\n\n const inlineEntries: Array<[string, string | number | boolean | null]> = []\n const nestedEntries: Array<[string, unknown]> = []\n\n Object.entries(payload).forEach(([key, value]) => {\n if (isPrimitiveLogValue(value)) {\n inlineEntries.push([key, value])\n return\n }\n nestedEntries.push([key, value])\n })\n\n return { inlineEntries, nestedEntries }\n}\n\nexport default function IntegrationDetailPage({ params }: IntegrationDetailPageProps) {\n const pathname = usePathname()\n const router = useRouter()\n const searchParams = useSearchParams()\n const integrationId = resolveRouteId(params?.id) ?? resolvePathnameId(pathname)\n const t = useT()\n\n const [detail, setDetail] = React.useState<IntegrationDetail | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n\n const [credValues, setCredValues] = React.useState<Record<string, unknown>>({})\n const [credentialsFormKey, setCredentialsFormKey] = React.useState(0)\n const [isSavingCredentials, setIsSavingCredentials] = React.useState(false)\n\n const [logs, setLogs] = React.useState<LogEntry[]>([])\n const [logLevel, setLogLevel] = React.useState<string>('')\n const [isLoadingLogs, setIsLoadingLogs] = React.useState(false)\n\n const [isCheckingHealth, setIsCheckingHealth] = React.useState(false)\n const [isTogglingState, setIsTogglingState] = React.useState(false)\n const [latestHealthResult, setLatestHealthResult] = React.useState<HealthCheckResponse | null>(null)\n const [activeRunDetail, setActiveRunDetail] = React.useState<DataSyncRunDetail | null>(null)\n const [activeRunRefreshedAt, setActiveRunRefreshedAt] = React.useState<string | null>(null)\n const [isRefreshingRunActivity, setIsRefreshingRunActivity] = React.useState(false)\n const [activeTab, setActiveTab] = React.useState<IntegrationDetailTab>('credentials')\n\n const credentialsFormId = React.useId()\n\n const resolveCurrentIntegrationId = React.useCallback(() => {\n return integrationId ?? (\n typeof window !== 'undefined'\n ? resolvePathnameId(window.location.pathname)\n : undefined\n )\n }, [integrationId])\n\n const loadDetail = React.useCallback(async (options?: { showLoading?: boolean }) => {\n const showLoading = options?.showLoading ?? true\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) {\n if (showLoading) setIsLoading(false)\n if (showLoading) setError(t('integrations.detail.loadError', 'Failed to load integration'))\n return\n }\n if (showLoading) setError(null)\n if (showLoading) setIsNotFound(false)\n if (showLoading) setIsLoading(true)\n try {\n const call = await apiCall<IntegrationDetail>(\n `/api/integrations/${encodeURIComponent(currentIntegrationId)}`,\n undefined,\n { fallback: null },\n )\n if (!call.ok || !call.result) {\n if (call.status === 404) {\n if (showLoading) setIsNotFound(true)\n } else {\n if (showLoading) setError(t('integrations.detail.loadError', 'Failed to load integration'))\n }\n if (showLoading) setIsLoading(false)\n return\n }\n setDetail(call.result)\n setError(null)\n if (showLoading) setIsLoading(false)\n } catch {\n if (showLoading) setError(t('integrations.detail.loadError', 'Failed to load integration'))\n if (showLoading) setIsLoading(false)\n }\n }, [resolveCurrentIntegrationId, t])\n\n const loadCredentials = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n const call = await apiCall<{ credentials: Record<string, unknown> }>(\n `/api/integrations/${encodeURIComponent(currentIntegrationId)}/credentials`,\n undefined,\n { fallback: null },\n )\n if (call.ok && call.result?.credentials) {\n const next = { ...call.result.credentials }\n if (currentIntegrationId === 'storage_s3') {\n const authMode = next.authMode\n if (authMode !== 'access_keys' && authMode !== 'ambient') {\n const hasKeys = Boolean(next.accessKeyId || next.secretAccessKey)\n next.authMode = hasKeys ? 'access_keys' : 'ambient'\n }\n }\n setCredValues(next)\n setCredentialsFormKey((current) => current + 1)\n }\n }, [resolveCurrentIntegrationId])\n\n const loadLogs = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsLoadingLogs(true)\n const params = new URLSearchParams({ integrationId: currentIntegrationId, pageSize: '50' })\n if (logLevel) params.set('level', logLevel)\n const call = await apiCall<{ items: LogEntry[] }>(\n `/api/integrations/logs?${params.toString()}`,\n undefined,\n { fallback: { items: [] } },\n )\n if (call.ok && call.result) {\n setLogs(call.result.items)\n }\n setIsLoadingLogs(false)\n }, [logLevel, resolveCurrentIntegrationId])\n\n const detailWidgetSpotId = React.useMemo(\n () => resolveIntegrationDetailWidgetSpotId(detail?.integration ?? null, LEGACY_INTEGRATION_DETAIL_TABS_SPOT_ID),\n [detail?.integration],\n )\n const mutationContextId = React.useMemo(\n () => `integrations.detail:${integrationId ?? 'unknown'}`,\n [integrationId],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<Record<string, unknown>>({\n contextId: mutationContextId,\n spotId: detailWidgetSpotId,\n })\n const refreshDetail = React.useCallback(async () => {\n await refreshIntegrationDetailPanels({ loadDetail, loadCredentials })\n }, [loadCredentials, loadDetail])\n const refreshLogs = React.useCallback(async () => {\n await loadLogs()\n }, [loadLogs])\n const refreshHealthSnapshot = React.useCallback(async () => {\n await loadDetail({ showLoading: false })\n }, [loadDetail])\n const runIdFromUrl = searchParams?.get('runId') ?? null\n const refreshRunActivity = React.useCallback(async (options?: { showLoading?: boolean }) => {\n if (!runIdFromUrl) {\n setActiveRunDetail(null)\n setActiveRunRefreshedAt(null)\n return null\n }\n if (options?.showLoading) setIsRefreshingRunActivity(true)\n try {\n const [call] = await Promise.all([\n apiCall<DataSyncRunDetail>(\n `/api/data_sync/runs/${encodeURIComponent(runIdFromUrl)}`,\n undefined,\n { fallback: null },\n ),\n refreshIntegrationRunActivityPanels({ loadLogs, loadDetail }),\n ])\n if (call.ok && call.result) {\n setActiveRunDetail(call.result)\n setActiveRunRefreshedAt(new Date().toISOString())\n return call.result\n }\n return null\n } finally {\n if (options?.showLoading) setIsRefreshingRunActivity(false)\n }\n }, [loadDetail, loadLogs, runIdFromUrl])\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n integrationDetailWidgetSpotId: detailWidgetSpotId,\n resourceKind: 'integrations.integration',\n resourceId: integrationId ?? detail?.integration.id,\n integrationId: integrationId ?? detail?.integration.id,\n integration: detail?.integration ?? null,\n detail,\n state: detail?.state ?? null,\n credentialValues: credValues,\n latestHealthResult,\n activeTab,\n setActiveTab,\n refreshDetail,\n refreshLogs,\n refreshHealthSnapshot,\n retryLastMutation,\n }),\n [\n activeTab,\n credValues,\n detail,\n detailWidgetSpotId,\n integrationId,\n latestHealthResult,\n mutationContextId,\n refreshDetail,\n refreshHealthSnapshot,\n refreshLogs,\n retryLastMutation,\n ],\n )\n const { widgets: detailWidgets } = useInjectionWidgets(detailWidgetSpotId, {\n context: injectionContext,\n triggerOnLoad: true,\n })\n const stackedDetailWidgets = React.useMemo(\n () => filterIntegrationDetailWidgetsByKind(detailWidgets, 'stack'),\n [detailWidgets],\n )\n const groupedDetailWidgets = React.useMemo(\n () => filterIntegrationDetailWidgetsByKind(detailWidgets, 'group'),\n [detailWidgets],\n )\n const injectedTabs = React.useMemo(\n () => buildIntegrationDetailInjectedTabs(\n detailWidgets,\n (widget) => (\n widget.placement?.groupLabel\n ? t(widget.placement.groupLabel, widget.module.metadata.title ?? widget.widgetId)\n : (widget.module.metadata.title ?? widget.widgetId)\n ),\n ),\n [detailWidgets, t],\n )\n const hasDataSyncScheduleTab = Boolean(\n detail?.integration.hub === 'data_sync'\n && detail?.integration.providerKey\n && detail.integration.providerKey.trim().length > 0,\n )\n const runMutationWithContext = React.useCallback(\n async <T,>({\n operation,\n mutationPayload,\n actionId,\n tabId,\n operationType = 'update',\n }: {\n operation: () => Promise<T>\n mutationPayload?: Record<string, unknown>\n actionId: string\n tabId?: string\n operationType?: 'create' | 'update' | 'delete'\n }): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: {\n ...injectionContext,\n operation: operationType,\n actionId,\n activeTab: tabId ?? activeTab,\n },\n })\n },\n [activeTab, injectionContext, runMutation],\n )\n\n React.useEffect(() => { void loadDetail() }, [loadDetail])\n React.useEffect(() => { void loadCredentials() }, [loadCredentials])\n React.useEffect(() => { void loadLogs() }, [loadLogs])\n\n const handleToggleState = React.useCallback(async (enabled: boolean) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsTogglingState(true)\n try {\n const call = await runMutationWithContext({\n actionId: 'toggle-state',\n mutationPayload: { integrationId: currentIntegrationId, isEnabled: enabled },\n operation: () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/state`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ isEnabled: enabled }),\n }, { fallback: null }),\n })\n if (call.ok) {\n setDetail((prev) => prev ? {\n ...prev,\n state: {\n ...prev.state,\n isEnabled: enabled,\n enabledAt: enabled ? new Date().toISOString() : prev.state.enabledAt,\n },\n } : prev)\n flash(t('integrations.detail.stateUpdated'), 'success')\n } else {\n flash(t('integrations.detail.stateError'), 'error')\n }\n } catch {\n flash(t('integrations.detail.stateError'), 'error')\n } finally {\n setIsTogglingState(false)\n }\n }, [resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const handleSaveCredentials = React.useCallback(async (values: Record<string, unknown>) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsSavingCredentials(true)\n try {\n const sanitizedValues = { ...values }\n if (currentIntegrationId === 'storage_s3') {\n const authMode = sanitizedValues.authMode\n if (authMode !== 'access_keys' && authMode !== 'ambient') {\n const hasKeys = Boolean(sanitizedValues.accessKeyId || sanitizedValues.secretAccessKey)\n sanitizedValues.authMode = hasKeys ? 'access_keys' : 'ambient'\n }\n if (sanitizedValues.authMode === 'ambient') {\n delete sanitizedValues.accessKeyId\n delete sanitizedValues.secretAccessKey\n delete sanitizedValues.sessionToken\n }\n }\n const call = await runMutationWithContext({\n actionId: 'save-credentials',\n tabId: 'credentials',\n mutationPayload: { integrationId: currentIntegrationId, credentials: sanitizedValues },\n operation: () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/credentials`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ credentials: sanitizedValues }),\n }, { fallback: null }),\n })\n\n if (call.ok) {\n setCredValues(sanitizedValues)\n setCredentialsFormKey((current) => current + 1)\n flash(t('integrations.detail.credentials.saved'), 'success')\n return\n }\n\n const result = call.result as {\n error?: string\n details?: { fieldErrors?: Record<string, string>; formErrors?: string[] }\n } | null\n throw createCrudFormError(\n result?.error ?? t('integrations.detail.credentials.saveError', 'Failed to save credentials'),\n result?.details?.fieldErrors,\n { details: result?.details },\n )\n } finally {\n setIsSavingCredentials(false)\n }\n }, [resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const handleVersionChange = React.useCallback(async (version: string) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n try {\n const call = await runMutationWithContext({\n actionId: 'change-version',\n tabId: 'version',\n mutationPayload: { integrationId: currentIntegrationId, apiVersion: version },\n operation: () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/version`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ apiVersion: version }),\n }, { fallback: null }),\n })\n if (call.ok) {\n setDetail((prev) => prev ? { ...prev, state: { ...prev.state, apiVersion: version } } : prev)\n flash(t('integrations.detail.version.saved'), 'success')\n } else {\n flash(t('integrations.detail.version.saveError'), 'error')\n }\n } catch {\n flash(t('integrations.detail.version.saveError'), 'error')\n }\n }, [resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const handleHealthCheck = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsCheckingHealth(true)\n try {\n const call = await runMutationWithContext({\n actionId: 'run-health-check',\n tabId: 'health',\n mutationPayload: { integrationId: currentIntegrationId },\n operation: () => apiCall<HealthCheckResponse>(\n `/api/integrations/${encodeURIComponent(currentIntegrationId)}/health`,\n { method: 'POST' },\n { fallback: null },\n ),\n })\n const result = call.result\n if (call.ok && result) {\n setLatestHealthResult(result)\n setDetail((prev) => prev ? {\n ...prev,\n healthStatus: result.status,\n state: {\n ...prev.state,\n lastHealthStatus: result.status === 'unconfigured' ? prev.state.lastHealthStatus : result.status,\n lastHealthCheckedAt: result.status === 'unconfigured' ? prev.state.lastHealthCheckedAt : result.checkedAt,\n lastHealthLatencyMs: result.latencyMs ?? prev.state.lastHealthLatencyMs,\n },\n } : prev)\n void refreshLogs()\n } else {\n flash(t('integrations.detail.health.checkError'), 'error')\n }\n } catch {\n flash(t('integrations.detail.health.checkError'), 'error')\n } finally {\n setIsCheckingHealth(false)\n }\n }, [refreshLogs, resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const hasVersions = Boolean(detail?.integration.apiVersions?.length)\n const integration = detail?.integration ?? null\n const state = detail?.state ?? null\n const editableCredentialFields = React.useMemo(\n () => (detail?.integration.credentials?.fields ?? detail?.bundle?.credentials?.fields ?? []).filter(isEditableCredentialField),\n [detail?.bundle?.credentials?.fields, detail?.integration.credentials?.fields],\n )\n const credentialFormFields = React.useMemo(\n () => buildCredentialFields(editableCredentialFields),\n [editableCredentialFields],\n )\n const credentialSchema = React.useMemo(() => (\n z.object({}).passthrough().superRefine((rawValues, ctx) => {\n const values = rawValues as Record<string, unknown>\n\n editableCredentialFields.forEach((field) => {\n if (field.visibleWhen) {\n const targetValue = values[field.visibleWhen.field]\n if (targetValue !== field.visibleWhen.equals) return\n }\n const value = values[field.key]\n\n if (field.type === 'boolean') {\n if (value !== undefined && value !== null && typeof value !== 'boolean') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.boolean', 'Select a valid value.'),\n })\n }\n if (field.required && typeof value !== 'boolean') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.required', '{field} is required.', { field: field.label }),\n })\n }\n return\n }\n\n if (value !== undefined && value !== null && typeof value !== 'string') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.text', 'Enter a valid value.'),\n })\n return\n }\n\n const normalizedValue = typeof value === 'string' ? value : ''\n\n if (field.required && normalizedValue.trim().length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.required', '{field} is required.', { field: field.label }),\n })\n }\n\n if (normalizedValue.length > 20_000) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.tooLong', 'Value is too long.'),\n })\n }\n\n if (\n field.type === 'url'\n && normalizedValue.trim().length > 0\n && !isValidCredentialUrl(normalizedValue.trim())\n ) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.url', '{field} must be a valid http(s) URL.', { field: field.label }),\n })\n }\n\n if (\n field.type === 'select'\n && normalizedValue\n && field.options\n && !field.options.some((option) => option.value === normalizedValue)\n ) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.option', 'Select one of the available options.'),\n })\n }\n })\n })\n ) as z.ZodType<Record<string, unknown>>, [editableCredentialFields, t])\n const latestHealthLog = React.useMemo(() => logs.find(isHealthLog) ?? null, [logs])\n const latestOperationalLog = React.useMemo(\n () => logs.find((log) => (\n typeof log.payload?.operationalStatus === 'string'\n || typeof log.payload?.summary === 'string'\n )) ?? null,\n [logs],\n )\n const healthMessage =\n latestHealthResult?.message ??\n (typeof latestHealthLog?.payload?.message === 'string'\n ? latestHealthLog.payload.message\n : typeof latestOperationalLog?.payload?.summary === 'string'\n ? latestOperationalLog.payload.summary\n : null)\n const healthDetailsSource = latestHealthResult?.details ?? extractHealthDetails(latestHealthLog?.payload ?? latestOperationalLog?.payload)\n const healthDetails = latestHealthLog?.code\n ? { ...healthDetailsSource, code: latestHealthLog.code }\n : healthDetailsSource\n const healthDetailEntries = Object.entries(healthDetails)\n const resolvedIntegration = detail?.integration ?? null\n const resolvedState = detail?.state ?? null\n const displayHealthStatus =\n latestHealthResult?.status ?? detail?.healthStatus ?? resolvedState?.lastHealthStatus ?? 'unconfigured'\n\n const healthStatusDescription = displayHealthStatus && displayHealthStatus !== 'unconfigured'\n ? t(\n `integrations.detail.health.meaning.${displayHealthStatus}`,\n displayHealthStatus === 'healthy'\n ? 'The provider responded successfully using the current credentials.'\n : displayHealthStatus === 'degraded'\n ? 'The provider responded, but reported warnings or limited functionality.'\n : integration?.id === 'gateway_stripe'\n ? 'Stripe rejected the last check. This usually means the secret key is invalid, missing required permissions, revoked, or Stripe was temporarily unavailable.'\n : 'The last check failed. This usually means invalid credentials, missing permissions, or a provider outage.',\n )\n : displayHealthStatus === 'unconfigured'\n ? t(\n 'integrations.detail.health.meaning.unconfigured',\n 'Credentials or a health check are not configured, or the integration has not been probed yet.',\n )\n : null\n\n const CategoryIcon = resolvedIntegration?.category ? CATEGORY_ICONS[resolvedIntegration.category] : null\n const HealthStatusIcon = HEALTH_STATUS_ICONS[displayHealthStatus] ?? null\n const prioritizedInjectedTabs = resolvedIntegration?.id === 'sync_akeneo'\n ? [...injectedTabs].sort((left, right) => {\n const leftPriority = isAkeneoSettingsTab(left) ? 1 : 0\n const rightPriority = isAkeneoSettingsTab(right) ? 1 : 0\n if (leftPriority !== rightPriority) return rightPriority - leftPriority\n return 0\n })\n : injectedTabs\n const leadingInjectedTab = resolvedIntegration?.id === 'sync_akeneo'\n ? prioritizedInjectedTabs.find(isAkeneoSettingsTab) ?? null\n : null\n const trailingInjectedTabs = leadingInjectedTab\n ? prioritizedInjectedTabs.filter((tab) => tab.id !== leadingInjectedTab.id)\n : prioritizedInjectedTabs\n const hiddenBuiltInTabs = new Set(resolvedIntegration?.detailPage?.hiddenTabs ?? [])\n const showCredentialsTab = !hiddenBuiltInTabs.has('credentials')\n const showVersionTab = hasVersions && !hiddenBuiltInTabs.has('version')\n const showDataSyncScheduleTab = hasDataSyncScheduleTab && !hiddenBuiltInTabs.has('data-sync-schedule')\n const showHealthTab = !hiddenBuiltInTabs.has('health')\n const showLogsTab = !hiddenBuiltInTabs.has('logs')\n const visibleTabIds = [\n ...(showCredentialsTab ? ['credentials'] : []),\n ...(leadingInjectedTab ? [leadingInjectedTab.id] : []),\n ...(showVersionTab ? ['version'] : []),\n ...(showDataSyncScheduleTab ? ['data-sync-schedule'] : []),\n ...(showHealthTab ? ['health'] : []),\n ...(showLogsTab ? ['logs'] : []),\n ...trailingInjectedTabs.map((tab) => tab.id),\n ] satisfies IntegrationDetailTab[]\n const StateIcon = resolvedState?.isEnabled ? CheckCircle2 : XCircle\n const stateBadgeClass = resolvedState?.isEnabled\n ? 'border-status-success-border bg-status-success-bg text-status-success-text'\n : 'border-status-neutral-border bg-status-neutral-bg text-status-neutral-text'\n\n const showCredentialActions = showCredentialsTab && activeTab === 'credentials' && credentialFormFields.length > 0\n\n React.useEffect(() => {\n setActiveTab(resolveRequestedIntegrationDetailTab(searchParams?.get('tab'), visibleTabIds))\n }, [searchParams, visibleTabIds])\n\n const handleTabChange = React.useCallback((nextValue: string) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n const nextTab = resolveRequestedIntegrationDetailTab(nextValue, visibleTabIds)\n setActiveTab(nextTab)\n if (!currentIntegrationId) return\n const basePath = `/backend/integrations/${encodeURIComponent(currentIntegrationId)}`\n const params = new URLSearchParams(searchParams?.toString() ?? '')\n if (nextTab === 'credentials') params.delete('tab')\n else params.set('tab', nextTab)\n const query = params.toString()\n router.replace(query ? `${basePath}?${query}` : basePath)\n }, [resolveCurrentIntegrationId, router, searchParams, visibleTabIds])\n\n React.useEffect(() => {\n if (!runIdFromUrl) {\n setActiveRunDetail(null)\n setActiveRunRefreshedAt(null)\n return\n }\n if (activeTab !== 'logs' && activeTab !== 'health') return\n\n let cancelled = false\n let timeoutId: ReturnType<typeof setTimeout> | null = null\n\n const poll = async () => {\n const detail = await refreshRunActivity()\n if (cancelled) return\n\n const status = detail?.status ?? null\n if (status === 'pending' || status === 'running') {\n timeoutId = setTimeout(() => {\n void poll()\n }, 4_000)\n }\n }\n\n void poll()\n\n return () => {\n cancelled = true\n if (timeoutId) clearTimeout(timeoutId)\n }\n }, [activeTab, refreshRunActivity, runIdFromUrl])\n\n if (isLoading) return <Page><PageBody><LoadingMessage label={t('integrations.detail.title')} /></PageBody></Page>\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('integrations.detail.notFound', 'Integration not found.')}\n backHref=\"/backend/integrations\"\n backLabel={t('integrations.detail.backToList', 'Back to integrations')}\n />\n </PageBody>\n </Page>\n )\n }\n if (error || !detail || !resolvedIntegration || !resolvedState) {\n return <Page><PageBody><ErrorMessage label={error ?? t('integrations.detail.loadError')} /></PageBody></Page>\n }\n\n return (\n <Page>\n <PageBody className=\"space-y-6\">\n <FormHeader\n backHref=\"/backend/integrations\"\n title={resolvedIntegration.title}\n actions={{\n cancelHref: showCredentialActions ? '/backend/integrations' : undefined,\n submit: showCredentialActions\n ? {\n formId: credentialsFormId,\n pending: isSavingCredentials,\n label: t('integrations.detail.credentials.save', 'Save credentials'),\n pendingLabel: t('ui.forms.status.saving', 'Saving...'),\n }\n : undefined,\n }}\n />\n\n <div className=\"space-y-2\">\n {resolvedIntegration.description ? (\n <p className=\"text-sm text-muted-foreground\">{resolvedIntegration.description}</p>\n ) : null}\n <div className=\"flex flex-wrap items-center gap-4 text-sm text-muted-foreground\">\n {resolvedIntegration.category ? (\n <div className=\"flex items-center gap-2\">\n {CategoryIcon ? <CategoryIcon className=\"h-4 w-4\" /> : null}\n <span>{formatTypeLabel(resolvedIntegration.category)}</span>\n </div>\n ) : null}\n {resolvedIntegration.hub ? (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground/80\">\n {t('integrations.detail.hub.label', 'Hub')}\n </span>\n <span>{formatTypeLabel(resolvedIntegration.hub)}</span>\n </div>\n ) : null}\n </div>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">{t('integrations.detail.analytics.title')}</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between\">\n <div className=\"space-y-1 text-sm text-muted-foreground\">\n <p>\n {t('integrations.detail.analytics.totalEvents', { count: detail.analytics.totalCount })}\n </p>\n <p>\n {t('integrations.detail.analytics.errorRate', {\n rate: `${Math.round(detail.analytics.errorRate * 1000) / 10}%`,\n })}\n </p>\n <p>\n {detail.analytics.lastActivityAt\n ? `${t('integrations.detail.analytics.lastActivity')}: ${new Date(detail.analytics.lastActivityAt).toLocaleString()}`\n : t('integrations.detail.analytics.never')}\n </p>\n </div>\n <DetailLogSparkline counts={detail.analytics.dailyCounts} />\n </CardContent>\n </Card>\n\n <section className=\"rounded-lg border bg-card p-4\">\n <div className=\"flex items-center justify-between gap-4\">\n <div className=\"space-y-2\">\n <p className=\"text-overline uppercase tracking-wide text-muted-foreground\">\n {t('integrations.detail.state.label', 'State')}\n </p>\n <Badge variant=\"outline\" className={cn('gap-1.5 rounded-full px-3 py-1 text-xs font-medium', stateBadgeClass)}>\n <StateIcon className=\"h-3.5 w-3.5\" />\n {resolvedState.isEnabled\n ? t('integrations.detail.state.enabled', 'Enabled')\n : t('integrations.detail.state.disabled', 'Disabled')}\n </Badge>\n </div>\n <Switch\n checked={resolvedState.isEnabled}\n disabled={isTogglingState}\n onCheckedChange={(checked) => void handleToggleState(checked)}\n />\n </div>\n </section>\n\n {stackedDetailWidgets.length > 0 ? (\n <section className=\"space-y-4\">\n <InjectionSpot\n spotId={detailWidgetSpotId}\n context={injectionContext}\n data={detail}\n onDataChange={(next) => setDetail(next as IntegrationDetail)}\n widgetsOverride={stackedDetailWidgets}\n />\n </section>\n ) : null}\n\n {groupedDetailWidgets.length > 0 ? (\n <section className=\"grid gap-4 lg:grid-cols-2\">\n {groupedDetailWidgets.map((widget) => (\n <Card\n key={widget.widgetId}\n className={widget.placement?.column === 2 ? 'lg:col-start-2' : undefined}\n >\n <CardHeader>\n <CardTitle>\n {widget.placement?.groupLabel\n ? t(widget.placement.groupLabel, widget.module.metadata.title)\n : widget.module.metadata.title}\n </CardTitle>\n {widget.placement?.groupDescription ? (\n <p className=\"text-sm text-muted-foreground\">\n {widget.placement.groupDescription}\n </p>\n ) : null}\n </CardHeader>\n <CardContent>\n <widget.module.Widget\n context={injectionContext}\n data={detail}\n onDataChange={(next) => setDetail(next as IntegrationDetail)}\n />\n </CardContent>\n </Card>\n ))}\n </section>\n ) : null}\n\n <Tabs value={activeTab} onValueChange={handleTabChange} className=\"space-y-5\">\n <TabsList className=\"h-auto w-full justify-start overflow-x-auto rounded-none border-b border-border bg-transparent p-0\">\n {showCredentialsTab ? (\n <TabsTrigger\n value=\"credentials\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Key className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.credentials')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {leadingInjectedTab ? (\n <TabsTrigger\n value={leadingInjectedTab.id}\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Settings className=\"h-4 w-4\" />\n <span>{leadingInjectedTab.label}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showVersionTab ? (\n <TabsTrigger\n value=\"version\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <RefreshCw className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.version')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showDataSyncScheduleTab ? (\n <TabsTrigger\n value=\"data-sync-schedule\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Calendar className=\"h-4 w-4\" />\n <span>{t('data_sync.integrationTab.title', 'Sync schedules')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showHealthTab ? (\n <TabsTrigger\n value=\"health\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Activity className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.health')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showLogsTab ? (\n <TabsTrigger\n value=\"logs\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <FileText className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.logs')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {trailingInjectedTabs.map((tab) => (\n <TabsTrigger\n key={tab.id}\n value={tab.id}\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Settings className=\"h-4 w-4\" />\n <span>{tab.label}</span>\n </span>\n </TabsTrigger>\n ))}\n </TabsList>\n\n {showCredentialsTab ? (\n <TabsContent value=\"credentials\" className=\"mt-0\">\n <section className=\"space-y-4 rounded-lg border bg-card p-6\">\n {detail.bundle ? (\n <div className=\"rounded-lg border border-status-info-border bg-status-info-bg p-3 text-sm text-status-info-text\">\n {t('integrations.detail.credentials.bundleShared', { bundle: detail.bundle.title })}\n </div>\n ) : null}\n {credentialFormFields.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('integrations.detail.credentials.notConfigured')}\n </p>\n ) : (\n <CrudForm<Record<string, unknown>>\n key={`${resolvedIntegration.id}:${credentialsFormKey}`}\n formId={credentialsFormId}\n entityId=\"integrations.integration\"\n schema={credentialSchema}\n fields={credentialFormFields}\n initialValues={credValues}\n onSubmit={handleSaveCredentials}\n embedded\n hideFooterActions\n />\n )}\n </section>\n </TabsContent>\n ) : null}\n\n {showVersionTab ? (\n <TabsContent value=\"version\" className=\"mt-0 space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle>{t('integrations.detail.version.select')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {resolvedIntegration.apiVersions?.map((version) => {\n const stableVersion = resolvedIntegration.apiVersions?.find((item) => item.status === 'stable')?.id\n const isSelected = (resolvedState.apiVersion ?? stableVersion) === version.id\n return (\n <div\n key={version.id}\n className={`flex cursor-pointer items-center justify-between rounded-lg border p-3 transition-colors ${isSelected ? 'border-primary bg-primary/5' : 'hover:bg-muted/50'}`}\n onClick={() => void handleVersionChange(version.id)}\n >\n <div>\n <span className=\"text-sm font-medium\">{version.label ?? version.id}</span>\n <Badge\n variant={version.status === 'stable' ? 'default' : version.status === 'deprecated' ? 'destructive' : 'secondary'}\n className=\"ml-2\"\n >\n {t(`integrations.detail.version.${version.status}`)}\n </Badge>\n {version.status === 'deprecated' && version.sunsetAt ? (\n <span className=\"ml-2 text-xs text-muted-foreground\">\n {t('integrations.detail.version.sunsetAt', { date: new Date(version.sunsetAt).toLocaleDateString() })}\n </span>\n ) : null}\n </div>\n {isSelected ? <Badge variant=\"outline\">{t('integrations.detail.version.current')}</Badge> : null}\n </div>\n )\n })}\n </CardContent>\n </Card>\n </TabsContent>\n ) : null}\n\n {showDataSyncScheduleTab ? (\n <TabsContent value=\"data-sync-schedule\" className=\"mt-0\">\n <IntegrationScheduleTab\n integrationId={resolvedIntegration.id}\n hasCredentials={detail.hasCredentials}\n isEnabled={resolvedState.isEnabled}\n />\n </TabsContent>\n ) : null}\n\n {showHealthTab ? (\n <TabsContent value=\"health\" className=\"mt-0 space-y-4\">\n <RunActivityStrip\n run={activeRunDetail}\n refreshedAt={activeRunRefreshedAt}\n isRefreshing={isRefreshingRunActivity}\n onRefresh={() => void refreshRunActivity({ showLoading: true })}\n t={t}\n />\n <Card className=\"gap-4 py-4\">\n <CardHeader className=\"px-5\">\n <div className=\"flex items-center justify-between\">\n <CardTitle>{t('integrations.detail.health.title')}</CardTitle>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void refreshRunActivity({ showLoading: true })}\n disabled={isRefreshingRunActivity || !runIdFromUrl}\n >\n {isRefreshingRunActivity ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('integrations.detail.runActivity.refresh', 'Refresh')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void handleHealthCheck()}\n disabled={isCheckingHealth}\n >\n {isCheckingHealth ? <Spinner className=\"mr-2 h-4 w-4\" /> : <Zap className=\"mr-2 h-4 w-4\" />}\n {isCheckingHealth ? t('integrations.detail.health.checking') : t('integrations.detail.health.check')}\n </Button>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3 px-5\">\n <div className=\"flex flex-wrap items-center gap-3 rounded-lg border bg-muted/20 px-4 py-3\">\n {displayHealthStatus ? (\n <Badge className={`gap-1.5 ${HEALTH_STATUS_STYLES[displayHealthStatus] ?? ''}`}>\n {HealthStatusIcon ? <HealthStatusIcon className=\"h-3.5 w-3.5\" /> : null}\n {t(`integrations.detail.health.${displayHealthStatus}`)}\n </Badge>\n ) : (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <AlertTriangle className=\"h-4 w-4\" />\n <span>{t('integrations.detail.health.unknown')}</span>\n </div>\n )}\n {healthStatusDescription ? (\n <p className=\"min-w-0 flex-1 text-sm text-muted-foreground\">{healthStatusDescription}</p>\n ) : null}\n <p className=\"text-xs text-muted-foreground md:ml-auto\">\n {resolvedState.lastHealthCheckedAt\n ? t('integrations.detail.health.lastChecked', { date: new Date(resolvedState.lastHealthCheckedAt).toLocaleString() })\n : t('integrations.detail.health.neverChecked')\n }\n </p>\n </div>\n {healthMessage || healthDetailEntries.length > 0 ? (\n <div className={`grid gap-3 ${healthMessage && healthDetailEntries.length > 0 ? 'xl:grid-cols-[minmax(0,1.25fr)_minmax(0,1fr)]' : ''}`}>\n {healthMessage ? (\n <div className=\"rounded-lg border px-4 py-3\">\n <p className=\"text-overline font-medium uppercase tracking-widest text-muted-foreground\">\n {t('integrations.detail.health.lastResult', 'Last result')}\n </p>\n <p className=\"mt-1.5 text-sm\">{healthMessage}</p>\n </div>\n ) : null}\n {healthDetailEntries.length > 0 ? (\n <div className=\"rounded-lg border px-4 py-3\">\n <p className=\"text-overline font-medium uppercase tracking-widest text-muted-foreground\">\n {t('integrations.detail.health.details', 'Details')}\n </p>\n <dl className=\"mt-2 grid gap-x-6 gap-y-2 sm:grid-cols-2\">\n {healthDetailEntries.map(([key, value]) => (\n <div key={key}>\n <dt className=\"text-xs font-medium text-muted-foreground\">{formatLogDetailLabel(key)}</dt>\n <dd className=\"mt-0.5 text-sm\">{formatHealthValue(value)}</dd>\n </div>\n ))}\n </dl>\n </div>\n ) : null}\n </div>\n ) : null}\n </CardContent>\n </Card>\n </TabsContent>\n ) : null}\n\n {showLogsTab ? (\n <TabsContent value=\"logs\" className=\"mt-0 space-y-4\">\n <RunActivityStrip\n run={activeRunDetail}\n refreshedAt={activeRunRefreshedAt}\n isRefreshing={isRefreshingRunActivity}\n onRefresh={() => void refreshRunActivity({ showLoading: true })}\n t={t}\n />\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"inline-flex\">\n <Select\n value={logLevel || undefined}\n onValueChange={(value) => setLogLevel(value ?? '')}\n >\n <SelectTrigger size=\"lg\" className=\"min-w-40\">\n <SelectValue placeholder={t('integrations.detail.logs.level.all')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"info\">{t('integrations.detail.logs.level.info')}</SelectItem>\n <SelectItem value=\"warn\">{t('integrations.detail.logs.level.warn')}</SelectItem>\n <SelectItem value=\"error\">{t('integrations.detail.logs.level.error')}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void refreshRunActivity({ showLoading: true })}\n disabled={isRefreshingRunActivity || !runIdFromUrl}\n >\n {isRefreshingRunActivity ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('integrations.detail.runActivity.refresh', 'Refresh')}\n </Button>\n </div>\n {isLoadingLogs ? (\n <div className=\"flex justify-center py-8\"><Spinner /></div>\n ) : (\n <LogList\n entries={logs.map<LogListEntry>((log) => {\n const metadataEntries = [\n ['Time', new Date(log.createdAt).toLocaleString()],\n ['Level', log.level],\n ['Code', log.code ?? null],\n ['Run ID', log.runId ?? null],\n ['Entity Type', log.scopeEntityType ?? null],\n ['Entity ID', log.scopeEntityId ?? null],\n ].filter((entry): entry is [string, string] => typeof entry[1] === 'string' && entry[1].trim().length > 0)\n const { inlineEntries, nestedEntries } = splitLogPayload(log.payload)\n\n return {\n id: log.id,\n time: new Date(log.createdAt).toLocaleString(),\n level: log.level,\n message: log.message,\n body: (\n <div className=\"grid gap-4 lg:grid-cols-[minmax(0,1.1fr)_minmax(0,0.9fr)]\">\n <div className=\"space-y-4\">\n <section className=\"space-y-3\">\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {t('integrations.detail.logs.details.summary', 'Summary')}\n </p>\n <p className=\"mt-1 text-sm font-medium\">{log.message}</p>\n </div>\n {metadataEntries.length > 0 ? (\n <dl className=\"grid gap-3 sm:grid-cols-2\">\n {metadataEntries.map(([label, value]) => (\n <div key={label} className=\"rounded-md border bg-muted/30 px-3 py-2\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">\n {label}\n </dt>\n <dd className=\"mt-1 break-all text-sm\">{value}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n </section>\n\n {inlineEntries.length > 0 ? (\n <section className=\"space-y-3\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {t('integrations.detail.logs.details.fields', 'Fields')}\n </p>\n <dl className=\"grid gap-3 sm:grid-cols-2\">\n {inlineEntries.map(([key, value]) => (\n <div key={key} className=\"rounded-md border bg-muted/30 px-3 py-2\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">\n {formatLogDetailLabel(key)}\n </dt>\n <dd className=\"mt-1 break-words text-sm\">\n {formatLogPrimitiveValue(value)}\n </dd>\n </div>\n ))}\n </dl>\n </section>\n ) : null}\n </div>\n\n <div className=\"space-y-3\">\n {nestedEntries.map(([key, value]) => (\n <JsonDisplay\n key={key}\n data={value}\n title={formatLogDetailLabel(key)}\n defaultExpanded\n maxInitialDepth={1}\n theme=\"dark\"\n maxHeight=\"16rem\"\n className=\"p-4\"\n />\n ))}\n {log.payload && nestedEntries.length === 0 ? (\n <JsonDisplay\n data={log.payload}\n title={t('integrations.detail.logs.details.payload', 'Payload')}\n defaultExpanded\n maxInitialDepth={1}\n theme=\"dark\"\n maxHeight=\"16rem\"\n className=\"p-4\"\n />\n ) : null}\n {!log.payload ? (\n <EmptyState\n size=\"sm\"\n icon={<FileX className=\"h-8 w-8\" aria-hidden=\"true\" />}\n title={t('integrations.detail.logs.details.noPayload', 'No structured payload was stored for this log entry.')}\n />\n ) : null}\n </div>\n </div>\n ),\n }\n })}\n emptyMessage={t('integrations.detail.logs.empty')}\n />\n )}\n </TabsContent>\n ) : null}\n\n {injectedTabs.map((tab) => (\n <TabsContent key={tab.id} value={tab.id} className=\"mt-0 space-y-4\">\n <InjectionSpot\n spotId={detailWidgetSpotId}\n context={injectionContext}\n data={detail}\n onDataChange={(next) => setDetail(next as IntegrationDetail)}\n widgetsOverride={tab.widgets}\n />\n </TabsContent>\n ))}\n </Tabs>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation'\nimport { z } from 'zod'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { CrudForm, type CrudField } from '@open-mercato/ui/backend/CrudForm'\nimport { WebhookSetupGuide } from '@open-mercato/ui/backend/WebhookSetupGuide'\nimport { InjectionSpot, useInjectionWidgets } from '@open-mercato/ui/backend/injection/InjectionSpot'\nimport { useGuardedMutation } from '@open-mercato/ui/backend/injection/useGuardedMutation'\nimport { FormHeader } from '@open-mercato/ui/backend/forms'\nimport { Card, CardHeader, CardTitle, CardContent } from '@open-mercato/ui/primitives/card'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Switch } from '@open-mercato/ui/primitives/switch'\nimport { Input } from '@open-mercato/ui/primitives/input'\nimport { PasswordInput } from '@open-mercato/ui/primitives/password-input'\nimport { Spinner } from '@open-mercato/ui/primitives/spinner'\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from '@open-mercato/ui/primitives/tabs'\nimport { JsonDisplay } from '@open-mercato/ui/backend/JsonDisplay'\nimport { apiCall, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { createCrudFormError } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport {\n LEGACY_INTEGRATION_DETAIL_TABS_SPOT_ID,\n type CredentialFieldType,\n type IntegrationCredentialField,\n type IntegrationDetailBuiltInTab,\n} from '@open-mercato/shared/modules/integrations/types'\nimport { LoadingMessage, ErrorMessage, RecordNotFoundState } from '@open-mercato/ui/backend/detail'\nimport { LogList, type LogListEntry } from '@open-mercato/ui/backend/LogList'\nimport { Activity, AlertTriangle, Bell, Calendar, CheckCircle2, CreditCard, FileText, FileX, HardDrive, Key, MessageSquare, RefreshCw, Settings, Truck, Webhook, XCircle, Zap } from 'lucide-react'\nimport { EmptyState } from '@open-mercato/ui/primitives/empty-state'\nimport { IntegrationScheduleTab } from '../../../../data_sync/components/IntegrationScheduleTab'\nimport {\n buildIntegrationDetailInjectedTabs,\n filterIntegrationDetailWidgetsByKind,\n type IntegrationDetailInjectedTab,\n resolveIntegrationDetailWidgetSpotId,\n resolveRequestedIntegrationDetailTab,\n} from '../detail-page-widgets'\nimport {\n refreshIntegrationDetailPanels,\n refreshIntegrationRunActivityPanels,\n} from '../detail-page-refresh'\nimport { isValidCredentialUrl } from '../../../lib/credentials-field-validation'\n\ntype CredentialField = IntegrationCredentialField\ntype BuiltInIntegrationDetailTab = 'credentials' | 'version' | 'health' | 'logs' | 'data-sync-schedule'\ntype IntegrationDetailTab = BuiltInIntegrationDetailTab | string\n\nconst UNSUPPORTED_CREDENTIAL_FIELD_TYPES = new Set<CredentialFieldType>(['oauth', 'ssh_keypair'])\n\nfunction isEditableCredentialField(field: CredentialField): boolean {\n return !UNSUPPORTED_CREDENTIAL_FIELD_TYPES.has(field.type)\n}\n\ntype ApiVersion = {\n id: string\n label?: string\n status: 'stable' | 'deprecated' | 'experimental'\n sunsetAt?: string\n migrationGuide?: string\n}\n\ntype IntegrationLogAnalytics = {\n lastActivityAt: string | null\n totalCount: number\n errorCount: number\n errorRate: number\n dailyCounts: number[]\n}\n\ntype IntegrationDetail = {\n integration: {\n id: string\n title: string\n description?: string\n category?: string\n hub?: string\n providerKey?: string | null\n bundleId?: string\n docsUrl?: string\n apiVersions?: ApiVersion[]\n detailPage?: {\n widgetSpotId?: string\n hiddenTabs?: IntegrationDetailBuiltInTab[]\n }\n credentials?: { fields: CredentialField[] }\n }\n bundle?: { id: string; title: string; credentials?: { fields: CredentialField[] } }\n state: {\n isEnabled: boolean\n apiVersion: string | null\n reauthRequired: boolean\n lastHealthStatus: string | null\n lastHealthCheckedAt: string | null\n lastHealthLatencyMs: number | null\n enabledAt: string | null\n updatedAt: string | null\n }\n hasCredentials: boolean\n credentialsUpdatedAt?: string | null\n healthStatus: 'healthy' | 'degraded' | 'unhealthy' | 'unconfigured'\n analytics: IntegrationLogAnalytics\n}\n\ntype LogEntry = {\n id: string\n runId?: string | null\n scopeEntityType?: string | null\n scopeEntityId?: string | null\n level: 'info' | 'warn' | 'error'\n message: string\n createdAt: string\n code?: string | null\n payload?: Record<string, unknown> | null\n}\n\ntype IntegrationDetailPageProps = {\n params?: {\n id?: string | string[]\n }\n}\n\ntype HealthCheckResponse = {\n status: 'healthy' | 'degraded' | 'unhealthy' | 'unconfigured'\n message: string | null\n details: Record<string, unknown> | null\n checkedAt: string\n latencyMs: number | null\n}\n\ntype DataSyncRunDetail = {\n id: string\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'\n progressJobId?: string | null\n createdCount?: number\n updatedCount?: number\n skippedCount?: number\n failedCount?: number\n progressJob?: {\n progressPercent?: number | null\n processedCount?: number | null\n totalCount?: number | null\n } | null\n}\n\nconst LOG_LEVEL_STYLES: Record<string, string> = {\n info: 'bg-status-info-bg text-status-info-text',\n warn: 'bg-status-warning-bg text-status-warning-text',\n error: 'bg-status-error-bg text-status-error-text',\n}\n\nconst HEALTH_STATUS_STYLES: Record<string, string> = {\n healthy: 'bg-status-success-bg text-status-success-text',\n degraded: 'bg-status-warning-bg text-status-warning-text',\n unhealthy: 'bg-status-error-bg text-status-error-text',\n unconfigured: 'bg-status-neutral-bg text-status-neutral-text',\n}\n\nconst HEALTH_STATUS_ICONS: Record<string, React.ElementType> = {\n healthy: CheckCircle2,\n degraded: AlertTriangle,\n unhealthy: XCircle,\n unconfigured: AlertTriangle,\n}\n\nfunction formatRunStatusLabel(status: DataSyncRunDetail['status'], t: ReturnType<typeof useT>): string {\n switch (status) {\n case 'pending':\n return t('integrations.detail.runActivity.status.pending', 'Pending')\n case 'running':\n return t('integrations.detail.runActivity.status.running', 'Running')\n case 'completed':\n return t('integrations.detail.runActivity.status.completed', 'Completed')\n case 'failed':\n return t('integrations.detail.runActivity.status.failed', 'Failed')\n case 'cancelled':\n return t('integrations.detail.runActivity.status.cancelled', 'Cancelled')\n default:\n return status\n }\n}\n\nfunction RunActivityStrip({\n run,\n refreshedAt,\n isRefreshing,\n onRefresh,\n t,\n}: {\n run: DataSyncRunDetail | null\n refreshedAt: string | null\n isRefreshing: boolean\n onRefresh: () => void\n t: ReturnType<typeof useT>\n}) {\n if (!run) return null\n\n const progress = typeof run.progressJob?.progressPercent === 'number' ? run.progressJob.progressPercent : 0\n const processed = typeof run.progressJob?.processedCount === 'number' ? run.progressJob.processedCount : 0\n const total = typeof run.progressJob?.totalCount === 'number' ? run.progressJob.totalCount : null\n const statusClass = run.status === 'completed'\n ? 'border-status-success-border bg-status-success-bg text-status-success-text'\n : run.status === 'failed'\n ? 'border-status-error-border bg-status-error-bg text-status-error-text'\n : run.status === 'cancelled'\n ? 'border-status-neutral-border bg-status-neutral-bg text-status-neutral-text'\n : 'border-status-info-border bg-status-info-bg text-status-info-text'\n\n return (\n <div className=\"flex flex-wrap items-center gap-3 rounded-lg border bg-muted/20 px-4 py-3 text-sm\">\n <Badge variant=\"outline\" className={cn('gap-1.5', statusClass)}>\n <RefreshCw className={cn('h-3.5 w-3.5', run.status === 'running' ? 'animate-spin' : '')} />\n {formatRunStatusLabel(run.status, t)}\n </Badge>\n <span className=\"text-muted-foreground\">\n {t('integrations.detail.runActivity.processed', 'Processed')}: <span className=\"font-medium text-foreground\">{processed}{total !== null ? ` / ${total}` : ''}</span>\n </span>\n <span className=\"text-muted-foreground\">\n {t('integrations.detail.runActivity.progress', 'Progress')}: <span className=\"font-medium text-foreground\">{progress}%</span>\n </span>\n {refreshedAt ? (\n <span className=\"text-muted-foreground\">\n {t('integrations.detail.runActivity.lastRefreshed', 'Last refreshed')}: {new Date(refreshedAt).toLocaleTimeString()}\n </span>\n ) : null}\n <Button type=\"button\" variant=\"outline\" size=\"sm\" className=\"ml-auto\" onClick={onRefresh} disabled={isRefreshing}>\n {isRefreshing ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('integrations.detail.runActivity.refresh', 'Refresh')}\n </Button>\n </div>\n )\n}\n\nfunction DetailLogSparkline({ counts, className }: { counts: number[]; className?: string }) {\n const max = Math.max(1, ...counts)\n const w = 120\n const h = 36\n const step = counts.length > 1 ? w / (counts.length - 1) : w\n const points = counts.map((count, index) => {\n const x = index * step\n const y = h - (count / max) * (h - 4) - 2\n return `${x},${y}`\n }).join(' ')\n return (\n <svg width={w} height={h} className={className} aria-hidden>\n <polyline\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n points={points}\n className=\"text-muted-foreground/80\"\n />\n </svg>\n )\n}\n\nconst CATEGORY_ICONS: Record<string, React.ElementType> = {\n payment: CreditCard,\n shipping: Truck,\n data_sync: RefreshCw,\n communication: MessageSquare,\n notification: Bell,\n storage: HardDrive,\n webhook: Webhook,\n}\n\nfunction resolveRouteId(value: string | string[] | undefined): string | undefined {\n if (Array.isArray(value)) return value[0]\n return value\n}\n\nfunction resolvePathnameId(pathname: string): string | undefined {\n const parts = pathname.split('/').filter(Boolean)\n const integrationId = parts.at(-1)\n if (!integrationId || integrationId === 'integrations' || integrationId === 'bundle') return undefined\n return decodeURIComponent(integrationId)\n}\n\nfunction buildCredentialFields(credFields: CredentialField[]): CrudField[] {\n return credFields.map((field) => {\n const shared = {\n id: field.key,\n label: field.label,\n description: field.helpDetails ? (\n <div className=\"space-y-1\">\n {field.helpText ? <div>{field.helpText}</div> : null}\n <WebhookSetupGuide guide={field.helpDetails} buttonLabel=\"Show details\" />\n </div>\n ) : field.helpText,\n placeholder: field.placeholder,\n required: field.required,\n visibleWhen: field.visibleWhen,\n }\n\n if (field.type === 'secret') {\n return {\n ...shared,\n type: 'custom' as const,\n component: ({ id, value, setValue, disabled }) => (\n <PasswordInput\n id={id}\n placeholder={field.placeholder}\n value={typeof value === 'string' ? value : ''}\n onChange={(event) => setValue(event.target.value)}\n disabled={disabled}\n />\n ),\n }\n }\n\n if (field.type === 'select' && field.options) {\n return {\n ...shared,\n type: 'select' as const,\n options: field.options,\n }\n }\n\n if (field.type === 'boolean') {\n return {\n ...shared,\n type: 'checkbox' as const,\n }\n }\n\n return {\n ...shared,\n type: 'text' as const,\n }\n })\n}\n\nfunction isHealthLog(log: LogEntry): boolean {\n return log.message === 'Health check passed' || log.message.startsWith('Health check:')\n}\n\nfunction extractHealthDetails(payload: Record<string, unknown> | null | undefined): Record<string, unknown> {\n if (!payload) return {}\n return Object.fromEntries(\n Object.entries(payload).filter(([key, value]) => key !== 'status' && key !== 'message' && value !== undefined && value !== null),\n )\n}\n\nfunction formatHealthValue(value: unknown): string {\n if (typeof value === 'boolean') return value ? 'Yes' : 'No'\n if (typeof value === 'string') return value\n if (typeof value === 'number') return String(value)\n if (value instanceof Date) return value.toLocaleString()\n return JSON.stringify(value)\n}\n\nfunction formatTypeLabel(value: string): string {\n return value.split('_').filter(Boolean).map((part) => part[0]?.toUpperCase() + part.slice(1)).join(' ')\n}\n\nfunction isPrimitiveLogValue(value: unknown): value is string | number | boolean | null {\n return value === null || typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'\n}\n\nfunction formatLogDetailLabel(key: string): string {\n return key\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .split(' ')\n .filter(Boolean)\n .map((part) => part[0]?.toUpperCase() + part.slice(1))\n .join(' ')\n}\n\nfunction formatLogPrimitiveValue(value: string | number | boolean | null): string {\n if (value === null) return 'None'\n if (typeof value === 'boolean') return value ? 'Yes' : 'No'\n return String(value)\n}\n\nfunction isAkeneoSettingsTab(tab: IntegrationDetailInjectedTab): boolean {\n return tab.id.includes('sync_akeneo') || tab.label.toLowerCase().includes('akeneo')\n}\n\nfunction splitLogPayload(payload: Record<string, unknown> | null | undefined) {\n if (!payload) {\n return {\n inlineEntries: [] as Array<[string, string | number | boolean | null]>,\n nestedEntries: [] as Array<[string, unknown]>,\n }\n }\n\n const inlineEntries: Array<[string, string | number | boolean | null]> = []\n const nestedEntries: Array<[string, unknown]> = []\n\n Object.entries(payload).forEach(([key, value]) => {\n if (isPrimitiveLogValue(value)) {\n inlineEntries.push([key, value])\n return\n }\n nestedEntries.push([key, value])\n })\n\n return { inlineEntries, nestedEntries }\n}\n\nexport default function IntegrationDetailPage({ params }: IntegrationDetailPageProps) {\n const pathname = usePathname()\n const router = useRouter()\n const searchParams = useSearchParams()\n const integrationId = resolveRouteId(params?.id) ?? resolvePathnameId(pathname)\n const t = useT()\n\n const [detail, setDetail] = React.useState<IntegrationDetail | null>(null)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n const [isNotFound, setIsNotFound] = React.useState(false)\n\n const [credValues, setCredValues] = React.useState<Record<string, unknown>>({})\n const [credentialsUpdatedAt, setCredentialsUpdatedAt] = React.useState<string | null>(null)\n const [credentialsFormKey, setCredentialsFormKey] = React.useState(0)\n const [isSavingCredentials, setIsSavingCredentials] = React.useState(false)\n\n const [logs, setLogs] = React.useState<LogEntry[]>([])\n const [logLevel, setLogLevel] = React.useState<string>('')\n const [isLoadingLogs, setIsLoadingLogs] = React.useState(false)\n\n const [isCheckingHealth, setIsCheckingHealth] = React.useState(false)\n const [isTogglingState, setIsTogglingState] = React.useState(false)\n const [latestHealthResult, setLatestHealthResult] = React.useState<HealthCheckResponse | null>(null)\n const [activeRunDetail, setActiveRunDetail] = React.useState<DataSyncRunDetail | null>(null)\n const [activeRunRefreshedAt, setActiveRunRefreshedAt] = React.useState<string | null>(null)\n const [isRefreshingRunActivity, setIsRefreshingRunActivity] = React.useState(false)\n const [activeTab, setActiveTab] = React.useState<IntegrationDetailTab>('credentials')\n\n const credentialsFormId = React.useId()\n\n const resolveCurrentIntegrationId = React.useCallback(() => {\n return integrationId ?? (\n typeof window !== 'undefined'\n ? resolvePathnameId(window.location.pathname)\n : undefined\n )\n }, [integrationId])\n\n const loadDetail = React.useCallback(async (options?: { showLoading?: boolean }) => {\n const showLoading = options?.showLoading ?? true\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) {\n if (showLoading) setIsLoading(false)\n if (showLoading) setError(t('integrations.detail.loadError', 'Failed to load integration'))\n return\n }\n if (showLoading) setError(null)\n if (showLoading) setIsNotFound(false)\n if (showLoading) setIsLoading(true)\n try {\n const call = await apiCall<IntegrationDetail>(\n `/api/integrations/${encodeURIComponent(currentIntegrationId)}`,\n undefined,\n { fallback: null },\n )\n if (!call.ok || !call.result) {\n if (call.status === 404) {\n if (showLoading) setIsNotFound(true)\n } else {\n if (showLoading) setError(t('integrations.detail.loadError', 'Failed to load integration'))\n }\n if (showLoading) setIsLoading(false)\n return\n }\n setDetail(call.result)\n setError(null)\n if (showLoading) setIsLoading(false)\n } catch {\n if (showLoading) setError(t('integrations.detail.loadError', 'Failed to load integration'))\n if (showLoading) setIsLoading(false)\n }\n }, [resolveCurrentIntegrationId, t])\n\n const loadCredentials = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n const call = await apiCall<{ credentials: Record<string, unknown>; updatedAt?: string | null }>(\n `/api/integrations/${encodeURIComponent(currentIntegrationId)}/credentials`,\n undefined,\n { fallback: null },\n )\n if (call.ok && call.result) {\n setCredentialsUpdatedAt(call.result.updatedAt ?? null)\n }\n if (call.ok && call.result?.credentials) {\n const next = { ...call.result.credentials }\n if (currentIntegrationId === 'storage_s3') {\n const authMode = next.authMode\n if (authMode !== 'access_keys' && authMode !== 'ambient') {\n const hasKeys = Boolean(next.accessKeyId || next.secretAccessKey)\n next.authMode = hasKeys ? 'access_keys' : 'ambient'\n }\n }\n setCredValues(next)\n setCredentialsFormKey((current) => current + 1)\n }\n }, [resolveCurrentIntegrationId])\n\n const loadLogs = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsLoadingLogs(true)\n const params = new URLSearchParams({ integrationId: currentIntegrationId, pageSize: '50' })\n if (logLevel) params.set('level', logLevel)\n const call = await apiCall<{ items: LogEntry[] }>(\n `/api/integrations/logs?${params.toString()}`,\n undefined,\n { fallback: { items: [] } },\n )\n if (call.ok && call.result) {\n setLogs(call.result.items)\n }\n setIsLoadingLogs(false)\n }, [logLevel, resolveCurrentIntegrationId])\n\n const detailWidgetSpotId = React.useMemo(\n () => resolveIntegrationDetailWidgetSpotId(detail?.integration ?? null, LEGACY_INTEGRATION_DETAIL_TABS_SPOT_ID),\n [detail?.integration],\n )\n const mutationContextId = React.useMemo(\n () => `integrations.detail:${integrationId ?? 'unknown'}`,\n [integrationId],\n )\n const { runMutation, retryLastMutation } = useGuardedMutation<Record<string, unknown>>({\n contextId: mutationContextId,\n spotId: detailWidgetSpotId,\n })\n const refreshDetail = React.useCallback(async () => {\n await refreshIntegrationDetailPanels({ loadDetail, loadCredentials })\n }, [loadCredentials, loadDetail])\n const refreshLogs = React.useCallback(async () => {\n await loadLogs()\n }, [loadLogs])\n const refreshHealthSnapshot = React.useCallback(async () => {\n await loadDetail({ showLoading: false })\n }, [loadDetail])\n const runIdFromUrl = searchParams?.get('runId') ?? null\n const refreshRunActivity = React.useCallback(async (options?: { showLoading?: boolean }) => {\n if (!runIdFromUrl) {\n setActiveRunDetail(null)\n setActiveRunRefreshedAt(null)\n return null\n }\n if (options?.showLoading) setIsRefreshingRunActivity(true)\n try {\n const [call] = await Promise.all([\n apiCall<DataSyncRunDetail>(\n `/api/data_sync/runs/${encodeURIComponent(runIdFromUrl)}`,\n undefined,\n { fallback: null },\n ),\n refreshIntegrationRunActivityPanels({ loadLogs, loadDetail }),\n ])\n if (call.ok && call.result) {\n setActiveRunDetail(call.result)\n setActiveRunRefreshedAt(new Date().toISOString())\n return call.result\n }\n return null\n } finally {\n if (options?.showLoading) setIsRefreshingRunActivity(false)\n }\n }, [loadDetail, loadLogs, runIdFromUrl])\n const injectionContext = React.useMemo(\n () => ({\n formId: mutationContextId,\n integrationDetailWidgetSpotId: detailWidgetSpotId,\n resourceKind: 'integrations.integration',\n resourceId: integrationId ?? detail?.integration.id,\n integrationId: integrationId ?? detail?.integration.id,\n integration: detail?.integration ?? null,\n detail,\n state: detail?.state ?? null,\n credentialValues: credValues,\n latestHealthResult,\n activeTab,\n setActiveTab,\n refreshDetail,\n refreshLogs,\n refreshHealthSnapshot,\n retryLastMutation,\n }),\n [\n activeTab,\n credValues,\n detail,\n detailWidgetSpotId,\n integrationId,\n latestHealthResult,\n mutationContextId,\n refreshDetail,\n refreshHealthSnapshot,\n refreshLogs,\n retryLastMutation,\n ],\n )\n const { widgets: detailWidgets } = useInjectionWidgets(detailWidgetSpotId, {\n context: injectionContext,\n triggerOnLoad: true,\n })\n const stackedDetailWidgets = React.useMemo(\n () => filterIntegrationDetailWidgetsByKind(detailWidgets, 'stack'),\n [detailWidgets],\n )\n const groupedDetailWidgets = React.useMemo(\n () => filterIntegrationDetailWidgetsByKind(detailWidgets, 'group'),\n [detailWidgets],\n )\n const injectedTabs = React.useMemo(\n () => buildIntegrationDetailInjectedTabs(\n detailWidgets,\n (widget) => (\n widget.placement?.groupLabel\n ? t(widget.placement.groupLabel, widget.module.metadata.title ?? widget.widgetId)\n : (widget.module.metadata.title ?? widget.widgetId)\n ),\n ),\n [detailWidgets, t],\n )\n const hasDataSyncScheduleTab = Boolean(\n detail?.integration.hub === 'data_sync'\n && detail?.integration.providerKey\n && detail.integration.providerKey.trim().length > 0,\n )\n const runMutationWithContext = React.useCallback(\n async <T,>({\n operation,\n mutationPayload,\n actionId,\n tabId,\n operationType = 'update',\n }: {\n operation: () => Promise<T>\n mutationPayload?: Record<string, unknown>\n actionId: string\n tabId?: string\n operationType?: 'create' | 'update' | 'delete'\n }): Promise<T> => {\n return runMutation({\n operation,\n mutationPayload,\n context: {\n ...injectionContext,\n operation: operationType,\n actionId,\n activeTab: tabId ?? activeTab,\n },\n })\n },\n [activeTab, injectionContext, runMutation],\n )\n\n React.useEffect(() => { void loadDetail() }, [loadDetail])\n React.useEffect(() => { void loadCredentials() }, [loadCredentials])\n React.useEffect(() => { void loadLogs() }, [loadLogs])\n\n const handleToggleState = React.useCallback(async (enabled: boolean) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsTogglingState(true)\n try {\n const call = await runMutationWithContext({\n actionId: 'toggle-state',\n mutationPayload: { integrationId: currentIntegrationId, isEnabled: enabled },\n operation: () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(detail?.state.updatedAt),\n () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/state`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ isEnabled: enabled }),\n }, { fallback: null }),\n ),\n })\n if (call.ok) {\n setDetail((prev) => prev ? {\n ...prev,\n state: {\n ...prev.state,\n isEnabled: enabled,\n enabledAt: enabled ? new Date().toISOString() : prev.state.enabledAt,\n },\n } : prev)\n flash(t('integrations.detail.stateUpdated'), 'success')\n void refreshDetail()\n } else {\n flash(t('integrations.detail.stateError'), 'error')\n }\n } catch {\n flash(t('integrations.detail.stateError'), 'error')\n } finally {\n setIsTogglingState(false)\n }\n }, [detail?.state.updatedAt, refreshDetail, resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const handleSaveCredentials = React.useCallback(async (values: Record<string, unknown>) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsSavingCredentials(true)\n try {\n const sanitizedValues = { ...values }\n if (currentIntegrationId === 'storage_s3') {\n const authMode = sanitizedValues.authMode\n if (authMode !== 'access_keys' && authMode !== 'ambient') {\n const hasKeys = Boolean(sanitizedValues.accessKeyId || sanitizedValues.secretAccessKey)\n sanitizedValues.authMode = hasKeys ? 'access_keys' : 'ambient'\n }\n if (sanitizedValues.authMode === 'ambient') {\n delete sanitizedValues.accessKeyId\n delete sanitizedValues.secretAccessKey\n delete sanitizedValues.sessionToken\n }\n }\n const call = await runMutationWithContext({\n actionId: 'save-credentials',\n tabId: 'credentials',\n mutationPayload: { integrationId: currentIntegrationId, credentials: sanitizedValues },\n operation: () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(credentialsUpdatedAt),\n () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/credentials`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ credentials: sanitizedValues }),\n }, { fallback: null }),\n ),\n })\n\n if (call.ok) {\n setCredValues(sanitizedValues)\n setCredentialsFormKey((current) => current + 1)\n flash(t('integrations.detail.credentials.saved'), 'success')\n void loadCredentials()\n return\n }\n\n const result = call.result as {\n error?: string\n details?: { fieldErrors?: Record<string, string>; formErrors?: string[] }\n } | null\n throw createCrudFormError(\n result?.error ?? t('integrations.detail.credentials.saveError', 'Failed to save credentials'),\n result?.details?.fieldErrors,\n { details: result?.details },\n )\n } finally {\n setIsSavingCredentials(false)\n }\n }, [credentialsUpdatedAt, loadCredentials, resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const handleVersionChange = React.useCallback(async (version: string) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n try {\n const call = await runMutationWithContext({\n actionId: 'change-version',\n tabId: 'version',\n mutationPayload: { integrationId: currentIntegrationId, apiVersion: version },\n operation: () => withScopedApiRequestHeaders(\n buildOptimisticLockHeader(detail?.state.updatedAt),\n () => apiCall(`/api/integrations/${encodeURIComponent(currentIntegrationId)}/version`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ apiVersion: version }),\n }, { fallback: null }),\n ),\n })\n if (call.ok) {\n setDetail((prev) => prev ? { ...prev, state: { ...prev.state, apiVersion: version } } : prev)\n flash(t('integrations.detail.version.saved'), 'success')\n void refreshDetail()\n } else {\n flash(t('integrations.detail.version.saveError'), 'error')\n }\n } catch {\n flash(t('integrations.detail.version.saveError'), 'error')\n }\n }, [detail?.state.updatedAt, refreshDetail, resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const handleHealthCheck = React.useCallback(async () => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n if (!currentIntegrationId) return\n setIsCheckingHealth(true)\n try {\n const call = await runMutationWithContext({\n actionId: 'run-health-check',\n tabId: 'health',\n mutationPayload: { integrationId: currentIntegrationId },\n operation: () => apiCall<HealthCheckResponse>(\n `/api/integrations/${encodeURIComponent(currentIntegrationId)}/health`,\n { method: 'POST' },\n { fallback: null },\n ),\n })\n const result = call.result\n if (call.ok && result) {\n setLatestHealthResult(result)\n setDetail((prev) => prev ? {\n ...prev,\n healthStatus: result.status,\n state: {\n ...prev.state,\n lastHealthStatus: result.status === 'unconfigured' ? prev.state.lastHealthStatus : result.status,\n lastHealthCheckedAt: result.status === 'unconfigured' ? prev.state.lastHealthCheckedAt : result.checkedAt,\n lastHealthLatencyMs: result.latencyMs ?? prev.state.lastHealthLatencyMs,\n },\n } : prev)\n void refreshLogs()\n } else {\n flash(t('integrations.detail.health.checkError'), 'error')\n }\n } catch {\n flash(t('integrations.detail.health.checkError'), 'error')\n } finally {\n setIsCheckingHealth(false)\n }\n }, [refreshLogs, resolveCurrentIntegrationId, runMutationWithContext, t])\n\n const hasVersions = Boolean(detail?.integration.apiVersions?.length)\n const integration = detail?.integration ?? null\n const state = detail?.state ?? null\n const editableCredentialFields = React.useMemo(\n () => (detail?.integration.credentials?.fields ?? detail?.bundle?.credentials?.fields ?? []).filter(isEditableCredentialField),\n [detail?.bundle?.credentials?.fields, detail?.integration.credentials?.fields],\n )\n const credentialFormFields = React.useMemo(\n () => buildCredentialFields(editableCredentialFields),\n [editableCredentialFields],\n )\n const credentialSchema = React.useMemo(() => (\n z.object({}).passthrough().superRefine((rawValues, ctx) => {\n const values = rawValues as Record<string, unknown>\n\n editableCredentialFields.forEach((field) => {\n if (field.visibleWhen) {\n const targetValue = values[field.visibleWhen.field]\n if (targetValue !== field.visibleWhen.equals) return\n }\n const value = values[field.key]\n\n if (field.type === 'boolean') {\n if (value !== undefined && value !== null && typeof value !== 'boolean') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.boolean', 'Select a valid value.'),\n })\n }\n if (field.required && typeof value !== 'boolean') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.required', '{field} is required.', { field: field.label }),\n })\n }\n return\n }\n\n if (value !== undefined && value !== null && typeof value !== 'string') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.text', 'Enter a valid value.'),\n })\n return\n }\n\n const normalizedValue = typeof value === 'string' ? value : ''\n\n if (field.required && normalizedValue.trim().length === 0) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.required', '{field} is required.', { field: field.label }),\n })\n }\n\n if (normalizedValue.length > 20_000) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.tooLong', 'Value is too long.'),\n })\n }\n\n if (\n field.type === 'url'\n && normalizedValue.trim().length > 0\n && !isValidCredentialUrl(normalizedValue.trim())\n ) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.url', '{field} must be a valid http(s) URL.', { field: field.label }),\n })\n }\n\n if (\n field.type === 'select'\n && normalizedValue\n && field.options\n && !field.options.some((option) => option.value === normalizedValue)\n ) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: [field.key],\n message: t('integrations.detail.credentials.validation.option', 'Select one of the available options.'),\n })\n }\n })\n })\n ) as z.ZodType<Record<string, unknown>>, [editableCredentialFields, t])\n const latestHealthLog = React.useMemo(() => logs.find(isHealthLog) ?? null, [logs])\n const latestOperationalLog = React.useMemo(\n () => logs.find((log) => (\n typeof log.payload?.operationalStatus === 'string'\n || typeof log.payload?.summary === 'string'\n )) ?? null,\n [logs],\n )\n const healthMessage =\n latestHealthResult?.message ??\n (typeof latestHealthLog?.payload?.message === 'string'\n ? latestHealthLog.payload.message\n : typeof latestOperationalLog?.payload?.summary === 'string'\n ? latestOperationalLog.payload.summary\n : null)\n const healthDetailsSource = latestHealthResult?.details ?? extractHealthDetails(latestHealthLog?.payload ?? latestOperationalLog?.payload)\n const healthDetails = latestHealthLog?.code\n ? { ...healthDetailsSource, code: latestHealthLog.code }\n : healthDetailsSource\n const healthDetailEntries = Object.entries(healthDetails)\n const resolvedIntegration = detail?.integration ?? null\n const resolvedState = detail?.state ?? null\n const displayHealthStatus =\n latestHealthResult?.status ?? detail?.healthStatus ?? resolvedState?.lastHealthStatus ?? 'unconfigured'\n\n const healthStatusDescription = displayHealthStatus && displayHealthStatus !== 'unconfigured'\n ? t(\n `integrations.detail.health.meaning.${displayHealthStatus}`,\n displayHealthStatus === 'healthy'\n ? 'The provider responded successfully using the current credentials.'\n : displayHealthStatus === 'degraded'\n ? 'The provider responded, but reported warnings or limited functionality.'\n : integration?.id === 'gateway_stripe'\n ? 'Stripe rejected the last check. This usually means the secret key is invalid, missing required permissions, revoked, or Stripe was temporarily unavailable.'\n : 'The last check failed. This usually means invalid credentials, missing permissions, or a provider outage.',\n )\n : displayHealthStatus === 'unconfigured'\n ? t(\n 'integrations.detail.health.meaning.unconfigured',\n 'Credentials or a health check are not configured, or the integration has not been probed yet.',\n )\n : null\n\n const CategoryIcon = resolvedIntegration?.category ? CATEGORY_ICONS[resolvedIntegration.category] : null\n const HealthStatusIcon = HEALTH_STATUS_ICONS[displayHealthStatus] ?? null\n const prioritizedInjectedTabs = resolvedIntegration?.id === 'sync_akeneo'\n ? [...injectedTabs].sort((left, right) => {\n const leftPriority = isAkeneoSettingsTab(left) ? 1 : 0\n const rightPriority = isAkeneoSettingsTab(right) ? 1 : 0\n if (leftPriority !== rightPriority) return rightPriority - leftPriority\n return 0\n })\n : injectedTabs\n const leadingInjectedTab = resolvedIntegration?.id === 'sync_akeneo'\n ? prioritizedInjectedTabs.find(isAkeneoSettingsTab) ?? null\n : null\n const trailingInjectedTabs = leadingInjectedTab\n ? prioritizedInjectedTabs.filter((tab) => tab.id !== leadingInjectedTab.id)\n : prioritizedInjectedTabs\n const hiddenBuiltInTabs = new Set(resolvedIntegration?.detailPage?.hiddenTabs ?? [])\n const showCredentialsTab = !hiddenBuiltInTabs.has('credentials')\n const showVersionTab = hasVersions && !hiddenBuiltInTabs.has('version')\n const showDataSyncScheduleTab = hasDataSyncScheduleTab && !hiddenBuiltInTabs.has('data-sync-schedule')\n const showHealthTab = !hiddenBuiltInTabs.has('health')\n const showLogsTab = !hiddenBuiltInTabs.has('logs')\n const visibleTabIds = [\n ...(showCredentialsTab ? ['credentials'] : []),\n ...(leadingInjectedTab ? [leadingInjectedTab.id] : []),\n ...(showVersionTab ? ['version'] : []),\n ...(showDataSyncScheduleTab ? ['data-sync-schedule'] : []),\n ...(showHealthTab ? ['health'] : []),\n ...(showLogsTab ? ['logs'] : []),\n ...trailingInjectedTabs.map((tab) => tab.id),\n ] satisfies IntegrationDetailTab[]\n const StateIcon = resolvedState?.isEnabled ? CheckCircle2 : XCircle\n const stateBadgeClass = resolvedState?.isEnabled\n ? 'border-status-success-border bg-status-success-bg text-status-success-text'\n : 'border-status-neutral-border bg-status-neutral-bg text-status-neutral-text'\n\n const showCredentialActions = showCredentialsTab && activeTab === 'credentials' && credentialFormFields.length > 0\n\n React.useEffect(() => {\n setActiveTab(resolveRequestedIntegrationDetailTab(searchParams?.get('tab'), visibleTabIds))\n }, [searchParams, visibleTabIds])\n\n const handleTabChange = React.useCallback((nextValue: string) => {\n const currentIntegrationId = resolveCurrentIntegrationId()\n const nextTab = resolveRequestedIntegrationDetailTab(nextValue, visibleTabIds)\n setActiveTab(nextTab)\n if (!currentIntegrationId) return\n const basePath = `/backend/integrations/${encodeURIComponent(currentIntegrationId)}`\n const params = new URLSearchParams(searchParams?.toString() ?? '')\n if (nextTab === 'credentials') params.delete('tab')\n else params.set('tab', nextTab)\n const query = params.toString()\n router.replace(query ? `${basePath}?${query}` : basePath)\n }, [resolveCurrentIntegrationId, router, searchParams, visibleTabIds])\n\n React.useEffect(() => {\n if (!runIdFromUrl) {\n setActiveRunDetail(null)\n setActiveRunRefreshedAt(null)\n return\n }\n if (activeTab !== 'logs' && activeTab !== 'health') return\n\n let cancelled = false\n let timeoutId: ReturnType<typeof setTimeout> | null = null\n\n const poll = async () => {\n const detail = await refreshRunActivity()\n if (cancelled) return\n\n const status = detail?.status ?? null\n if (status === 'pending' || status === 'running') {\n timeoutId = setTimeout(() => {\n void poll()\n }, 4_000)\n }\n }\n\n void poll()\n\n return () => {\n cancelled = true\n if (timeoutId) clearTimeout(timeoutId)\n }\n }, [activeTab, refreshRunActivity, runIdFromUrl])\n\n if (isLoading) return <Page><PageBody><LoadingMessage label={t('integrations.detail.title')} /></PageBody></Page>\n if (isNotFound) {\n return (\n <Page>\n <PageBody>\n <RecordNotFoundState\n label={t('integrations.detail.notFound', 'Integration not found.')}\n backHref=\"/backend/integrations\"\n backLabel={t('integrations.detail.backToList', 'Back to integrations')}\n />\n </PageBody>\n </Page>\n )\n }\n if (error || !detail || !resolvedIntegration || !resolvedState) {\n return <Page><PageBody><ErrorMessage label={error ?? t('integrations.detail.loadError')} /></PageBody></Page>\n }\n\n return (\n <Page>\n <PageBody className=\"space-y-6\">\n <FormHeader\n backHref=\"/backend/integrations\"\n title={resolvedIntegration.title}\n actions={{\n cancelHref: showCredentialActions ? '/backend/integrations' : undefined,\n submit: showCredentialActions\n ? {\n formId: credentialsFormId,\n pending: isSavingCredentials,\n label: t('integrations.detail.credentials.save', 'Save credentials'),\n pendingLabel: t('ui.forms.status.saving', 'Saving...'),\n }\n : undefined,\n }}\n />\n\n <div className=\"space-y-2\">\n {resolvedIntegration.description ? (\n <p className=\"text-sm text-muted-foreground\">{resolvedIntegration.description}</p>\n ) : null}\n <div className=\"flex flex-wrap items-center gap-4 text-sm text-muted-foreground\">\n {resolvedIntegration.category ? (\n <div className=\"flex items-center gap-2\">\n {CategoryIcon ? <CategoryIcon className=\"h-4 w-4\" /> : null}\n <span>{formatTypeLabel(resolvedIntegration.category)}</span>\n </div>\n ) : null}\n {resolvedIntegration.hub ? (\n <div className=\"flex items-center gap-2\">\n <span className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground/80\">\n {t('integrations.detail.hub.label', 'Hub')}\n </span>\n <span>{formatTypeLabel(resolvedIntegration.hub)}</span>\n </div>\n ) : null}\n </div>\n </div>\n\n <Card>\n <CardHeader>\n <CardTitle className=\"text-base\">{t('integrations.detail.analytics.title')}</CardTitle>\n </CardHeader>\n <CardContent className=\"flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between\">\n <div className=\"space-y-1 text-sm text-muted-foreground\">\n <p>\n {t('integrations.detail.analytics.totalEvents', { count: detail.analytics.totalCount })}\n </p>\n <p>\n {t('integrations.detail.analytics.errorRate', {\n rate: `${Math.round(detail.analytics.errorRate * 1000) / 10}%`,\n })}\n </p>\n <p>\n {detail.analytics.lastActivityAt\n ? `${t('integrations.detail.analytics.lastActivity')}: ${new Date(detail.analytics.lastActivityAt).toLocaleString()}`\n : t('integrations.detail.analytics.never')}\n </p>\n </div>\n <DetailLogSparkline counts={detail.analytics.dailyCounts} />\n </CardContent>\n </Card>\n\n <section className=\"rounded-lg border bg-card p-4\">\n <div className=\"flex items-center justify-between gap-4\">\n <div className=\"space-y-2\">\n <p className=\"text-overline uppercase tracking-wide text-muted-foreground\">\n {t('integrations.detail.state.label', 'State')}\n </p>\n <Badge variant=\"outline\" className={cn('gap-1.5 rounded-full px-3 py-1 text-xs font-medium', stateBadgeClass)}>\n <StateIcon className=\"h-3.5 w-3.5\" />\n {resolvedState.isEnabled\n ? t('integrations.detail.state.enabled', 'Enabled')\n : t('integrations.detail.state.disabled', 'Disabled')}\n </Badge>\n </div>\n <Switch\n checked={resolvedState.isEnabled}\n disabled={isTogglingState}\n onCheckedChange={(checked) => void handleToggleState(checked)}\n />\n </div>\n </section>\n\n {stackedDetailWidgets.length > 0 ? (\n <section className=\"space-y-4\">\n <InjectionSpot\n spotId={detailWidgetSpotId}\n context={injectionContext}\n data={detail}\n onDataChange={(next) => setDetail(next as IntegrationDetail)}\n widgetsOverride={stackedDetailWidgets}\n />\n </section>\n ) : null}\n\n {groupedDetailWidgets.length > 0 ? (\n <section className=\"grid gap-4 lg:grid-cols-2\">\n {groupedDetailWidgets.map((widget) => (\n <Card\n key={widget.widgetId}\n className={widget.placement?.column === 2 ? 'lg:col-start-2' : undefined}\n >\n <CardHeader>\n <CardTitle>\n {widget.placement?.groupLabel\n ? t(widget.placement.groupLabel, widget.module.metadata.title)\n : widget.module.metadata.title}\n </CardTitle>\n {widget.placement?.groupDescription ? (\n <p className=\"text-sm text-muted-foreground\">\n {widget.placement.groupDescription}\n </p>\n ) : null}\n </CardHeader>\n <CardContent>\n <widget.module.Widget\n context={injectionContext}\n data={detail}\n onDataChange={(next) => setDetail(next as IntegrationDetail)}\n />\n </CardContent>\n </Card>\n ))}\n </section>\n ) : null}\n\n <Tabs value={activeTab} onValueChange={handleTabChange} className=\"space-y-5\">\n <TabsList className=\"h-auto w-full justify-start overflow-x-auto rounded-none border-b border-border bg-transparent p-0\">\n {showCredentialsTab ? (\n <TabsTrigger\n value=\"credentials\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Key className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.credentials')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {leadingInjectedTab ? (\n <TabsTrigger\n value={leadingInjectedTab.id}\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Settings className=\"h-4 w-4\" />\n <span>{leadingInjectedTab.label}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showVersionTab ? (\n <TabsTrigger\n value=\"version\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <RefreshCw className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.version')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showDataSyncScheduleTab ? (\n <TabsTrigger\n value=\"data-sync-schedule\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Calendar className=\"h-4 w-4\" />\n <span>{t('data_sync.integrationTab.title', 'Sync schedules')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showHealthTab ? (\n <TabsTrigger\n value=\"health\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Activity className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.health')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {showLogsTab ? (\n <TabsTrigger\n value=\"logs\"\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <FileText className=\"h-4 w-4\" />\n <span>{t('integrations.detail.tabs.logs')}</span>\n </span>\n </TabsTrigger>\n ) : null}\n {trailingInjectedTabs.map((tab) => (\n <TabsTrigger\n key={tab.id}\n value={tab.id}\n className=\"mr-8 h-auto rounded-none border-b-2 border-transparent bg-transparent px-0 py-2.5 text-sm font-medium text-muted-foreground shadow-none transition-colors hover:bg-transparent hover:text-foreground aria-selected:border-accent-indigo aria-selected:bg-transparent aria-selected:text-foreground aria-selected:shadow-none last:mr-0\"\n >\n <span className=\"inline-flex items-center gap-2\">\n <Settings className=\"h-4 w-4\" />\n <span>{tab.label}</span>\n </span>\n </TabsTrigger>\n ))}\n </TabsList>\n\n {showCredentialsTab ? (\n <TabsContent value=\"credentials\" className=\"mt-0\">\n <section className=\"space-y-4 rounded-lg border bg-card p-6\">\n {detail.bundle ? (\n <div className=\"rounded-lg border border-status-info-border bg-status-info-bg p-3 text-sm text-status-info-text\">\n {t('integrations.detail.credentials.bundleShared', { bundle: detail.bundle.title })}\n </div>\n ) : null}\n {credentialFormFields.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {t('integrations.detail.credentials.notConfigured')}\n </p>\n ) : (\n <CrudForm<Record<string, unknown>>\n key={`${resolvedIntegration.id}:${credentialsFormKey}`}\n formId={credentialsFormId}\n entityId=\"integrations.integration\"\n schema={credentialSchema}\n fields={credentialFormFields}\n initialValues={credValues}\n onSubmit={handleSaveCredentials}\n embedded\n hideFooterActions\n />\n )}\n </section>\n </TabsContent>\n ) : null}\n\n {showVersionTab ? (\n <TabsContent value=\"version\" className=\"mt-0 space-y-4\">\n <Card>\n <CardHeader>\n <CardTitle>{t('integrations.detail.version.select')}</CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-3\">\n {resolvedIntegration.apiVersions?.map((version) => {\n const stableVersion = resolvedIntegration.apiVersions?.find((item) => item.status === 'stable')?.id\n const isSelected = (resolvedState.apiVersion ?? stableVersion) === version.id\n return (\n <div\n key={version.id}\n className={`flex cursor-pointer items-center justify-between rounded-lg border p-3 transition-colors ${isSelected ? 'border-primary bg-primary/5' : 'hover:bg-muted/50'}`}\n onClick={() => void handleVersionChange(version.id)}\n >\n <div>\n <span className=\"text-sm font-medium\">{version.label ?? version.id}</span>\n <Badge\n variant={version.status === 'stable' ? 'default' : version.status === 'deprecated' ? 'destructive' : 'secondary'}\n className=\"ml-2\"\n >\n {t(`integrations.detail.version.${version.status}`)}\n </Badge>\n {version.status === 'deprecated' && version.sunsetAt ? (\n <span className=\"ml-2 text-xs text-muted-foreground\">\n {t('integrations.detail.version.sunsetAt', { date: new Date(version.sunsetAt).toLocaleDateString() })}\n </span>\n ) : null}\n </div>\n {isSelected ? <Badge variant=\"outline\">{t('integrations.detail.version.current')}</Badge> : null}\n </div>\n )\n })}\n </CardContent>\n </Card>\n </TabsContent>\n ) : null}\n\n {showDataSyncScheduleTab ? (\n <TabsContent value=\"data-sync-schedule\" className=\"mt-0\">\n <IntegrationScheduleTab\n integrationId={resolvedIntegration.id}\n hasCredentials={detail.hasCredentials}\n isEnabled={resolvedState.isEnabled}\n />\n </TabsContent>\n ) : null}\n\n {showHealthTab ? (\n <TabsContent value=\"health\" className=\"mt-0 space-y-4\">\n <RunActivityStrip\n run={activeRunDetail}\n refreshedAt={activeRunRefreshedAt}\n isRefreshing={isRefreshingRunActivity}\n onRefresh={() => void refreshRunActivity({ showLoading: true })}\n t={t}\n />\n <Card className=\"gap-4 py-4\">\n <CardHeader className=\"px-5\">\n <div className=\"flex items-center justify-between\">\n <CardTitle>{t('integrations.detail.health.title')}</CardTitle>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void refreshRunActivity({ showLoading: true })}\n disabled={isRefreshingRunActivity || !runIdFromUrl}\n >\n {isRefreshingRunActivity ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('integrations.detail.runActivity.refresh', 'Refresh')}\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void handleHealthCheck()}\n disabled={isCheckingHealth}\n >\n {isCheckingHealth ? <Spinner className=\"mr-2 h-4 w-4\" /> : <Zap className=\"mr-2 h-4 w-4\" />}\n {isCheckingHealth ? t('integrations.detail.health.checking') : t('integrations.detail.health.check')}\n </Button>\n </div>\n </div>\n </CardHeader>\n <CardContent className=\"space-y-3 px-5\">\n <div className=\"flex flex-wrap items-center gap-3 rounded-lg border bg-muted/20 px-4 py-3\">\n {displayHealthStatus ? (\n <Badge className={`gap-1.5 ${HEALTH_STATUS_STYLES[displayHealthStatus] ?? ''}`}>\n {HealthStatusIcon ? <HealthStatusIcon className=\"h-3.5 w-3.5\" /> : null}\n {t(`integrations.detail.health.${displayHealthStatus}`)}\n </Badge>\n ) : (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <AlertTriangle className=\"h-4 w-4\" />\n <span>{t('integrations.detail.health.unknown')}</span>\n </div>\n )}\n {healthStatusDescription ? (\n <p className=\"min-w-0 flex-1 text-sm text-muted-foreground\">{healthStatusDescription}</p>\n ) : null}\n <p className=\"text-xs text-muted-foreground md:ml-auto\">\n {resolvedState.lastHealthCheckedAt\n ? t('integrations.detail.health.lastChecked', { date: new Date(resolvedState.lastHealthCheckedAt).toLocaleString() })\n : t('integrations.detail.health.neverChecked')\n }\n </p>\n </div>\n {healthMessage || healthDetailEntries.length > 0 ? (\n <div className={`grid gap-3 ${healthMessage && healthDetailEntries.length > 0 ? 'xl:grid-cols-[minmax(0,1.25fr)_minmax(0,1fr)]' : ''}`}>\n {healthMessage ? (\n <div className=\"rounded-lg border px-4 py-3\">\n <p className=\"text-overline font-medium uppercase tracking-widest text-muted-foreground\">\n {t('integrations.detail.health.lastResult', 'Last result')}\n </p>\n <p className=\"mt-1.5 text-sm\">{healthMessage}</p>\n </div>\n ) : null}\n {healthDetailEntries.length > 0 ? (\n <div className=\"rounded-lg border px-4 py-3\">\n <p className=\"text-overline font-medium uppercase tracking-widest text-muted-foreground\">\n {t('integrations.detail.health.details', 'Details')}\n </p>\n <dl className=\"mt-2 grid gap-x-6 gap-y-2 sm:grid-cols-2\">\n {healthDetailEntries.map(([key, value]) => (\n <div key={key}>\n <dt className=\"text-xs font-medium text-muted-foreground\">{formatLogDetailLabel(key)}</dt>\n <dd className=\"mt-0.5 text-sm\">{formatHealthValue(value)}</dd>\n </div>\n ))}\n </dl>\n </div>\n ) : null}\n </div>\n ) : null}\n </CardContent>\n </Card>\n </TabsContent>\n ) : null}\n\n {showLogsTab ? (\n <TabsContent value=\"logs\" className=\"mt-0 space-y-4\">\n <RunActivityStrip\n run={activeRunDetail}\n refreshedAt={activeRunRefreshedAt}\n isRefreshing={isRefreshingRunActivity}\n onRefresh={() => void refreshRunActivity({ showLoading: true })}\n t={t}\n />\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"inline-flex\">\n <Select\n value={logLevel || undefined}\n onValueChange={(value) => setLogLevel(value ?? '')}\n >\n <SelectTrigger size=\"lg\" className=\"min-w-40\">\n <SelectValue placeholder={t('integrations.detail.logs.level.all')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"info\">{t('integrations.detail.logs.level.info')}</SelectItem>\n <SelectItem value=\"warn\">{t('integrations.detail.logs.level.warn')}</SelectItem>\n <SelectItem value=\"error\">{t('integrations.detail.logs.level.error')}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => void refreshRunActivity({ showLoading: true })}\n disabled={isRefreshingRunActivity || !runIdFromUrl}\n >\n {isRefreshingRunActivity ? <Spinner className=\"mr-2 h-4 w-4\" /> : <RefreshCw className=\"mr-2 h-4 w-4\" />}\n {t('integrations.detail.runActivity.refresh', 'Refresh')}\n </Button>\n </div>\n {isLoadingLogs ? (\n <div className=\"flex justify-center py-8\"><Spinner /></div>\n ) : (\n <LogList\n entries={logs.map<LogListEntry>((log) => {\n const metadataEntries = [\n ['Time', new Date(log.createdAt).toLocaleString()],\n ['Level', log.level],\n ['Code', log.code ?? null],\n ['Run ID', log.runId ?? null],\n ['Entity Type', log.scopeEntityType ?? null],\n ['Entity ID', log.scopeEntityId ?? null],\n ].filter((entry): entry is [string, string] => typeof entry[1] === 'string' && entry[1].trim().length > 0)\n const { inlineEntries, nestedEntries } = splitLogPayload(log.payload)\n\n return {\n id: log.id,\n time: new Date(log.createdAt).toLocaleString(),\n level: log.level,\n message: log.message,\n body: (\n <div className=\"grid gap-4 lg:grid-cols-[minmax(0,1.1fr)_minmax(0,0.9fr)]\">\n <div className=\"space-y-4\">\n <section className=\"space-y-3\">\n <div>\n <p className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {t('integrations.detail.logs.details.summary', 'Summary')}\n </p>\n <p className=\"mt-1 text-sm font-medium\">{log.message}</p>\n </div>\n {metadataEntries.length > 0 ? (\n <dl className=\"grid gap-3 sm:grid-cols-2\">\n {metadataEntries.map(([label, value]) => (\n <div key={label} className=\"rounded-md border bg-muted/30 px-3 py-2\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">\n {label}\n </dt>\n <dd className=\"mt-1 break-all text-sm\">{value}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n </section>\n\n {inlineEntries.length > 0 ? (\n <section className=\"space-y-3\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-muted-foreground\">\n {t('integrations.detail.logs.details.fields', 'Fields')}\n </p>\n <dl className=\"grid gap-3 sm:grid-cols-2\">\n {inlineEntries.map(([key, value]) => (\n <div key={key} className=\"rounded-md border bg-muted/30 px-3 py-2\">\n <dt className=\"text-overline font-medium uppercase tracking-wide text-muted-foreground\">\n {formatLogDetailLabel(key)}\n </dt>\n <dd className=\"mt-1 break-words text-sm\">\n {formatLogPrimitiveValue(value)}\n </dd>\n </div>\n ))}\n </dl>\n </section>\n ) : null}\n </div>\n\n <div className=\"space-y-3\">\n {nestedEntries.map(([key, value]) => (\n <JsonDisplay\n key={key}\n data={value}\n title={formatLogDetailLabel(key)}\n defaultExpanded\n maxInitialDepth={1}\n theme=\"dark\"\n maxHeight=\"16rem\"\n className=\"p-4\"\n />\n ))}\n {log.payload && nestedEntries.length === 0 ? (\n <JsonDisplay\n data={log.payload}\n title={t('integrations.detail.logs.details.payload', 'Payload')}\n defaultExpanded\n maxInitialDepth={1}\n theme=\"dark\"\n maxHeight=\"16rem\"\n className=\"p-4\"\n />\n ) : null}\n {!log.payload ? (\n <EmptyState\n size=\"sm\"\n icon={<FileX className=\"h-8 w-8\" aria-hidden=\"true\" />}\n title={t('integrations.detail.logs.details.noPayload', 'No structured payload was stored for this log entry.')}\n />\n ) : null}\n </div>\n </div>\n ),\n }\n })}\n emptyMessage={t('integrations.detail.logs.empty')}\n />\n )}\n </TabsContent>\n ) : null}\n\n {injectedTabs.map((tab) => (\n <TabsContent key={tab.id} value={tab.id} className=\"mt-0 space-y-4\">\n <InjectionSpot\n spotId={detailWidgetSpotId}\n context={injectionContext}\n data={detail}\n onDataChange={(next) => setDetail(next as IntegrationDetail)}\n widgetsOverride={tab.widgets}\n />\n </TabsContent>\n ))}\n </Tabs>\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["params", "detail"]
|
|
7
7
|
}
|
|
@@ -46,6 +46,7 @@ function BundleConfigPage({ params }) {
|
|
|
46
46
|
const [error, setError] = React.useState(null);
|
|
47
47
|
const [isNotFound, setIsNotFound] = React.useState(false);
|
|
48
48
|
const [credValues, setCredValues] = React.useState({});
|
|
49
|
+
const [credentialsUpdatedAt, setCredentialsUpdatedAt] = React.useState(null);
|
|
49
50
|
const [isSavingCreds, setIsSavingCreds] = React.useState(false);
|
|
50
51
|
const [togglingIds, setTogglingIds] = React.useState(/* @__PURE__ */ new Set());
|
|
51
52
|
const mutationContextId = React.useMemo(
|
|
@@ -88,6 +89,9 @@ function BundleConfigPage({ params }) {
|
|
|
88
89
|
void 0,
|
|
89
90
|
{ fallback: null }
|
|
90
91
|
);
|
|
92
|
+
if (credCall.ok && credCall.result) {
|
|
93
|
+
setCredentialsUpdatedAt(credCall.result.updatedAt ?? null);
|
|
94
|
+
}
|
|
91
95
|
if (credCall.ok && credCall.result?.credentials) {
|
|
92
96
|
const next = { ...credCall.result.credentials };
|
|
93
97
|
if (currentBundleId === "storage_s3") {
|
|
@@ -120,9 +124,8 @@ function BundleConfigPage({ params }) {
|
|
|
120
124
|
bundleId: currentBundleId,
|
|
121
125
|
retryLastMutation
|
|
122
126
|
},
|
|
123
|
-
// TODO(#2373-B): thread updatedAt — integration detail/state response does not expose a record version yet
|
|
124
127
|
operation: () => withScopedApiRequestHeaders(
|
|
125
|
-
buildOptimisticLockHeader(
|
|
128
|
+
buildOptimisticLockHeader(credentialsUpdatedAt),
|
|
126
129
|
() => apiCall(`/api/integrations/${encodeURIComponent(currentBundleId)}/credentials`, {
|
|
127
130
|
method: "PUT",
|
|
128
131
|
headers: { "Content-Type": "application/json" },
|
|
@@ -132,6 +135,7 @@ function BundleConfigPage({ params }) {
|
|
|
132
135
|
});
|
|
133
136
|
if (call.ok) {
|
|
134
137
|
flash(t("integrations.detail.credentials.saved"), "success");
|
|
138
|
+
await load();
|
|
135
139
|
} else {
|
|
136
140
|
flash(t("integrations.detail.credentials.saveError"), "error");
|
|
137
141
|
}
|
|
@@ -140,8 +144,8 @@ function BundleConfigPage({ params }) {
|
|
|
140
144
|
} finally {
|
|
141
145
|
setIsSavingCreds(false);
|
|
142
146
|
}
|
|
143
|
-
}, [resolveCurrentBundleId, runMutation, mutationContextId, retryLastMutation, credValues, t]);
|
|
144
|
-
const handleToggle = React.useCallback(async (integrationId, enabled) => {
|
|
147
|
+
}, [resolveCurrentBundleId, runMutation, mutationContextId, retryLastMutation, credValues, credentialsUpdatedAt, load, t]);
|
|
148
|
+
const handleToggle = React.useCallback(async (integrationId, enabled, updatedAt) => {
|
|
145
149
|
setTogglingIds((prev) => new Set(prev).add(integrationId));
|
|
146
150
|
try {
|
|
147
151
|
const call = await runMutation({
|
|
@@ -155,9 +159,8 @@ function BundleConfigPage({ params }) {
|
|
|
155
159
|
integrationId,
|
|
156
160
|
retryLastMutation
|
|
157
161
|
},
|
|
158
|
-
// TODO(#2373-B): thread updatedAt — integration detail/state response does not expose a record version yet
|
|
159
162
|
operation: () => withScopedApiRequestHeaders(
|
|
160
|
-
buildOptimisticLockHeader(
|
|
163
|
+
buildOptimisticLockHeader(updatedAt),
|
|
161
164
|
() => apiCall(`/api/integrations/${encodeURIComponent(integrationId)}/state`, {
|
|
162
165
|
method: "PUT",
|
|
163
166
|
headers: { "Content-Type": "application/json" },
|
|
@@ -166,12 +169,13 @@ function BundleConfigPage({ params }) {
|
|
|
166
169
|
)
|
|
167
170
|
});
|
|
168
171
|
if (call.ok) {
|
|
172
|
+
const nextUpdatedAt = call.result?.updatedAt ?? null;
|
|
169
173
|
setDetail((prev) => {
|
|
170
174
|
if (!prev) return prev;
|
|
171
175
|
return {
|
|
172
176
|
...prev,
|
|
173
177
|
bundleIntegrations: prev.bundleIntegrations.map(
|
|
174
|
-
(item) => item.id === integrationId ? { ...item, isEnabled: enabled } : item
|
|
178
|
+
(item) => item.id === integrationId ? { ...item, isEnabled: enabled, state: { updatedAt: nextUpdatedAt ?? item.state?.updatedAt ?? null } } : item
|
|
175
179
|
)
|
|
176
180
|
};
|
|
177
181
|
});
|
|
@@ -191,7 +195,7 @@ function BundleConfigPage({ params }) {
|
|
|
191
195
|
const handleBulkToggle = React.useCallback(async (enabled) => {
|
|
192
196
|
if (!detail) return;
|
|
193
197
|
const targets = detail.bundleIntegrations.filter((item) => item.isEnabled !== enabled);
|
|
194
|
-
await Promise.all(targets.map((item) => handleToggle(item.id, enabled)));
|
|
198
|
+
await Promise.all(targets.map((item) => handleToggle(item.id, enabled, item.state?.updatedAt)));
|
|
195
199
|
}, [detail, handleToggle]);
|
|
196
200
|
if (isLoading) return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsx(PageBody, { children: /* @__PURE__ */ jsx(LoadingMessage, { label: t("integrations.bundle.title") }) }) });
|
|
197
201
|
if (isNotFound) {
|
|
@@ -284,7 +288,7 @@ function BundleConfigPage({ params }) {
|
|
|
284
288
|
{
|
|
285
289
|
checked: item.isEnabled,
|
|
286
290
|
disabled: togglingIds.has(item.id),
|
|
287
|
-
onCheckedChange: (checked) => void handleToggle(item.id, checked)
|
|
291
|
+
onCheckedChange: (checked) => void handleToggle(item.id, checked, item.state?.updatedAt)
|
|
288
292
|
}
|
|
289
293
|
)
|
|
290
294
|
] })
|