@burdenoff/microfe-adaptercloud 2026.825.4 → 2026.829.1

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.
Files changed (57) hide show
  1. package/dist/adaptercloud/AdapterCloudRoot.d.ts.map +1 -1
  2. package/dist/adaptercloud/AdapterCloudRoot.js +52 -55
  3. package/dist/adaptercloud/AdapterCloudRoot.js.map +1 -1
  4. package/dist/adaptercloud/components/ActiveSwitch.d.ts +17 -0
  5. package/dist/adaptercloud/components/ActiveSwitch.d.ts.map +1 -0
  6. package/dist/adaptercloud/components/ActiveSwitch.js +28 -0
  7. package/dist/adaptercloud/components/ActiveSwitch.js.map +1 -0
  8. package/dist/adaptercloud/components/index.d.ts +1 -0
  9. package/dist/adaptercloud/components/index.d.ts.map +1 -1
  10. package/dist/adaptercloud/hooks/index.d.ts +1 -0
  11. package/dist/adaptercloud/hooks/index.d.ts.map +1 -1
  12. package/dist/adaptercloud/hooks/useAdapterCloudApi.d.ts +28 -2
  13. package/dist/adaptercloud/hooks/useAdapterCloudApi.d.ts.map +1 -1
  14. package/dist/adaptercloud/hooks/useAdapterCloudApi.js +318 -291
  15. package/dist/adaptercloud/hooks/useAdapterCloudApi.js.map +1 -1
  16. package/dist/adaptercloud/hooks/useTr.d.ts +2 -0
  17. package/dist/adaptercloud/hooks/useTr.d.ts.map +1 -0
  18. package/dist/adaptercloud/hooks/useTr.js +14 -0
  19. package/dist/adaptercloud/hooks/useTr.js.map +1 -0
  20. package/dist/adaptercloud/pages/OverviewPage.d.ts.map +1 -1
  21. package/dist/adaptercloud/pages/OverviewPage.js +117 -120
  22. package/dist/adaptercloud/pages/OverviewPage.js.map +1 -1
  23. package/dist/adaptercloud/pages/adapters/AdaptersListPage.d.ts.map +1 -1
  24. package/dist/adaptercloud/pages/adapters/AdaptersListPage.js +6 -5
  25. package/dist/adaptercloud/pages/adapters/AdaptersListPage.js.map +1 -1
  26. package/dist/adaptercloud/pages/connections/ConnectionDetailPage.d.ts.map +1 -1
  27. package/dist/adaptercloud/pages/connections/ConnectionDetailPage.js +217 -104
  28. package/dist/adaptercloud/pages/connections/ConnectionDetailPage.js.map +1 -1
  29. package/dist/adaptercloud/pages/connections/ConnectionsListPage.d.ts.map +1 -1
  30. package/dist/adaptercloud/pages/connections/ConnectionsListPage.js +6 -5
  31. package/dist/adaptercloud/pages/connections/ConnectionsListPage.js.map +1 -1
  32. package/dist/adaptercloud/pages/costs/CostsPage.d.ts.map +1 -1
  33. package/dist/adaptercloud/pages/costs/CostsPage.js +183 -156
  34. package/dist/adaptercloud/pages/costs/CostsPage.js.map +1 -1
  35. package/dist/adaptercloud/pages/drift/DriftListPage.d.ts.map +1 -1
  36. package/dist/adaptercloud/pages/drift/DriftListPage.js +108 -107
  37. package/dist/adaptercloud/pages/drift/DriftListPage.js.map +1 -1
  38. package/dist/adaptercloud/pages/policies/PoliciesListPage.d.ts.map +1 -1
  39. package/dist/adaptercloud/pages/policies/PoliciesListPage.js +141 -131
  40. package/dist/adaptercloud/pages/policies/PoliciesListPage.js.map +1 -1
  41. package/dist/adaptercloud/pages/policies/PolicyDetailPage.d.ts.map +1 -1
  42. package/dist/adaptercloud/pages/policies/PolicyDetailPage.js +171 -117
  43. package/dist/adaptercloud/pages/policies/PolicyDetailPage.js.map +1 -1
  44. package/dist/adaptercloud/pages/resources/ResourcesListPage.d.ts.map +1 -1
  45. package/dist/adaptercloud/pages/resources/ResourcesListPage.js +85 -66
  46. package/dist/adaptercloud/pages/resources/ResourcesListPage.js.map +1 -1
  47. package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.d.ts.map +1 -1
  48. package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.js +148 -121
  49. package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.js.map +1 -1
  50. package/dist/adaptercloud/pages/violations/ViolationsListPage.d.ts.map +1 -1
  51. package/dist/adaptercloud/pages/violations/ViolationsListPage.js +145 -144
  52. package/dist/adaptercloud/pages/violations/ViolationsListPage.js.map +1 -1
  53. package/dist/utils/pageContext.d.ts +0 -2
  54. package/dist/utils/pageContext.d.ts.map +1 -1
  55. package/dist/utils/pageContext.js +1 -3
  56. package/dist/utils/pageContext.js.map +1 -1
  57. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AdaptersListPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/adapters/AdaptersListPage.tsx"],"sourcesContent":["/**\n * Adapters List Page\n * @module adaptercloud/pages/adapters\n *\n * The adapter catalog — every reusable connector definition in the workspace.\n * Lists from `adaListAdapters` with kind/status filters and offset pagination\n * (driven by `AdaPageInfo.hasMore`).\n */\n\nimport { useState, useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Boxes,\n Cloud,\n Cpu,\n Database,\n HardDrive,\n Network,\n Plus,\n Puzzle,\n Radio,\n ServerCog,\n ChevronLeft,\n ChevronRight,\n type LucideIcon,\n} from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataState } from '../../components/DataState';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { useAdapters } from '../../hooks/useAdapterCloudApi';\nimport { adapterKindLabels, adapterStatusLabels } from '../../utils/domain';\nimport { formatRelativeTime } from '../../utils/formatters';\nimport type { AdaAdapterKind, AdaAdapterStatus } from '../../types';\n\nconst PAGE_SIZE = 20;\n\n/** Per-kind glyph — mirrors the mock's vendor logo tile on each catalog card. */\nconst kindIcons: Record<AdaAdapterKind, LucideIcon> = {\n PUBLIC_CLOUD: Cloud,\n SAAS: Cloud,\n PRIVATE_CLOUD: ServerCog,\n ON_PREM: HardDrive,\n EDGE: Radio,\n IOT: Cpu,\n KUBERNETES: Boxes,\n NETWORK: Network,\n DATA_SYSTEM: Database,\n CUSTOM: Puzzle,\n};\n\nexport function AdaptersListPage() {\n const { navigateTo } = useAdapterCloud();\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n const [kind, setKind] = useState<AdaAdapterKind | ''>('');\n const [status, setStatus] = useState<AdaAdapterStatus | ''>('');\n const [offset, setOffset] = useState(0);\n\n const query = useAdapters({\n kind: kind || undefined,\n status: status || undefined,\n pagination: { limit: PAGE_SIZE, offset },\n });\n\n const items = query.data?.items ?? [];\n const hasMore = query.data?.pageInfo.hasMore ?? false;\n\n const resetTo = useCallback(<T,>(setter: (v: T) => void) => {\n return (v: T) => {\n setter(v);\n setOffset(0);\n };\n }, []);\n\n return (\n <PageLayout\n title={t('adaptercloud.adapters.title', 'Adapters')}\n description={t(\n 'adaptercloud.adapters.subtitle',\n 'The catalog of connectors that bridge each class of system into the fabric.'\n )}\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/adapters/new')}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90\"\n >\n <Plus className=\"h-4 w-4\" />\n {t('adaptercloud.adapters.new', 'New adapter')}\n </button>\n }\n >\n {/* Filters */}\n <div className=\"mb-6 flex flex-wrap gap-3\">\n <select\n value={kind}\n onChange={(e) => resetTo(setKind)(e.target.value as AdaAdapterKind | '')}\n aria-label={t('adaptercloud.adapters.filterByKind', 'Filter by kind')}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">{t('adaptercloud.adapters.allKinds', 'All kinds')}</option>\n {(Object.keys(adapterKindLabels) as AdaAdapterKind[]).map((k) => (\n <option key={k} value={k}>\n {adapterKindLabels[k]}\n </option>\n ))}\n </select>\n <select\n value={status}\n onChange={(e) => resetTo(setStatus)(e.target.value as AdaAdapterStatus | '')}\n aria-label={t('adaptercloud.adapters.filterByStatus', 'Filter by status')}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">{t('adaptercloud.adapters.allStatuses', 'All statuses')}</option>\n {(Object.keys(adapterStatusLabels) as AdaAdapterStatus[]).map((s) => (\n <option key={s} value={s}>\n {adapterStatusLabels[s]}\n </option>\n ))}\n </select>\n </div>\n\n <DataState\n isLoading={query.isLoading}\n isError={query.isError}\n isEmpty={items.length === 0}\n error={query.error}\n onRetry={() => void query.refetch()}\n emptyTitle={t('adaptercloud.adapters.emptyTitle', 'No adapters yet')}\n emptyDescription={t(\n 'adaptercloud.adapters.emptyDescription',\n 'Define your first adapter to start bridging a class of system into the fabric.'\n )}\n emptyIcon={<Boxes className=\"h-10 w-10\" />}\n emptyAction={\n <button\n type=\"button\"\n onClick={() => navigateTo('/adapters/new')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90\"\n >\n {t('adaptercloud.adapters.new', 'New adapter')}\n </button>\n }\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {items.map((adapter) => (\n <GlassCard\n key={adapter.id}\n role=\"button\"\n tabIndex={0}\n onClick={() => navigateTo(`/adapters/${adapter.id}`)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n navigateTo(`/adapters/${adapter.id}`);\n }\n }}\n className=\"cursor-pointer p-5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex min-w-0 items-center gap-3\">\n <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-accent-blue-subtle text-accent-blue\">\n {(() => {\n const Icon = kindIcons[adapter.kind];\n return <Icon className=\"h-5 w-5\" />;\n })()}\n </span>\n <div className=\"min-w-0\">\n <h3 className=\"truncate text-base font-semibold text-text-primary\">\n {adapter.name}\n </h3>\n <p className=\"mt-0.5 truncate text-xs text-text-secondary\">{adapter.slug}</p>\n </div>\n </div>\n <StatusBadge status={adapter.status} />\n </div>\n\n <div className=\"mt-3 flex flex-wrap items-center gap-2 text-xs text-text-secondary\">\n <span className=\"inline-flex items-center rounded-full bg-bg-sunken px-2 py-0.5\">\n {adapterKindLabels[adapter.kind]}\n </span>\n <span>v{adapter.version}</span>\n {adapter.vendor && <span>· {adapter.vendor}</span>}\n </div>\n\n {adapter.description && (\n <p className=\"mt-3 line-clamp-2 text-sm text-text-secondary\">\n {adapter.description}\n </p>\n )}\n\n {adapter.capabilities.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-1.5\">\n {adapter.capabilities.slice(0, 4).map((cap) => (\n <span\n key={cap}\n className=\"inline-flex items-center rounded-full bg-accent-blue-subtle px-2 py-0.5 text-xs text-accent-blue\"\n >\n {cap}\n </span>\n ))}\n {adapter.capabilities.length > 4 && (\n <span className=\"text-xs text-text-secondary\">\n +{adapter.capabilities.length - 4}\n </span>\n )}\n </div>\n )}\n\n <p className=\"mt-4 text-xs text-text-secondary\">\n {t('adaptercloud.common.updated', 'Updated')}{' '}\n {formatRelativeTime(adapter.updatedAt)}\n </p>\n </GlassCard>\n ))}\n </div>\n\n {/* Pagination */}\n {(offset > 0 || hasMore) && (\n <div className=\"mt-6 flex items-center justify-between\">\n <button\n type=\"button\"\n disabled={offset === 0}\n onClick={() => setOffset((o) => Math.max(0, o - PAGE_SIZE))}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n {t('adaptercloud.common.prev', 'Previous')}\n </button>\n <span className=\"text-sm text-text-secondary\">\n {t('adaptercloud.common.showing', 'Showing')} {offset + 1}–{offset + items.length}\n </span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => setOffset((o) => o + PAGE_SIZE)}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {t('adaptercloud.common.next', 'Next')}\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </DataState>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AdaptersListPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/adapters/AdaptersListPage.tsx"],"sourcesContent":["/**\n * Adapters List Page\n * @module adaptercloud/pages/adapters\n *\n * The adapter catalog — every reusable connector definition in the workspace.\n * Lists from `adaListAdapters` with kind/status filters and offset pagination\n * (driven by `AdaPageInfo.hasMore`).\n */\n\nimport { useState, useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Boxes,\n Cloud,\n Cpu,\n Database,\n HardDrive,\n Network,\n Plus,\n Puzzle,\n Radio,\n ServerCog,\n ChevronLeft,\n ChevronRight,\n type LucideIcon,\n} from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataState } from '../../components/DataState';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { useAdapters } from '../../hooks/useAdapterCloudApi';\nimport { adapterKindLabels, adapterStatusLabels } from '../../utils/domain';\nimport { formatRelativeTime } from '../../utils/formatters';\nimport type { AdaAdapterKind, AdaAdapterStatus } from '../../types';\n\nconst PAGE_SIZE = 20;\n\n/** Per-kind glyph — mirrors the mock's vendor logo tile on each catalog card. */\nconst kindIcons: Record<AdaAdapterKind, LucideIcon> = {\n PUBLIC_CLOUD: Cloud,\n SAAS: Cloud,\n PRIVATE_CLOUD: ServerCog,\n ON_PREM: HardDrive,\n EDGE: Radio,\n IOT: Cpu,\n KUBERNETES: Boxes,\n NETWORK: Network,\n DATA_SYSTEM: Database,\n CUSTOM: Puzzle,\n};\n\nexport function AdaptersListPage() {\n const { navigateTo } = useAdapterCloud();\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n const [kind, setKind] = useState<AdaAdapterKind | ''>('');\n const [status, setStatus] = useState<AdaAdapterStatus | ''>('');\n const [offset, setOffset] = useState(0);\n\n const query = useAdapters({\n kind: kind || undefined,\n status: status || undefined,\n pagination: { limit: PAGE_SIZE, offset },\n });\n\n const items = query.data?.items ?? [];\n const hasMore = query.data?.pageInfo.hasMore ?? false;\n // Estate-wide total for the current filter. Nullable on older deployed\n // schemas — the footer then falls back to the bare offset range.\n const totalCount = query.data?.pageInfo.totalCount;\n\n const resetTo = useCallback(<T,>(setter: (v: T) => void) => {\n return (v: T) => {\n setter(v);\n setOffset(0);\n };\n }, []);\n\n return (\n <PageLayout\n title={t('adaptercloud.adapters.title', 'Adapters')}\n description={t(\n 'adaptercloud.adapters.subtitle',\n 'The catalog of connectors that bridge each class of system into the fabric.'\n )}\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/adapters/new')}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90\"\n >\n <Plus className=\"h-4 w-4\" />\n {t('adaptercloud.adapters.new', 'New adapter')}\n </button>\n }\n >\n {/* Filters */}\n <div className=\"mb-6 flex flex-wrap gap-3\">\n <select\n value={kind}\n onChange={(e) => resetTo(setKind)(e.target.value as AdaAdapterKind | '')}\n aria-label={t('adaptercloud.adapters.filterByKind', 'Filter by kind')}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">{t('adaptercloud.adapters.allKinds', 'All kinds')}</option>\n {(Object.keys(adapterKindLabels) as AdaAdapterKind[]).map((k) => (\n <option key={k} value={k}>\n {adapterKindLabels[k]}\n </option>\n ))}\n </select>\n <select\n value={status}\n onChange={(e) => resetTo(setStatus)(e.target.value as AdaAdapterStatus | '')}\n aria-label={t('adaptercloud.adapters.filterByStatus', 'Filter by status')}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">{t('adaptercloud.adapters.allStatuses', 'All statuses')}</option>\n {(Object.keys(adapterStatusLabels) as AdaAdapterStatus[]).map((s) => (\n <option key={s} value={s}>\n {adapterStatusLabels[s]}\n </option>\n ))}\n </select>\n </div>\n\n <DataState\n isLoading={query.isLoading}\n isError={query.isError}\n isEmpty={items.length === 0}\n error={query.error}\n onRetry={() => void query.refetch()}\n emptyTitle={t('adaptercloud.adapters.emptyTitle', 'No adapters yet')}\n emptyDescription={t(\n 'adaptercloud.adapters.emptyDescription',\n 'Define your first adapter to start bridging a class of system into the fabric.'\n )}\n emptyIcon={<Boxes className=\"h-10 w-10\" />}\n emptyAction={\n <button\n type=\"button\"\n onClick={() => navigateTo('/adapters/new')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90\"\n >\n {t('adaptercloud.adapters.new', 'New adapter')}\n </button>\n }\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {items.map((adapter) => (\n <GlassCard\n key={adapter.id}\n role=\"button\"\n tabIndex={0}\n onClick={() => navigateTo(`/adapters/${adapter.id}`)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n navigateTo(`/adapters/${adapter.id}`);\n }\n }}\n className=\"cursor-pointer p-5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"flex min-w-0 items-center gap-3\">\n <span className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-accent-blue-subtle text-accent-blue\">\n {(() => {\n const Icon = kindIcons[adapter.kind];\n return <Icon className=\"h-5 w-5\" />;\n })()}\n </span>\n <div className=\"min-w-0\">\n <h3 className=\"truncate text-base font-semibold text-text-primary\">\n {adapter.name}\n </h3>\n <p className=\"mt-0.5 truncate text-xs text-text-secondary\">{adapter.slug}</p>\n </div>\n </div>\n <StatusBadge status={adapter.status} />\n </div>\n\n <div className=\"mt-3 flex flex-wrap items-center gap-2 text-xs text-text-secondary\">\n <span className=\"inline-flex items-center rounded-full bg-bg-sunken px-2 py-0.5\">\n {adapterKindLabels[adapter.kind]}\n </span>\n <span>v{adapter.version}</span>\n {adapter.vendor && <span>· {adapter.vendor}</span>}\n </div>\n\n {adapter.description && (\n <p className=\"mt-3 line-clamp-2 text-sm text-text-secondary\">\n {adapter.description}\n </p>\n )}\n\n {adapter.capabilities.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-1.5\">\n {adapter.capabilities.slice(0, 4).map((cap) => (\n <span\n key={cap}\n className=\"inline-flex items-center rounded-full bg-accent-blue-subtle px-2 py-0.5 text-xs text-accent-blue\"\n >\n {cap}\n </span>\n ))}\n {adapter.capabilities.length > 4 && (\n <span className=\"text-xs text-text-secondary\">\n +{adapter.capabilities.length - 4}\n </span>\n )}\n </div>\n )}\n\n <p className=\"mt-4 text-xs text-text-secondary\">\n {t('adaptercloud.common.updated', 'Updated')}{' '}\n {formatRelativeTime(adapter.updatedAt)}\n </p>\n </GlassCard>\n ))}\n </div>\n\n {/* Pagination */}\n {(offset > 0 || hasMore) && (\n <div className=\"mt-6 flex items-center justify-between\">\n <button\n type=\"button\"\n disabled={offset === 0}\n onClick={() => setOffset((o) => Math.max(0, o - PAGE_SIZE))}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n {t('adaptercloud.common.prev', 'Previous')}\n </button>\n <span className=\"text-sm tabular-nums text-text-secondary\">\n {t('adaptercloud.common.showing', 'Showing')} {offset + 1}–{offset + items.length}\n {totalCount != null && ` ${t('adaptercloud.common.of', 'of')} ${totalCount}`}\n </span>\n <button\n type=\"button\"\n disabled={!hasMore}\n onClick={() => setOffset((o) => o + PAGE_SIZE)}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {t('adaptercloud.common.next', 'Next')}\n <ChevronRight className=\"h-4 w-4\" />\n </button>\n </div>\n )}\n </DataState>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAoCA,IAAM,IAAY,IAGZ,IAAgD;CACpD,cAAc;CACd,MAAM;CACN,eAAe;CACf,SAAS;CACT,MAAM;CACN,KAAK;CACL,YAAY;CACZ,SAAS;CACT,aAAa;CACb,QAAQ;AACV;AAEA,SAAgB,IAAmB;CACjC,IAAM,EAAE,kBAAe,EAAgB,GACjC,EAAE,GAAG,MAAc,EAAQ,GAC3B,IAAI,GACP,GAAa,MAA6B;EACzC,IAAM,IAAQ,EAAU,CAAG;EAC3B,OAAO,MAAU,IAAM,IAAW;CACpC,GACA,CAAC,CAAS,CACZ,GAEM,CAAC,GAAM,KAAW,EAA8B,EAAE,GAClD,CAAC,GAAQ,KAAa,EAAgC,EAAE,GACxD,CAAC,GAAQ,KAAa,EAAS,CAAC,GAEhC,IAAQ,EAAY;EACxB,MAAM,KAAQ,KAAA;EACd,QAAQ,KAAU,KAAA;EAClB,YAAY;GAAE,OAAO;GAAW;EAAO;CACzC,CAAC,GAEK,IAAQ,EAAM,MAAM,SAAS,CAAC,GAC9B,IAAU,EAAM,MAAM,SAAS,WAAW,IAG1C,IAAa,EAAM,MAAM,SAAS,YAElC,IAAU,GAAiB,OACvB,MAAS;EAEf,AADA,EAAO,CAAC,GACR,EAAU,CAAC;CACb,GACC,CAAC,CAAC;CAEL,OACE,kBAAC,GAAD;EACE,OAAO,EAAE,+BAA+B,UAAU;EAClD,aAAa,EACX,kCACA,6EACF;EACA,SACE,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,EAAW,eAAe;GACzC,WAAU;aAHZ,CAKE,kBAAC,GAAD,EAAM,WAAU,UAAW,CAAA,GAC1B,EAAE,6BAA6B,aAAa,CACvC;;YAdZ,CAkBE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,UAAD;IACE,OAAO;IACP,WAAW,MAAM,EAAQ,CAAO,EAAE,EAAE,OAAO,KAA4B;IACvE,cAAY,EAAE,sCAAsC,gBAAgB;IACpE,WAAU;cAJZ,CAME,kBAAC,UAAD;KAAQ,OAAM;eAAI,EAAE,kCAAkC,WAAW;IAAU,CAAA,GACzE,OAAO,KAAK,CAAiB,EAAuB,KAAK,MACzD,kBAAC,UAAD;KAAgB,OAAO;eACpB,EAAkB;IACb,GAFK,CAEL,CACT,CACK;OACR,kBAAC,UAAD;IACE,OAAO;IACP,WAAW,MAAM,EAAQ,CAAS,EAAE,EAAE,OAAO,KAA8B;IAC3E,cAAY,EAAE,wCAAwC,kBAAkB;IACxE,WAAU;cAJZ,CAME,kBAAC,UAAD;KAAQ,OAAM;eAAI,EAAE,qCAAqC,cAAc;IAAU,CAAA,GAC/E,OAAO,KAAK,CAAmB,EAAyB,KAAK,MAC7D,kBAAC,UAAD;KAAgB,OAAO;eACpB,EAAoB;IACf,GAFK,CAEL,CACT,CACK;KACL;MAEL,kBAAC,GAAD;GACE,WAAW,EAAM;GACjB,SAAS,EAAM;GACf,SAAS,EAAM,WAAW;GAC1B,OAAO,EAAM;GACb,eAAe,KAAK,EAAM,QAAQ;GAClC,YAAY,EAAE,oCAAoC,iBAAiB;GACnE,kBAAkB,EAChB,0CACA,gFACF;GACA,WAAW,kBAAC,GAAD,EAAO,WAAU,YAAa,CAAA;GACzC,aACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAW,eAAe;IACzC,WAAU;cAET,EAAE,6BAA6B,aAAa;GACvC,CAAA;aAnBZ,CAsBE,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAM,KAAK,MACV,kBAAC,GAAD;KAEE,MAAK;KACL,UAAU;KACV,eAAe,EAAW,aAAa,EAAQ,IAAI;KACnD,YAAY,MAAM;MAChB,CAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,SACjC,EAAE,eAAe,GACjB,EAAW,aAAa,EAAQ,IAAI;KAExC;KACA,WAAU;eAXZ;MAaE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;0BACN;UACN,IAAM,IAAO,EAAU,EAAQ;UAC/B,OAAO,kBAAC,GAAD,EAAM,WAAU,UAAW,CAAA;SACpC,GAAG;QACC,CAAA,GACN,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAQ;SACP,CAAA,GACJ,kBAAC,KAAD;UAAG,WAAU;oBAA+C,EAAQ;SAAQ,CAAA,CACzE;UACF;WACL,kBAAC,GAAD,EAAa,QAAQ,EAAQ,OAAS,CAAA,CACnC;;MAEL,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAkB,EAAQ;QACvB,CAAA;QACN,kBAAC,QAAD,EAAA,UAAA,CAAM,KAAE,EAAQ,OAAc,EAAA,CAAA;QAC7B,EAAQ,UAAU,kBAAC,QAAD,EAAA,UAAA,CAAM,MAAG,EAAQ,MAAa,EAAA,CAAA;OAC9C;;MAEJ,EAAQ,eACP,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAQ;MACR,CAAA;MAGJ,EAAQ,aAAa,SAAS,KAC7B,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACG,EAAQ,aAAa,MAAM,GAAG,CAAC,EAAE,KAAK,MACrC,kBAAC,QAAD;QAEE,WAAU;kBAET;OACG,GAJC,CAID,CACP,GACA,EAAQ,aAAa,SAAS,KAC7B,kBAAC,QAAD;QAAM,WAAU;kBAAhB,CAA8C,KAC1C,EAAQ,aAAa,SAAS,CAC5B;SAEL;;MAGP,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG,EAAE,+BAA+B,SAAS;QAAG;QAC7C,EAAmB,EAAQ,SAAS;OACpC;;KACM;OAlEJ,EAAQ,EAkEJ,CACZ;GACE,CAAA,IAGH,IAAS,KAAK,MACd,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,UAAD;MACE,MAAK;MACL,UAAU,MAAW;MACrB,eAAe,GAAW,MAAM,KAAK,IAAI,GAAG,IAAI,CAAS,CAAC;MAC1D,WAAU;gBAJZ,CAME,kBAAC,GAAD,EAAa,WAAU,UAAW,CAAA,GACjC,EAAE,4BAA4B,UAAU,CACnC;;KACR,kBAAC,QAAD;MAAM,WAAU;gBAAhB;OACG,EAAE,+BAA+B,SAAS;OAAE;OAAE,IAAS;OAAE;OAAE,IAAS,EAAM;OAC1E,KAAc,QAAQ,IAAI,EAAE,0BAA0B,IAAI,EAAE,GAAG;MAC5D;;KACN,kBAAC,UAAD;MACE,MAAK;MACL,UAAU,CAAC;MACX,eAAe,GAAW,MAAM,IAAI,CAAS;MAC7C,WAAU;gBAJZ,CAMG,EAAE,4BAA4B,MAAM,GACrC,kBAAC,GAAD,EAAc,WAAU,UAAW,CAAA,CAC7B;;IACL;KAEE;IACD;;AAEhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"ConnectionDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/adaptercloud/pages/connections/ConnectionDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAqCH,wBAAgB,oBAAoB,gCA2VnC"}
1
+ {"version":3,"file":"ConnectionDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/adaptercloud/pages/connections/ConnectionDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA+CH,wBAAgB,oBAAoB,gCAkenC"}
@@ -1,14 +1,14 @@
1
1
  import { useAdapterCloud as e } from "../../context/AdapterCloudContext.js";
2
2
  import { PageLayout as t } from "../../components/PageLayout.js";
3
- import { authMethodLabels as n, connectionStatusLabels as r, formatMoney as i, resourceStateLabels as a, syncKindLabels as o } from "../../utils/domain.js";
4
- import { StatusBadge as s } from "../../components/StatusBadge.js";
5
- import { DataState as c } from "../../components/DataState.js";
6
- import { useConnection as l, useDisableConnection as u, useSetConnectionStatus as d, useStartSyncRun as f } from "../../hooks/useAdapterCloudApi.js";
7
- import { formatDate as p } from "../../utils/formatters.js";
8
- import { ConfirmDialog as m } from "../../components/ConfirmDialog.js";
9
- import { canStartConnectionSync as h, canStartConnectionSyncKind as g, isConnectionSyncKindExecutable as _ } from "./connectionSync.js";
10
- import { useCallback as v, useState as y } from "react";
11
- import { useI18n as b } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
3
+ import { authMethodLabels as n, connectionStatusLabels as r, formatMoney as i, resourceStateLabels as a, syncKindLabels as o, syncStatusLabels as s } from "../../utils/domain.js";
4
+ import { StatusBadge as c } from "../../components/StatusBadge.js";
5
+ import { DataState as l } from "../../components/DataState.js";
6
+ import { useConnection as u, useDisableConnection as ee, useSetConnectionStatus as d, useStartSyncRun as f, useSyncRuns as te } from "../../hooks/useAdapterCloudApi.js";
7
+ import { formatDate as p, formatRelativeTime as m } from "../../utils/formatters.js";
8
+ import { ConfirmDialog as h } from "../../components/ConfirmDialog.js";
9
+ import { canStartConnectionSync as g, canStartConnectionSyncKind as _, isConnectionSyncKindExecutable as v } from "./connectionSync.js";
10
+ import { useCallback as y, useState as b } from "react";
11
+ import { useI18n as ne } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
12
12
  import { ArrowLeft as x, Ban as S, Loader2 as C, Pencil as w, Play as T, RefreshCw as E, Server as D } from "lucide-react";
13
13
  import { useParams as O } from "react-router";
14
14
  import { jsx as k, jsxs as A } from "react/jsx-runtime";
@@ -24,89 +24,98 @@ var M = [
24
24
  "RECONCILE",
25
25
  "COST_INGEST",
26
26
  "FULL"
27
- ];
28
- function P() {
29
- let { id: P } = O(), { navigateTo: F } = e(), { t: I } = b(), L = v((e, t) => {
30
- let n = I(e);
27
+ ], P = 5;
28
+ function F(e) {
29
+ return e === "QUEUED" || e === "RUNNING";
30
+ }
31
+ function I() {
32
+ let { id: I } = O(), { navigateTo: L } = e(), { t: R } = ne(), z = y((e, t) => {
33
+ let n = R(e);
31
34
  return n === e ? t : n;
32
- }, [I]), R = l(P), z = d(), B = u(), V = f(), H = R.data, U = H ? h(H.status) : !1, [W, G] = y(null), [K, q] = y(null), [J, Y] = y(!1), X = v((e) => q(e instanceof Error ? e.message : "Action failed. Please try again."), []), Z = v((e) => {
33
- P && (q(null), z.mutate({
34
- id: P,
35
+ }, [R]), B = u(I), V = d(), H = ee(), U = f(), W = B.data, G = W ? g(W.status) : !1, K = te({
36
+ connectionId: I,
37
+ pagination: {
38
+ limit: P,
39
+ offset: 0
40
+ }
41
+ }, { enabled: !!I }), q = K.data?.items ?? [], [J, Y] = b(null), [X, Z] = b(null), [re, Q] = b(!1), $ = y((e) => Z(e instanceof Error ? e.message : "Action failed. Please try again."), []), ie = y((e) => {
42
+ I && (Z(null), V.mutate({
43
+ id: I,
35
44
  status: e
36
- }, { onError: X }));
45
+ }, { onError: $ }));
37
46
  }, [
38
- P,
39
- z,
40
- X
41
- ]), Q = v(() => {
42
- P && (q(null), B.mutate(P, {
43
- onSuccess: () => Y(!1),
44
- onError: X
47
+ I,
48
+ V,
49
+ $
50
+ ]), ae = y(() => {
51
+ I && (Z(null), H.mutate(I, {
52
+ onSuccess: () => Q(!1),
53
+ onError: $
45
54
  }));
46
55
  }, [
47
- P,
48
- B,
49
- X
50
- ]), $ = v((e) => {
51
- !P || !H || !g(H.status, e) || (q(null), G(e), V.mutate({
52
- connectionId: P,
56
+ I,
57
+ H,
58
+ $
59
+ ]), oe = y((e) => {
60
+ !I || !W || !_(W.status, e) || (Z(null), Y(e), U.mutate({
61
+ connectionId: I,
53
62
  kind: e
54
63
  }, {
55
64
  onSuccess: () => {
56
- G(null), F("/sync-runs");
65
+ Y(null), L("/sync-runs");
57
66
  },
58
67
  onError: (e) => {
59
- G(null), X(e);
68
+ Y(null), $(e);
60
69
  }
61
70
  }));
62
71
  }, [
63
- P,
64
- H,
65
- V,
66
- F,
67
- X
72
+ I,
73
+ W,
74
+ U,
75
+ L,
76
+ $
68
77
  ]);
69
78
  return /* @__PURE__ */ A(t, {
70
- title: H?.name ?? L("adaptercloud.connections.detailTitle", "Connection"),
71
- description: H?.adapter?.name,
79
+ title: W?.name ?? z("adaptercloud.connections.detailTitle", "Connection"),
80
+ description: W?.adapter?.name,
72
81
  actions: /* @__PURE__ */ A("div", {
73
82
  className: "flex items-center gap-2",
74
83
  children: [/* @__PURE__ */ A("button", {
75
84
  type: "button",
76
- onClick: () => F("/connections"),
85
+ onClick: () => L("/connections"),
77
86
  className: "inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent",
78
- children: [/* @__PURE__ */ k(x, { className: "h-4 w-4" }), L("adaptercloud.common.back", "Back")]
79
- }), H && /* @__PURE__ */ A("button", {
87
+ children: [/* @__PURE__ */ k(x, { className: "h-4 w-4" }), z("adaptercloud.common.back", "Back")]
88
+ }), W && /* @__PURE__ */ A("button", {
80
89
  type: "button",
81
- onClick: () => F(`/connections/${H.id}/edit`),
90
+ onClick: () => L(`/connections/${W.id}/edit`),
82
91
  className: "inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent",
83
- children: [/* @__PURE__ */ k(w, { className: "h-4 w-4" }), L("adaptercloud.common.edit", "Edit")]
92
+ children: [/* @__PURE__ */ k(w, { className: "h-4 w-4" }), z("adaptercloud.common.edit", "Edit")]
84
93
  })]
85
94
  }),
86
- children: [/* @__PURE__ */ k(c, {
87
- isLoading: R.isLoading,
88
- isError: R.isError,
89
- isEmpty: !R.isLoading && !H,
90
- error: R.error,
91
- onRetry: () => void R.refetch(),
92
- emptyTitle: L("adaptercloud.connections.notFound", "Connection not found"),
93
- children: H && /* @__PURE__ */ A("div", {
95
+ children: [/* @__PURE__ */ k(l, {
96
+ isLoading: B.isLoading,
97
+ isError: B.isError,
98
+ isEmpty: !B.isLoading && !W,
99
+ error: B.error,
100
+ onRetry: () => void B.refetch(),
101
+ emptyTitle: z("adaptercloud.connections.notFound", "Connection not found"),
102
+ children: W && /* @__PURE__ */ A("div", {
94
103
  className: "space-y-6",
95
104
  children: [
96
- K && /* @__PURE__ */ k("p", {
105
+ X && /* @__PURE__ */ k("p", {
97
106
  role: "alert",
98
107
  "aria-live": "polite",
99
108
  className: "rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
100
- children: K
109
+ children: X
101
110
  }),
102
111
  /* @__PURE__ */ A(j, {
103
112
  className: "p-6",
104
113
  children: [
105
114
  /* @__PURE__ */ A("div", {
106
115
  className: "mb-4 flex flex-wrap items-center gap-3",
107
- children: [/* @__PURE__ */ k(s, { status: H.status }), /* @__PURE__ */ k("span", {
116
+ children: [/* @__PURE__ */ k(c, { status: W.status }), /* @__PURE__ */ k("span", {
108
117
  className: "inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
109
- children: n[H.authMethod]
118
+ children: n[W.authMethod]
110
119
  })]
111
120
  }),
112
121
  /* @__PURE__ */ A("dl", {
@@ -114,57 +123,98 @@ function P() {
114
123
  children: [
115
124
  /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("dt", {
116
125
  className: "text-text-secondary",
117
- children: L("adaptercloud.connections.region", "Region")
126
+ children: z("adaptercloud.connections.adapter", "Adapter")
118
127
  }), /* @__PURE__ */ k("dd", {
119
128
  className: "mt-0.5 font-medium text-text-primary",
120
- children: H.region ?? ""
129
+ children: W.adapter ? /* @__PURE__ */ A("button", {
130
+ type: "button",
131
+ onClick: () => L(`/adapters/${W.adapterId}`),
132
+ className: "max-w-full truncate text-left text-accent-blue hover:underline",
133
+ children: [W.adapter.name, W.adapter.version ? ` v${W.adapter.version}` : ""]
134
+ }) : "—"
121
135
  })] }),
122
136
  /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("dt", {
123
137
  className: "text-text-secondary",
124
- children: L("adaptercloud.connections.environment", "Environment")
138
+ children: z("adaptercloud.connections.region", "Region")
125
139
  }), /* @__PURE__ */ k("dd", {
126
140
  className: "mt-0.5 font-medium text-text-primary",
127
- children: H.environment ?? "—"
141
+ children: W.region ?? "—"
128
142
  })] }),
129
143
  /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("dt", {
130
144
  className: "text-text-secondary",
131
- children: L("adaptercloud.connections.resourceCount", "Resources")
145
+ children: z("adaptercloud.connections.environment", "Environment")
146
+ }), /* @__PURE__ */ k("dd", {
147
+ className: "mt-0.5 font-medium text-text-primary",
148
+ children: W.environment ?? "—"
149
+ })] }),
150
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("dt", {
151
+ className: "text-text-secondary",
152
+ children: z("adaptercloud.connections.resourceCount", "Resources")
132
153
  }), /* @__PURE__ */ k("dd", {
133
154
  className: "mt-0.5 font-medium tabular-nums text-text-primary",
134
- children: H.resourceCount
155
+ children: W.resourceCount
135
156
  })] }),
136
157
  /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("dt", {
137
158
  className: "text-text-secondary",
138
- children: L("adaptercloud.connections.lastSynced", "Last synced")
159
+ children: z("adaptercloud.connections.lastSynced", "Last synced")
139
160
  }), /* @__PURE__ */ k("dd", {
140
161
  className: "mt-0.5 font-medium text-text-primary",
141
- children: H.lastSyncedAt ? p(H.lastSyncedAt) : "—"
162
+ children: W.lastSyncedAt ? p(W.lastSyncedAt) : "—"
142
163
  })] })
143
164
  ]
144
165
  }),
145
- H.lastError && /* @__PURE__ */ k("p", {
166
+ (W.targetRef || W.secretRef) && /* @__PURE__ */ A("dl", {
167
+ className: "mt-4 space-y-3 border-t border-border-subtle pt-4 text-sm",
168
+ children: [W.targetRef && /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("dt", {
169
+ className: "text-text-secondary",
170
+ children: z("adaptercloud.connections.targetRef", "Target ref")
171
+ }), /* @__PURE__ */ k("dd", {
172
+ className: "mt-1 break-all rounded-lg bg-bg-sunken px-3 py-1.5 font-mono text-xs text-text-primary",
173
+ children: W.targetRef
174
+ })] }), W.secretRef && /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("dt", {
175
+ className: "text-text-secondary",
176
+ children: z("adaptercloud.connections.secretRef", "Secret ref")
177
+ }), /* @__PURE__ */ k("dd", {
178
+ className: "mt-1 break-all rounded-lg bg-bg-sunken px-3 py-1.5 font-mono text-xs text-text-primary",
179
+ children: W.secretRef
180
+ })] })]
181
+ }),
182
+ W.tags.length > 0 && /* @__PURE__ */ A("div", {
183
+ className: "mt-4",
184
+ children: [/* @__PURE__ */ k("h3", {
185
+ className: "mb-2 text-sm font-semibold text-text-primary",
186
+ children: z("adaptercloud.common.tags", "Tags")
187
+ }), /* @__PURE__ */ k("div", {
188
+ className: "flex flex-wrap gap-1.5",
189
+ children: W.tags.map((e) => /* @__PURE__ */ k("span", {
190
+ className: "inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary",
191
+ children: e
192
+ }, e))
193
+ })]
194
+ }),
195
+ W.lastError && /* @__PURE__ */ k("p", {
146
196
  className: "mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
147
- children: H.lastError
197
+ children: W.lastError
148
198
  }),
149
199
  /* @__PURE__ */ A("div", {
150
200
  className: "mt-5 border-t border-border-subtle pt-5",
151
201
  children: [/* @__PURE__ */ k("h3", {
152
202
  className: "mb-3 text-sm font-semibold text-text-primary",
153
- children: L("adaptercloud.connections.setHealth", "Set health")
203
+ children: z("adaptercloud.connections.setHealth", "Set health")
154
204
  }), /* @__PURE__ */ A("div", {
155
205
  className: "flex flex-wrap gap-2",
156
206
  children: [M.map((e) => /* @__PURE__ */ k("button", {
157
207
  type: "button",
158
- disabled: z.isPending || H.status === e,
159
- onClick: () => Z(e),
208
+ disabled: V.isPending || W.status === e,
209
+ onClick: () => ie(e),
160
210
  className: "rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-40",
161
211
  children: r[e]
162
- }, e)), H.status !== "DISABLED" && /* @__PURE__ */ A("button", {
212
+ }, e)), W.status !== "DISABLED" && /* @__PURE__ */ A("button", {
163
213
  type: "button",
164
- disabled: B.isPending,
165
- onClick: () => Y(!0),
214
+ disabled: H.isPending,
215
+ onClick: () => Q(!0),
166
216
  className: "inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-40",
167
- children: [/* @__PURE__ */ k(S, { className: "h-3.5 w-3.5" }), L("adaptercloud.connections.disable", "Disable")]
217
+ children: [/* @__PURE__ */ k(S, { className: "h-3.5 w-3.5" }), z("adaptercloud.connections.disable", "Disable")]
168
218
  })]
169
219
  })]
170
220
  }),
@@ -173,35 +223,35 @@ function P() {
173
223
  children: [
174
224
  /* @__PURE__ */ A("h3", {
175
225
  className: "mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary",
176
- children: [/* @__PURE__ */ k(E, { className: "h-4 w-4" }), L("adaptercloud.connections.startSync", "Start a sync run")]
226
+ children: [/* @__PURE__ */ k(E, { className: "h-4 w-4" }), z("adaptercloud.connections.startSync", "Start a sync run")]
177
227
  }),
178
- !U && /* @__PURE__ */ k("p", {
228
+ !G && /* @__PURE__ */ k("p", {
179
229
  id: "disabled-connection-sync-help",
180
230
  className: "mb-3 text-sm text-text-secondary",
181
- children: L("adaptercloud.connections.disabledSyncHelp", "Sync runs are unavailable while this connection is disabled. Set its health to re-enable sync.")
231
+ children: z("adaptercloud.connections.disabledSyncHelp", "Sync runs are unavailable while this connection is disabled. Set its health to re-enable sync.")
182
232
  }),
183
233
  /* @__PURE__ */ k("p", {
184
234
  id: "unsupported-sync-kind-help",
185
235
  className: "mb-3 text-sm text-text-secondary",
186
- children: L("adaptercloud.connections.syncModeAvailabilityHelp", "Discovery is executable today. Reconcile, Cost Ingest, and Full need distinct backend workers and are not available yet.")
236
+ children: z("adaptercloud.connections.syncModeAvailabilityHelp", "Discovery is executable today. Reconcile, Cost Ingest, and Full need distinct backend workers and are not available yet.")
187
237
  }),
188
238
  /* @__PURE__ */ k("div", {
189
239
  className: "flex flex-wrap gap-2",
190
240
  children: N.map((e) => {
191
- let t = V.isPending && W === e, n = _(e);
241
+ let t = U.isPending && J === e, n = v(e);
192
242
  return /* @__PURE__ */ A("button", {
193
243
  type: "button",
194
- disabled: V.isPending || !U || !n,
195
- "aria-describedby": n ? U ? void 0 : "disabled-connection-sync-help" : "unsupported-sync-kind-help",
196
- title: n ? U ? void 0 : L("adaptercloud.connections.disabledSyncTooltip", "Re-enable this connection before starting a sync run.") : L("adaptercloud.connections.unsupportedSyncModeTooltip", "This sync mode is not available yet because it needs a distinct backend worker."),
197
- onClick: () => $(e),
244
+ disabled: U.isPending || !G || !n,
245
+ "aria-describedby": n ? G ? void 0 : "disabled-connection-sync-help" : "unsupported-sync-kind-help",
246
+ title: n ? G ? void 0 : z("adaptercloud.connections.disabledSyncTooltip", "Re-enable this connection before starting a sync run.") : z("adaptercloud.connections.unsupportedSyncModeTooltip", "This sync mode is not available yet because it needs a distinct backend worker."),
247
+ onClick: () => oe(e),
198
248
  className: "inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50",
199
249
  children: [
200
250
  t ? /* @__PURE__ */ k(C, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ k(T, { className: "h-4 w-4" }),
201
251
  o[e],
202
252
  !n && /* @__PURE__ */ k("span", {
203
253
  className: "rounded bg-bg-sunken px-1.5 py-0.5 text-[10px] font-normal text-text-secondary",
204
- children: L("adaptercloud.connections.notAvailable", "Not available")
254
+ children: z("adaptercloud.connections.notAvailable", "Not available")
205
255
  })
206
256
  ]
207
257
  }, e);
@@ -211,32 +261,95 @@ function P() {
211
261
  })
212
262
  ]
213
263
  }),
214
- H.config != null && /* @__PURE__ */ A(j, {
264
+ /* @__PURE__ */ A("section", { children: [/* @__PURE__ */ A("div", {
265
+ className: "mb-3 flex items-center justify-between",
266
+ children: [/* @__PURE__ */ k("h3", {
267
+ className: "text-base font-semibold text-text-primary",
268
+ children: z("adaptercloud.connections.recentRuns", "Recent Sync Runs")
269
+ }), /* @__PURE__ */ k("button", {
270
+ type: "button",
271
+ onClick: () => L(`/sync-runs?connectionId=${W.id}`),
272
+ className: "text-sm font-medium text-accent-blue hover:underline",
273
+ children: z("adaptercloud.common.viewAll", "View all")
274
+ })]
275
+ }), /* @__PURE__ */ k(l, {
276
+ isLoading: K.isLoading,
277
+ isError: K.isError,
278
+ isEmpty: q.length === 0,
279
+ error: K.error,
280
+ onRetry: () => void K.refetch(),
281
+ emptyTitle: z("adaptercloud.connections.noRuns", "No sync runs yet"),
282
+ emptyDescription: z("adaptercloud.connections.noRunsDescription", "Start a sync run above to keep this connection’s inventory current."),
283
+ emptyIcon: /* @__PURE__ */ k(E, { className: "h-10 w-10" }),
284
+ children: /* @__PURE__ */ k("div", {
285
+ className: "divide-y divide-border rounded-xl border border-border-subtle bg-bg-surface",
286
+ children: q.map((e) => /* @__PURE__ */ A("div", {
287
+ className: "flex flex-wrap items-center gap-x-4 gap-y-2 px-4 py-3",
288
+ children: [
289
+ /* @__PURE__ */ k("span", {
290
+ className: "min-w-24 text-sm font-medium text-text-primary",
291
+ children: o[e.kind]
292
+ }),
293
+ /* @__PURE__ */ k(c, {
294
+ status: e.status,
295
+ label: s[e.status]
296
+ }),
297
+ /* @__PURE__ */ A("span", {
298
+ className: "text-xs text-text-secondary",
299
+ children: [
300
+ z("adaptercloud.syncRuns.discovered", "Discovered"),
301
+ " ",
302
+ /* @__PURE__ */ k("span", {
303
+ className: "tabular-nums text-text-primary",
304
+ children: F(e.status) ? "—" : e.discoveredCount
305
+ })
306
+ ]
307
+ }),
308
+ /* @__PURE__ */ A("span", {
309
+ className: "text-xs text-text-secondary",
310
+ children: [
311
+ z("adaptercloud.syncRuns.drift", "Drift"),
312
+ " ",
313
+ /* @__PURE__ */ k("span", {
314
+ className: "tabular-nums text-text-primary",
315
+ children: F(e.status) ? "—" : e.driftCount
316
+ })
317
+ ]
318
+ }),
319
+ /* @__PURE__ */ k("span", {
320
+ className: "ml-auto text-xs text-text-secondary",
321
+ children: e.finishedAt ? m(e.finishedAt) : z("adaptercloud.syncRuns.notFinished", "Not finished")
322
+ })
323
+ ]
324
+ }, e.id))
325
+ })
326
+ })] }),
327
+ W.config != null && /* @__PURE__ */ A(j, {
215
328
  className: "p-6",
216
329
  children: [/* @__PURE__ */ k("h3", {
217
330
  className: "mb-3 text-sm font-semibold text-text-primary",
218
- children: L("adaptercloud.connections.config", "Configuration")
331
+ children: z("adaptercloud.connections.config", "Configuration")
219
332
  }), /* @__PURE__ */ k("pre", {
220
333
  className: "overflow-auto rounded-lg bg-bg-sunken p-4 text-xs text-text-secondary",
221
- children: JSON.stringify(H.config, null, 2)
334
+ children: JSON.stringify(W.config, null, 2)
222
335
  })]
223
336
  }),
224
337
  /* @__PURE__ */ A("section", { children: [/* @__PURE__ */ A("div", {
225
338
  className: "mb-3 flex items-center justify-between",
226
339
  children: [/* @__PURE__ */ k("h3", {
227
340
  className: "text-base font-semibold text-text-primary",
228
- children: L("adaptercloud.connections.discoveredResources", "Discovered Resources")
341
+ children: z("adaptercloud.connections.discoveredResources", "Discovered Resources")
229
342
  }), /* @__PURE__ */ k("button", {
230
343
  type: "button",
231
- onClick: () => F(`/resources?connectionId=${H.id}`),
344
+ onClick: () => L(`/resources?connectionId=${W.id}`),
232
345
  className: "text-sm font-medium text-accent-blue hover:underline",
233
- children: L("adaptercloud.common.viewAll", "View all")
346
+ children: z("adaptercloud.common.viewAll", "View all")
234
347
  })]
235
- }), H.resources && H.resources.length > 0 ? /* @__PURE__ */ k("div", {
348
+ }), W.resources && W.resources.length > 0 ? /* @__PURE__ */ k("div", {
236
349
  className: "divide-y divide-border rounded-xl border border-border-subtle bg-bg-surface",
237
- children: H.resources.slice(0, 10).map((e) => /* @__PURE__ */ A("button", {
350
+ children: W.resources.slice(0, 10).map((e) => /* @__PURE__ */ A("button", {
238
351
  type: "button",
239
- onClick: () => F(`/resources/${e.id}`),
352
+ onClick: () => L(`/resources/${e.id}`),
240
353
  className: "flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-accent/50",
241
354
  children: [
242
355
  /* @__PURE__ */ k(D, { className: "h-4 w-4 shrink-0 text-text-secondary" }),
@@ -254,7 +367,7 @@ function P() {
254
367
  className: "hidden text-xs text-text-secondary sm:inline",
255
368
  children: i(e.monthlyCost)
256
369
  }),
257
- /* @__PURE__ */ k(s, {
370
+ /* @__PURE__ */ k(c, {
258
371
  status: e.state,
259
372
  label: a[e.state]
260
373
  })
@@ -262,24 +375,24 @@ function P() {
262
375
  }, e.id))
263
376
  }) : /* @__PURE__ */ k("p", {
264
377
  className: "rounded-xl border border-border-subtle bg-bg-surface px-4 py-6 text-center text-sm text-text-secondary",
265
- children: L("adaptercloud.connections.noResources", "No resources discovered yet. Start a discovery sync run.")
378
+ children: z("adaptercloud.connections.noResources", "No resources discovered yet. Start a discovery sync run.")
266
379
  })] })
267
380
  ]
268
381
  })
269
- }), /* @__PURE__ */ k(m, {
270
- open: J,
271
- onOpenChange: Y,
272
- title: L("adaptercloud.connections.disableTitle", "Disable this connection?"),
273
- description: L("adaptercloud.connections.disablePrompt", "Disabling stops discovery and sync runs against this target. You can re-enable it later by setting its health."),
274
- confirmLabel: L("adaptercloud.connections.disable", "Disable"),
275
- cancelLabel: L("adaptercloud.common.cancel", "Cancel"),
276
- onConfirm: Q,
277
- isPending: B.isPending,
382
+ }), /* @__PURE__ */ k(h, {
383
+ open: re,
384
+ onOpenChange: Q,
385
+ title: z("adaptercloud.connections.disableTitle", "Disable this connection?"),
386
+ description: z("adaptercloud.connections.disablePrompt", "Disabling stops discovery and sync runs against this target. You can re-enable it later by setting its health."),
387
+ confirmLabel: z("adaptercloud.connections.disable", "Disable"),
388
+ cancelLabel: z("adaptercloud.common.cancel", "Cancel"),
389
+ onConfirm: ae,
390
+ isPending: H.isPending,
278
391
  tone: "danger"
279
392
  })]
280
393
  });
281
394
  }
282
395
  //#endregion
283
- export { P as ConnectionDetailPage };
396
+ export { I as ConnectionDetailPage };
284
397
 
285
398
  //# sourceMappingURL=ConnectionDetailPage.js.map