@burdenoff/microfe-adaptercloud 2026.625.2 → 2026.628.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 (153) hide show
  1. package/dist/adaptercloud/AdapterCloudRoot.js +65 -121
  2. package/dist/adaptercloud/AdapterCloudRoot.js.map +1 -1
  3. package/dist/adaptercloud/AdapterCloudRoutes.js +70 -182
  4. package/dist/adaptercloud/AdapterCloudRoutes.js.map +1 -1
  5. package/dist/adaptercloud/components/DataState.js +42 -0
  6. package/dist/adaptercloud/components/DataState.js.map +1 -0
  7. package/dist/adaptercloud/components/SeverityBadge.js +12 -0
  8. package/dist/adaptercloud/components/SeverityBadge.js.map +1 -0
  9. package/dist/adaptercloud/components/StatusBadge.js +43 -44
  10. package/dist/adaptercloud/components/StatusBadge.js.map +1 -1
  11. package/dist/adaptercloud/context/AdapterCloudContext.js +22 -30
  12. package/dist/adaptercloud/context/AdapterCloudContext.js.map +1 -1
  13. package/dist/adaptercloud/hooks/useAdapterCloudApi.js +397 -194
  14. package/dist/adaptercloud/hooks/useAdapterCloudApi.js.map +1 -1
  15. package/dist/adaptercloud/index.js +1 -0
  16. package/dist/adaptercloud/pages/OverviewPage.js +334 -0
  17. package/dist/adaptercloud/pages/OverviewPage.js.map +1 -0
  18. package/dist/adaptercloud/pages/adapters/AdapterDetailPage.js +187 -0
  19. package/dist/adaptercloud/pages/adapters/AdapterDetailPage.js.map +1 -0
  20. package/dist/adaptercloud/pages/adapters/AdapterFormPage.js +278 -0
  21. package/dist/adaptercloud/pages/adapters/AdapterFormPage.js.map +1 -0
  22. package/dist/adaptercloud/pages/adapters/AdaptersListPage.js +172 -0
  23. package/dist/adaptercloud/pages/adapters/AdaptersListPage.js.map +1 -0
  24. package/dist/adaptercloud/pages/connections/ConnectionDetailPage.js +247 -0
  25. package/dist/adaptercloud/pages/connections/ConnectionDetailPage.js.map +1 -0
  26. package/dist/adaptercloud/pages/connections/ConnectionFormPage.js +271 -0
  27. package/dist/adaptercloud/pages/connections/ConnectionFormPage.js.map +1 -0
  28. package/dist/adaptercloud/pages/connections/ConnectionsListPage.js +167 -0
  29. package/dist/adaptercloud/pages/connections/ConnectionsListPage.js.map +1 -0
  30. package/dist/adaptercloud/pages/costs/CostsPage.js +169 -0
  31. package/dist/adaptercloud/pages/costs/CostsPage.js.map +1 -0
  32. package/dist/adaptercloud/pages/drift/DriftListPage.js +132 -0
  33. package/dist/adaptercloud/pages/drift/DriftListPage.js.map +1 -0
  34. package/dist/adaptercloud/pages/policies/PoliciesListPage.js +171 -0
  35. package/dist/adaptercloud/pages/policies/PoliciesListPage.js.map +1 -0
  36. package/dist/adaptercloud/pages/policies/PolicyDetailPage.js +185 -0
  37. package/dist/adaptercloud/pages/policies/PolicyDetailPage.js.map +1 -0
  38. package/dist/adaptercloud/pages/policies/PolicyFormPage.js +215 -0
  39. package/dist/adaptercloud/pages/policies/PolicyFormPage.js.map +1 -0
  40. package/dist/adaptercloud/pages/resources/ResourceDetailPage.js +207 -0
  41. package/dist/adaptercloud/pages/resources/ResourceDetailPage.js.map +1 -0
  42. package/dist/adaptercloud/pages/resources/ResourcesListPage.js +182 -0
  43. package/dist/adaptercloud/pages/resources/ResourcesListPage.js.map +1 -0
  44. package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.js +196 -0
  45. package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.js.map +1 -0
  46. package/dist/adaptercloud/pages/violations/ViolationsListPage.js +258 -0
  47. package/dist/adaptercloud/pages/violations/ViolationsListPage.js.map +1 -0
  48. package/dist/adaptercloud/store/adaptercloudStore.js +1 -7
  49. package/dist/adaptercloud/store/adaptercloudStore.js.map +1 -1
  50. package/dist/adaptercloud/utils/domain.js +105 -0
  51. package/dist/adaptercloud/utils/domain.js.map +1 -0
  52. package/dist/adaptercloud/utils/formatters.js +1 -12
  53. package/dist/adaptercloud/utils/formatters.js.map +1 -1
  54. package/dist/index.js +5 -4
  55. package/package.json +1 -1
  56. package/dist/adaptercloud/components/InvestmentCard.js +0 -98
  57. package/dist/adaptercloud/components/InvestmentCard.js.map +0 -1
  58. package/dist/adaptercloud/components/RatingDisplay.js +0 -35
  59. package/dist/adaptercloud/components/RatingDisplay.js.map +0 -1
  60. package/dist/adaptercloud/mocks/data.js +0 -1517
  61. package/dist/adaptercloud/mocks/data.js.map +0 -1
  62. package/dist/adaptercloud/mocks/users.js +0 -34
  63. package/dist/adaptercloud/mocks/users.js.map +0 -1
  64. package/dist/adaptercloud/pages/HomePage.js +0 -934
  65. package/dist/adaptercloud/pages/HomePage.js.map +0 -1
  66. package/dist/adaptercloud/pages/admin/AdminAnalyticsPage.js +0 -653
  67. package/dist/adaptercloud/pages/admin/AdminAnalyticsPage.js.map +0 -1
  68. package/dist/adaptercloud/pages/admin/AdminDashboard.js +0 -665
  69. package/dist/adaptercloud/pages/admin/AdminDashboard.js.map +0 -1
  70. package/dist/adaptercloud/pages/admin/AdminFinancialPage.js +0 -426
  71. package/dist/adaptercloud/pages/admin/AdminFinancialPage.js.map +0 -1
  72. package/dist/adaptercloud/pages/admin/AdminOrdersPage.js +0 -665
  73. package/dist/adaptercloud/pages/admin/AdminOrdersPage.js.map +0 -1
  74. package/dist/adaptercloud/pages/admin/AdminProfilePage.js +0 -261
  75. package/dist/adaptercloud/pages/admin/AdminProfilePage.js.map +0 -1
  76. package/dist/adaptercloud/pages/admin/AdminSettingsPage.js +0 -663
  77. package/dist/adaptercloud/pages/admin/AdminSettingsPage.js.map +0 -1
  78. package/dist/adaptercloud/pages/admin/CartManagementPage.js +0 -874
  79. package/dist/adaptercloud/pages/admin/CartManagementPage.js.map +0 -1
  80. package/dist/adaptercloud/pages/admin/UserManagementPage.js +0 -898
  81. package/dist/adaptercloud/pages/admin/UserManagementPage.js.map +0 -1
  82. package/dist/adaptercloud/pages/cart-owner/AnalyticsDashboard.js +0 -840
  83. package/dist/adaptercloud/pages/cart-owner/AnalyticsDashboard.js.map +0 -1
  84. package/dist/adaptercloud/pages/cart-owner/BusinessSettingsPage.js +0 -714
  85. package/dist/adaptercloud/pages/cart-owner/BusinessSettingsPage.js.map +0 -1
  86. package/dist/adaptercloud/pages/cart-owner/CartOwnerDashboard.js +0 -788
  87. package/dist/adaptercloud/pages/cart-owner/CartOwnerDashboard.js.map +0 -1
  88. package/dist/adaptercloud/pages/cart-owner/CartOwnerProfilePage.js +0 -888
  89. package/dist/adaptercloud/pages/cart-owner/CartOwnerProfilePage.js.map +0 -1
  90. package/dist/adaptercloud/pages/cart-owner/CartServiceConfigPage.js +0 -634
  91. package/dist/adaptercloud/pages/cart-owner/CartServiceConfigPage.js.map +0 -1
  92. package/dist/adaptercloud/pages/cart-owner/InventoryManagementPage.js +0 -907
  93. package/dist/adaptercloud/pages/cart-owner/InventoryManagementPage.js.map +0 -1
  94. package/dist/adaptercloud/pages/cart-owner/OrderManagementPage.js +0 -875
  95. package/dist/adaptercloud/pages/cart-owner/OrderManagementPage.js.map +0 -1
  96. package/dist/adaptercloud/pages/cart-owner/StaffManagementPage.js +0 -827
  97. package/dist/adaptercloud/pages/cart-owner/StaffManagementPage.js.map +0 -1
  98. package/dist/adaptercloud/pages/common/HelpSupportPage.js +0 -1329
  99. package/dist/adaptercloud/pages/common/HelpSupportPage.js.map +0 -1
  100. package/dist/adaptercloud/pages/common/NotificationCenterPage.js +0 -671
  101. package/dist/adaptercloud/pages/common/NotificationCenterPage.js.map +0 -1
  102. package/dist/adaptercloud/pages/common/SettingsPage.js +0 -982
  103. package/dist/adaptercloud/pages/common/SettingsPage.js.map +0 -1
  104. package/dist/adaptercloud/pages/customer/BookingDetailsPage.js +0 -596
  105. package/dist/adaptercloud/pages/customer/BookingDetailsPage.js.map +0 -1
  106. package/dist/adaptercloud/pages/customer/CartDetailPage.js +0 -623
  107. package/dist/adaptercloud/pages/customer/CartDetailPage.js.map +0 -1
  108. package/dist/adaptercloud/pages/customer/CartDiscoveryPage.js +0 -552
  109. package/dist/adaptercloud/pages/customer/CartDiscoveryPage.js.map +0 -1
  110. package/dist/adaptercloud/pages/customer/CheckoutPage.js +0 -534
  111. package/dist/adaptercloud/pages/customer/CheckoutPage.js.map +0 -1
  112. package/dist/adaptercloud/pages/customer/CustomerDashboard.js +0 -525
  113. package/dist/adaptercloud/pages/customer/CustomerDashboard.js.map +0 -1
  114. package/dist/adaptercloud/pages/customer/CustomerProfilePage.js +0 -623
  115. package/dist/adaptercloud/pages/customer/CustomerProfilePage.js.map +0 -1
  116. package/dist/adaptercloud/pages/customer/DirectServiceBookingPage.js +0 -629
  117. package/dist/adaptercloud/pages/customer/DirectServiceBookingPage.js.map +0 -1
  118. package/dist/adaptercloud/pages/customer/FavoritesPage.js +0 -480
  119. package/dist/adaptercloud/pages/customer/FavoritesPage.js.map +0 -1
  120. package/dist/adaptercloud/pages/customer/OrderHistoryPage.js +0 -444
  121. package/dist/adaptercloud/pages/customer/OrderHistoryPage.js.map +0 -1
  122. package/dist/adaptercloud/pages/customer/OrderTrackingPage.js +0 -391
  123. package/dist/adaptercloud/pages/customer/OrderTrackingPage.js.map +0 -1
  124. package/dist/adaptercloud/pages/customer/PaymentMethodsPage.js +0 -504
  125. package/dist/adaptercloud/pages/customer/PaymentMethodsPage.js.map +0 -1
  126. package/dist/adaptercloud/pages/customer/ReviewsPage.js +0 -609
  127. package/dist/adaptercloud/pages/customer/ReviewsPage.js.map +0 -1
  128. package/dist/adaptercloud/pages/customer/SavedAddressesPage.js +0 -459
  129. package/dist/adaptercloud/pages/customer/SavedAddressesPage.js.map +0 -1
  130. package/dist/adaptercloud/pages/investor/InvestmentDetailsPage.js +0 -851
  131. package/dist/adaptercloud/pages/investor/InvestmentDetailsPage.js.map +0 -1
  132. package/dist/adaptercloud/pages/investor/InvestmentOpportunitiesPage.js +0 -942
  133. package/dist/adaptercloud/pages/investor/InvestmentOpportunitiesPage.js.map +0 -1
  134. package/dist/adaptercloud/pages/investor/InvestorAnalyticsPage.js +0 -683
  135. package/dist/adaptercloud/pages/investor/InvestorAnalyticsPage.js.map +0 -1
  136. package/dist/adaptercloud/pages/investor/InvestorDashboard.js +0 -452
  137. package/dist/adaptercloud/pages/investor/InvestorDashboard.js.map +0 -1
  138. package/dist/adaptercloud/pages/investor/InvestorInvestmentsPage.js +0 -402
  139. package/dist/adaptercloud/pages/investor/InvestorInvestmentsPage.js.map +0 -1
  140. package/dist/adaptercloud/pages/investor/InvestorPortfolioPage.js +0 -571
  141. package/dist/adaptercloud/pages/investor/InvestorPortfolioPage.js.map +0 -1
  142. package/dist/adaptercloud/pages/investor/InvestorProfilePage.js +0 -1067
  143. package/dist/adaptercloud/pages/investor/InvestorProfilePage.js.map +0 -1
  144. package/dist/adaptercloud/pages/worker/TaskDetailsPage.js +0 -526
  145. package/dist/adaptercloud/pages/worker/TaskDetailsPage.js.map +0 -1
  146. package/dist/adaptercloud/pages/worker/WorkerDashboard.js +0 -659
  147. package/dist/adaptercloud/pages/worker/WorkerDashboard.js.map +0 -1
  148. package/dist/adaptercloud/pages/worker/WorkerOrdersPage.js +0 -678
  149. package/dist/adaptercloud/pages/worker/WorkerOrdersPage.js.map +0 -1
  150. package/dist/adaptercloud/pages/worker/WorkerProfilePage.js +0 -689
  151. package/dist/adaptercloud/pages/worker/WorkerProfilePage.js.map +0 -1
  152. package/dist/adaptercloud/pages/worker/WorkerSchedulePage.js +0 -582
  153. package/dist/adaptercloud/pages/worker/WorkerSchedulePage.js.map +0 -1
@@ -0,0 +1,185 @@
1
+ import { useAdapterCloud as e } from "../../context/AdapterCloudContext.js";
2
+ import { cn as t } from "../../utils/cn.js";
3
+ import { PageLayout as n } from "../../components/PageLayout.js";
4
+ import { policyEnforcementLabels as r, policyKindLabels as i } from "../../utils/domain.js";
5
+ import { StatusBadge as a } from "../../components/StatusBadge.js";
6
+ import { SeverityBadge as o } from "../../components/SeverityBadge.js";
7
+ import { DataState as s } from "../../components/DataState.js";
8
+ import { useArchivePolicy as c, usePolicy as l } from "../../hooks/useAdapterCloudApi.js";
9
+ import { formatDate as u, formatRelativeTime as d } from "../../utils/formatters.js";
10
+ import { useCallback as f } from "react";
11
+ import { useI18n as p } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
12
+ import { AlertCircle as m, Archive as h, ArrowLeft as g } from "lucide-react";
13
+ import { useParams as _ } from "react-router-dom";
14
+ import { jsx as v, jsxs as y } from "react/jsx-runtime";
15
+ import { GlassCard as b } from "@burdenoff/fe-libs/ui";
16
+ //#region src/adaptercloud/pages/policies/PolicyDetailPage.tsx
17
+ function x() {
18
+ let { id: x } = _(), { navigateTo: S } = e(), { t: C } = p(), w = f((e, t) => {
19
+ let n = C(e);
20
+ return n === e ? t : n;
21
+ }, [C]), T = l(x), E = c(), D = T.data, O = f(() => {
22
+ x && E.mutate(x, { onSuccess: () => S("/policies") });
23
+ }, [
24
+ E,
25
+ x,
26
+ S
27
+ ]);
28
+ return /* @__PURE__ */ v(n, {
29
+ title: D?.name ?? w("adaptercloud.policies.detailTitle", "Policy"),
30
+ description: D ? i[D.kind] : void 0,
31
+ actions: /* @__PURE__ */ y("div", {
32
+ className: "flex items-center gap-2",
33
+ children: [/* @__PURE__ */ y("button", {
34
+ type: "button",
35
+ onClick: () => S("/policies"),
36
+ 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",
37
+ children: [/* @__PURE__ */ v(g, { className: "h-4 w-4" }), w("adaptercloud.common.back", "Back")]
38
+ }), D && /* @__PURE__ */ y("button", {
39
+ type: "button",
40
+ onClick: O,
41
+ disabled: E.isPending,
42
+ 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-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50",
43
+ children: [/* @__PURE__ */ v(h, { className: "h-4 w-4" }), w("adaptercloud.common.archive", "Archive")]
44
+ })]
45
+ }),
46
+ children: /* @__PURE__ */ v(s, {
47
+ isLoading: T.isLoading,
48
+ isError: T.isError,
49
+ isEmpty: !T.isLoading && !D,
50
+ error: T.error,
51
+ onRetry: () => void T.refetch(),
52
+ emptyTitle: w("adaptercloud.policies.notFound", "Policy not found"),
53
+ children: D && /* @__PURE__ */ y("div", {
54
+ className: "space-y-6",
55
+ children: [
56
+ /* @__PURE__ */ y(b, {
57
+ className: "p-6",
58
+ children: [
59
+ /* @__PURE__ */ y("div", {
60
+ className: "mb-4 flex flex-wrap items-center gap-3",
61
+ children: [
62
+ /* @__PURE__ */ v(o, { severity: D.severity }),
63
+ /* @__PURE__ */ v("span", {
64
+ className: "inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
65
+ children: r[D.enforcement]
66
+ }),
67
+ /* @__PURE__ */ v("span", {
68
+ className: t("inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium", D.isActive ? "bg-status-success-bg-subtle text-status-success-text" : "bg-bg-sunken text-text-secondary"),
69
+ children: D.isActive ? w("adaptercloud.policies.active", "Active") : w("adaptercloud.policies.inactive", "Inactive")
70
+ })
71
+ ]
72
+ }),
73
+ D.description && /* @__PURE__ */ v("p", {
74
+ className: "mb-4 text-sm text-text-secondary",
75
+ children: D.description
76
+ }),
77
+ /* @__PURE__ */ y("dl", {
78
+ className: "grid grid-cols-2 gap-4 text-sm sm:grid-cols-3",
79
+ children: [
80
+ /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("dt", {
81
+ className: "text-text-secondary",
82
+ children: w("adaptercloud.policies.kind", "Kind")
83
+ }), /* @__PURE__ */ v("dd", {
84
+ className: "mt-0.5 font-medium text-text-primary",
85
+ children: i[D.kind]
86
+ })] }),
87
+ /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("dt", {
88
+ className: "text-text-secondary",
89
+ children: w("adaptercloud.common.created", "Created")
90
+ }), /* @__PURE__ */ v("dd", {
91
+ className: "mt-0.5 font-medium text-text-primary",
92
+ children: u(D.createdAt)
93
+ })] }),
94
+ /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("dt", {
95
+ className: "text-text-secondary",
96
+ children: w("adaptercloud.common.updated", "Updated")
97
+ }), /* @__PURE__ */ v("dd", {
98
+ className: "mt-0.5 font-medium text-text-primary",
99
+ children: u(D.updatedAt)
100
+ })] })
101
+ ]
102
+ }),
103
+ D.appliesTo.length > 0 && /* @__PURE__ */ y("div", {
104
+ className: "mt-5",
105
+ children: [/* @__PURE__ */ v("h3", {
106
+ className: "mb-2 text-sm font-semibold text-text-primary",
107
+ children: w("adaptercloud.policies.appliesTo", "Applies To")
108
+ }), /* @__PURE__ */ v("div", {
109
+ className: "flex flex-wrap gap-1.5",
110
+ children: D.appliesTo.map((e) => /* @__PURE__ */ v("span", {
111
+ className: "inline-flex items-center rounded-full bg-accent-blue-subtle px-2.5 py-0.5 font-mono text-xs text-accent-blue",
112
+ children: e
113
+ }, e))
114
+ })]
115
+ }),
116
+ D.tags.length > 0 && /* @__PURE__ */ y("div", {
117
+ className: "mt-4",
118
+ children: [/* @__PURE__ */ v("h3", {
119
+ className: "mb-2 text-sm font-semibold text-text-primary",
120
+ children: w("adaptercloud.common.tags", "Tags")
121
+ }), /* @__PURE__ */ v("div", {
122
+ className: "flex flex-wrap gap-1.5",
123
+ children: D.tags.map((e) => /* @__PURE__ */ v("span", {
124
+ className: "inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary",
125
+ children: e
126
+ }, e))
127
+ })]
128
+ })
129
+ ]
130
+ }),
131
+ /* @__PURE__ */ y(b, {
132
+ className: "p-6",
133
+ children: [/* @__PURE__ */ v("h3", {
134
+ className: "mb-3 text-sm font-semibold text-text-primary",
135
+ children: w("adaptercloud.policies.expression", "Expression")
136
+ }), /* @__PURE__ */ v("pre", {
137
+ className: "overflow-auto rounded-lg bg-bg-sunken p-4 text-xs text-text-secondary",
138
+ children: JSON.stringify(D.expression, null, 2)
139
+ })]
140
+ }),
141
+ /* @__PURE__ */ y("section", { children: [/* @__PURE__ */ y("div", {
142
+ className: "mb-3 flex items-center justify-between",
143
+ children: [/* @__PURE__ */ v("h3", {
144
+ className: "text-base font-semibold text-text-primary",
145
+ children: w("adaptercloud.policies.violations", "Violations")
146
+ }), /* @__PURE__ */ v("button", {
147
+ type: "button",
148
+ onClick: () => S(`/violations?policyId=${D.id}`),
149
+ className: "text-sm font-medium text-primary hover:underline",
150
+ children: w("adaptercloud.common.viewAll", "View all")
151
+ })]
152
+ }), D.violations && D.violations.length > 0 ? /* @__PURE__ */ v("div", {
153
+ className: "divide-y divide-border rounded-xl border border-border-subtle bg-bg-surface",
154
+ children: D.violations.slice(0, 10).map((e) => /* @__PURE__ */ y("button", {
155
+ type: "button",
156
+ onClick: () => S(`/violations?policyId=${D.id}`),
157
+ className: "flex w-full items-start gap-3 px-4 py-3 text-left transition-colors hover:bg-accent/50",
158
+ children: [
159
+ /* @__PURE__ */ v(m, { className: "mt-0.5 h-4 w-4 shrink-0 text-status-error-text" }),
160
+ /* @__PURE__ */ y("div", {
161
+ className: "min-w-0 flex-1",
162
+ children: [/* @__PURE__ */ v("p", {
163
+ className: "truncate text-sm font-medium text-text-primary",
164
+ children: e.message
165
+ }), /* @__PURE__ */ v("p", {
166
+ className: "mt-0.5 text-xs text-text-secondary",
167
+ children: d(e.detectedAt)
168
+ })]
169
+ }),
170
+ /* @__PURE__ */ v(a, { status: e.status })
171
+ ]
172
+ }, e.id))
173
+ }) : /* @__PURE__ */ v("p", {
174
+ className: "rounded-xl border border-border-subtle bg-bg-surface px-4 py-6 text-center text-sm text-text-secondary",
175
+ children: w("adaptercloud.policies.noViolations", "No violations recorded for this policy.")
176
+ })] })
177
+ ]
178
+ })
179
+ })
180
+ });
181
+ }
182
+ //#endregion
183
+ export { x as PolicyDetailPage };
184
+
185
+ //# sourceMappingURL=PolicyDetailPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PolicyDetailPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/policies/PolicyDetailPage.tsx"],"sourcesContent":["/**\n * Policy Detail Page\n * @module adaptercloud/pages/policies\n *\n * One governance policy (`adaPolicy`) — its kind, enforcement, severity, JSON\n * expression, applies-to selector, and the violations it has produced. Supports\n * archiving via `adaArchivePolicy`.\n */\n\nimport { useCallback } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { ArrowLeft, Archive, AlertCircle } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { SeverityBadge } from '../../components/SeverityBadge';\nimport { DataState } from '../../components/DataState';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { usePolicy, useArchivePolicy } from '../../hooks/useAdapterCloudApi';\nimport { policyKindLabels, policyEnforcementLabels } from '../../utils/domain';\nimport { formatDate, formatRelativeTime } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\n\nexport function PolicyDetailPage() {\n const { id } = useParams<{ id: string }>();\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 query = usePolicy(id);\n const archive = useArchivePolicy();\n const policy = query.data;\n\n const handleArchive = useCallback(() => {\n if (!id) return;\n archive.mutate(id, { onSuccess: () => navigateTo('/policies') });\n }, [archive, id, navigateTo]);\n\n return (\n <PageLayout\n title={policy?.name ?? t('adaptercloud.policies.detailTitle', 'Policy')}\n description={policy ? policyKindLabels[policy.kind] : undefined}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/policies')}\n 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\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n {t('adaptercloud.common.back', 'Back')}\n </button>\n {policy && (\n <button\n type=\"button\"\n onClick={handleArchive}\n disabled={archive.isPending}\n 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-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50\"\n >\n <Archive className=\"h-4 w-4\" />\n {t('adaptercloud.common.archive', 'Archive')}\n </button>\n )}\n </div>\n }\n >\n <DataState\n isLoading={query.isLoading}\n isError={query.isError}\n isEmpty={!query.isLoading && !policy}\n error={query.error}\n onRetry={() => void query.refetch()}\n emptyTitle={t('adaptercloud.policies.notFound', 'Policy not found')}\n >\n {policy && (\n <div className=\"space-y-6\">\n <GlassCard className=\"p-6\">\n <div className=\"mb-4 flex flex-wrap items-center gap-3\">\n <SeverityBadge severity={policy.severity} />\n <span className=\"inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\">\n {policyEnforcementLabels[policy.enforcement]}\n </span>\n <span\n className={cn(\n 'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium',\n policy.isActive\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-bg-sunken text-text-secondary'\n )}\n >\n {policy.isActive\n ? t('adaptercloud.policies.active', 'Active')\n : t('adaptercloud.policies.inactive', 'Inactive')}\n </span>\n </div>\n\n {policy.description && (\n <p className=\"mb-4 text-sm text-text-secondary\">{policy.description}</p>\n )}\n\n <dl className=\"grid grid-cols-2 gap-4 text-sm sm:grid-cols-3\">\n <div>\n <dt className=\"text-text-secondary\">{t('adaptercloud.policies.kind', 'Kind')}</dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {policyKindLabels[policy.kind]}\n </dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.common.created', 'Created')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDate(policy.createdAt)}\n </dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.common.updated', 'Updated')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {formatDate(policy.updatedAt)}\n </dd>\n </div>\n </dl>\n\n {policy.appliesTo.length > 0 && (\n <div className=\"mt-5\">\n <h3 className=\"mb-2 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.policies.appliesTo', 'Applies To')}\n </h3>\n <div className=\"flex flex-wrap gap-1.5\">\n {policy.appliesTo.map((sel) => (\n <span\n key={sel}\n className=\"inline-flex items-center rounded-full bg-accent-blue-subtle px-2.5 py-0.5 font-mono text-xs text-accent-blue\"\n >\n {sel}\n </span>\n ))}\n </div>\n </div>\n )}\n\n {policy.tags.length > 0 && (\n <div className=\"mt-4\">\n <h3 className=\"mb-2 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.common.tags', 'Tags')}\n </h3>\n <div className=\"flex flex-wrap gap-1.5\">\n {policy.tags.map((tag) => (\n <span\n key={tag}\n className=\"inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n </div>\n )}\n </GlassCard>\n\n {/* Expression */}\n <GlassCard className=\"p-6\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.policies.expression', 'Expression')}\n </h3>\n <pre className=\"overflow-auto rounded-lg bg-bg-sunken p-4 text-xs text-text-secondary\">\n {JSON.stringify(policy.expression, null, 2)}\n </pre>\n </GlassCard>\n\n {/* Violations */}\n <section>\n <div className=\"mb-3 flex items-center justify-between\">\n <h3 className=\"text-base font-semibold text-text-primary\">\n {t('adaptercloud.policies.violations', 'Violations')}\n </h3>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/violations?policyId=${policy.id}`)}\n className=\"text-sm font-medium text-primary hover:underline\"\n >\n {t('adaptercloud.common.viewAll', 'View all')}\n </button>\n </div>\n {policy.violations && policy.violations.length > 0 ? (\n <div className=\"divide-y divide-border rounded-xl border border-border-subtle bg-bg-surface\">\n {policy.violations.slice(0, 10).map((v) => (\n <button\n key={v.id}\n type=\"button\"\n onClick={() => navigateTo(`/violations?policyId=${policy.id}`)}\n className=\"flex w-full items-start gap-3 px-4 py-3 text-left transition-colors hover:bg-accent/50\"\n >\n <AlertCircle className=\"mt-0.5 h-4 w-4 shrink-0 text-status-error-text\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {v.message}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {formatRelativeTime(v.detectedAt)}\n </p>\n </div>\n <StatusBadge status={v.status} />\n </button>\n ))}\n </div>\n ) : (\n <p className=\"rounded-xl border border-border-subtle bg-bg-surface px-4 py-6 text-center text-sm text-text-secondary\">\n {t('adaptercloud.policies.noViolations', 'No violations recorded for this policy.')}\n </p>\n )}\n </section>\n </div>\n )}\n </DataState>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,215 @@
1
+ import { useAdapterCloud as e } from "../../context/AdapterCloudContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { policyEnforcementLabels as n, policyKindLabels as r, severityLabels as i } from "../../utils/domain.js";
4
+ import { useCreatePolicy as a } from "../../hooks/useAdapterCloudApi.js";
5
+ import { useCallback as o, useState as s } from "react";
6
+ import { useI18n as c } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
7
+ import { ArrowLeft as l, Loader2 as u, Save as d } from "lucide-react";
8
+ import { jsx as f, jsxs as p } from "react/jsx-runtime";
9
+ import { GlassCard as m } from "@burdenoff/fe-libs/ui";
10
+ //#region src/adaptercloud/pages/policies/PolicyFormPage.tsx
11
+ var h = (e) => e.split(",").map((e) => e.trim()).filter(Boolean), g = "{\n \"match\": { \"resourceType\": \"*\" },\n \"require\": { \"tags\": [\"owner\", \"env\"] }\n}";
12
+ function _() {
13
+ let { navigateTo: _ } = e(), { t: v } = c(), y = o((e, t) => {
14
+ let n = v(e);
15
+ return n === e ? t : n;
16
+ }, [v]), b = a(), [x, S] = s(""), [C, w] = s(""), [T, E] = s("GUARDRAIL"), [D, O] = s("WARN"), [k, A] = s("MEDIUM"), [j, M] = s(""), [N, P] = s(""), [F, I] = s(!0), [L, R] = s(g), [z, B] = s(null), V = o((e) => {
17
+ if (e.preventDefault(), B(null), !x.trim()) {
18
+ B(y("adaptercloud.policies.form.nameRequired", "Name is required."));
19
+ return;
20
+ }
21
+ let t;
22
+ try {
23
+ t = JSON.parse(L);
24
+ } catch {
25
+ B(y("adaptercloud.policies.form.invalidExpression", "Expression must be valid JSON."));
26
+ return;
27
+ }
28
+ b.mutate({
29
+ name: x.trim(),
30
+ description: C.trim() || void 0,
31
+ kind: T,
32
+ enforcement: D,
33
+ severity: k,
34
+ isActive: F,
35
+ appliesTo: h(j),
36
+ tags: h(N),
37
+ expression: t
38
+ }, {
39
+ onSuccess: (e) => _(`/policies/${e.id}`),
40
+ onError: (e) => B(e instanceof Error ? e.message : "Failed to create policy.")
41
+ });
42
+ }, [
43
+ b,
44
+ x,
45
+ C,
46
+ T,
47
+ D,
48
+ k,
49
+ F,
50
+ j,
51
+ N,
52
+ L,
53
+ _,
54
+ y
55
+ ]), H = "w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]", U = "mb-1.5 block text-sm font-medium text-text-primary";
56
+ return /* @__PURE__ */ f(t, {
57
+ title: y("adaptercloud.policies.newTitle", "New Policy"),
58
+ description: y("adaptercloud.policies.formSubtitle", "Put a governance rule into the system instead of a wiki."),
59
+ actions: /* @__PURE__ */ p("button", {
60
+ type: "button",
61
+ onClick: () => _("/policies"),
62
+ 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",
63
+ children: [/* @__PURE__ */ f(l, { className: "h-4 w-4" }), y("adaptercloud.common.cancel", "Cancel")]
64
+ }),
65
+ children: /* @__PURE__ */ f("form", {
66
+ onSubmit: V,
67
+ className: "max-w-2xl",
68
+ children: /* @__PURE__ */ p(m, {
69
+ className: "space-y-5 p-6",
70
+ children: [
71
+ /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ p("label", {
72
+ htmlFor: "ada-pol-name",
73
+ className: U,
74
+ children: [y("adaptercloud.policies.form.name", "Name"), " *"]
75
+ }), /* @__PURE__ */ f("input", {
76
+ id: "ada-pol-name",
77
+ type: "text",
78
+ value: x,
79
+ onChange: (e) => S(e.target.value),
80
+ className: H,
81
+ placeholder: "Require owner + env tags"
82
+ })] }),
83
+ /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
84
+ htmlFor: "ada-pol-desc",
85
+ className: U,
86
+ children: y("adaptercloud.policies.form.description", "Description")
87
+ }), /* @__PURE__ */ f("textarea", {
88
+ id: "ada-pol-desc",
89
+ value: C,
90
+ onChange: (e) => w(e.target.value),
91
+ rows: 2,
92
+ className: H,
93
+ placeholder: y("adaptercloud.policies.form.descriptionPlaceholder", "What this policy enforces and why.")
94
+ })] }),
95
+ /* @__PURE__ */ p("div", {
96
+ className: "grid grid-cols-1 gap-5 sm:grid-cols-3",
97
+ children: [
98
+ /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
99
+ htmlFor: "ada-pol-kind",
100
+ className: U,
101
+ children: y("adaptercloud.policies.form.kind", "Kind")
102
+ }), /* @__PURE__ */ f("select", {
103
+ id: "ada-pol-kind",
104
+ value: T,
105
+ onChange: (e) => E(e.target.value),
106
+ className: H,
107
+ children: Object.keys(r).map((e) => /* @__PURE__ */ f("option", {
108
+ value: e,
109
+ children: r[e]
110
+ }, e))
111
+ })] }),
112
+ /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
113
+ htmlFor: "ada-pol-enf",
114
+ className: U,
115
+ children: y("adaptercloud.policies.form.enforcement", "Enforcement")
116
+ }), /* @__PURE__ */ f("select", {
117
+ id: "ada-pol-enf",
118
+ value: D,
119
+ onChange: (e) => O(e.target.value),
120
+ className: H,
121
+ children: Object.keys(n).map((e) => /* @__PURE__ */ f("option", {
122
+ value: e,
123
+ children: n[e]
124
+ }, e))
125
+ })] }),
126
+ /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
127
+ htmlFor: "ada-pol-sev",
128
+ className: U,
129
+ children: y("adaptercloud.policies.form.severity", "Severity")
130
+ }), /* @__PURE__ */ f("select", {
131
+ id: "ada-pol-sev",
132
+ value: k,
133
+ onChange: (e) => A(e.target.value),
134
+ className: H,
135
+ children: Object.keys(i).map((e) => /* @__PURE__ */ f("option", {
136
+ value: e,
137
+ children: i[e]
138
+ }, e))
139
+ })] })
140
+ ]
141
+ }),
142
+ /* @__PURE__ */ p("div", { children: [
143
+ /* @__PURE__ */ f("label", {
144
+ htmlFor: "ada-pol-applies",
145
+ className: U,
146
+ children: y("adaptercloud.policies.form.appliesTo", "Applies To")
147
+ }),
148
+ /* @__PURE__ */ f("input", {
149
+ id: "ada-pol-applies",
150
+ type: "text",
151
+ value: j,
152
+ onChange: (e) => M(e.target.value),
153
+ className: H,
154
+ placeholder: "aws:ec2:instance, aws:s3:bucket"
155
+ }),
156
+ /* @__PURE__ */ f("p", {
157
+ className: "mt-1 text-xs text-text-secondary",
158
+ children: y("adaptercloud.common.commaSeparated", "Comma-separated.")
159
+ })
160
+ ] }),
161
+ /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ p("label", {
162
+ htmlFor: "ada-pol-expr",
163
+ className: U,
164
+ children: [y("adaptercloud.policies.form.expression", "Expression (JSON)"), " *"]
165
+ }), /* @__PURE__ */ f("textarea", {
166
+ id: "ada-pol-expr",
167
+ value: L,
168
+ onChange: (e) => R(e.target.value),
169
+ rows: 8,
170
+ spellCheck: !1,
171
+ className: `${H} font-mono`
172
+ })] }),
173
+ /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
174
+ htmlFor: "ada-pol-tags",
175
+ className: U,
176
+ children: y("adaptercloud.common.tags", "Tags")
177
+ }), /* @__PURE__ */ f("input", {
178
+ id: "ada-pol-tags",
179
+ type: "text",
180
+ value: N,
181
+ onChange: (e) => P(e.target.value),
182
+ className: H,
183
+ placeholder: "tagging, governance"
184
+ })] }),
185
+ /* @__PURE__ */ p("label", {
186
+ className: "flex items-center gap-2 text-sm text-text-primary",
187
+ children: [/* @__PURE__ */ f("input", {
188
+ type: "checkbox",
189
+ checked: F,
190
+ onChange: (e) => I(e.target.checked),
191
+ className: "h-4 w-4 rounded border-border-subtle"
192
+ }), y("adaptercloud.policies.form.activeImmediately", "Active immediately")]
193
+ }),
194
+ z && /* @__PURE__ */ f("p", {
195
+ className: "rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
196
+ children: z
197
+ }),
198
+ /* @__PURE__ */ f("div", {
199
+ className: "flex justify-end gap-3 pt-2",
200
+ children: /* @__PURE__ */ p("button", {
201
+ type: "submit",
202
+ disabled: b.isPending,
203
+ className: "inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-5 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90 disabled:opacity-50",
204
+ children: [b.isPending ? /* @__PURE__ */ f(u, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ f(d, { className: "h-4 w-4" }), y("adaptercloud.policies.create", "Create policy")]
205
+ })
206
+ })
207
+ ]
208
+ })
209
+ })
210
+ });
211
+ }
212
+ //#endregion
213
+ export { _ as PolicyFormPage };
214
+
215
+ //# sourceMappingURL=PolicyFormPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PolicyFormPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/policies/PolicyFormPage.tsx"],"sourcesContent":["/**\n * Policy Create Form Page\n * @module adaptercloud/pages/policies\n *\n * Authors a new governance policy (`adaCreatePolicy`). The expression is a JSON\n * document validated client-side before submit.\n */\n\nimport { useCallback, useState } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { ArrowLeft, Loader2, Save } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { useCreatePolicy } from '../../hooks/useAdapterCloudApi';\nimport {\n policyKindLabels,\n policyEnforcementLabels,\n severityLabels,\n} from '../../utils/domain';\nimport type { AdaPolicyEnforcement, AdaPolicyKind, AdaSeverity } from '../../types';\n\nconst parseList = (value: string): string[] =>\n value\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n\nconst DEFAULT_EXPRESSION = `{\n \"match\": { \"resourceType\": \"*\" },\n \"require\": { \"tags\": [\"owner\", \"env\"] }\n}`;\n\nexport function PolicyFormPage() {\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 create = useCreatePolicy();\n\n const [name, setName] = useState('');\n const [description, setDescription] = useState('');\n const [kind, setKind] = useState<AdaPolicyKind>('GUARDRAIL');\n const [enforcement, setEnforcement] = useState<AdaPolicyEnforcement>('WARN');\n const [severity, setSeverity] = useState<AdaSeverity>('MEDIUM');\n const [appliesTo, setAppliesTo] = useState('');\n const [tags, setTags] = useState('');\n const [isActive, setIsActive] = useState(true);\n const [expression, setExpression] = useState(DEFAULT_EXPRESSION);\n const [error, setError] = useState<string | null>(null);\n\n const handleSubmit = useCallback(\n (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n\n if (!name.trim()) {\n setError(t('adaptercloud.policies.form.nameRequired', 'Name is required.'));\n return;\n }\n\n let parsedExpression: unknown;\n try {\n parsedExpression = JSON.parse(expression);\n } catch {\n setError(\n t('adaptercloud.policies.form.invalidExpression', 'Expression must be valid JSON.')\n );\n return;\n }\n\n create.mutate(\n {\n name: name.trim(),\n description: description.trim() || undefined,\n kind,\n enforcement,\n severity,\n isActive,\n appliesTo: parseList(appliesTo),\n tags: parseList(tags),\n expression: parsedExpression,\n },\n {\n onSuccess: (p) => navigateTo(`/policies/${p.id}`),\n onError: (err) =>\n setError(err instanceof Error ? err.message : 'Failed to create policy.'),\n }\n );\n },\n [\n create,\n name,\n description,\n kind,\n enforcement,\n severity,\n isActive,\n appliesTo,\n tags,\n expression,\n navigateTo,\n t,\n ]\n );\n\n const fieldClass =\n 'w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]';\n const labelClass = 'mb-1.5 block text-sm font-medium text-text-primary';\n\n return (\n <PageLayout\n title={t('adaptercloud.policies.newTitle', 'New Policy')}\n description={t(\n 'adaptercloud.policies.formSubtitle',\n 'Put a governance rule into the system instead of a wiki.'\n )}\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/policies')}\n 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\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n {t('adaptercloud.common.cancel', 'Cancel')}\n </button>\n }\n >\n <form onSubmit={handleSubmit} className=\"max-w-2xl\">\n <GlassCard className=\"space-y-5 p-6\">\n <div>\n <label htmlFor=\"ada-pol-name\" className={labelClass}>\n {t('adaptercloud.policies.form.name', 'Name')} *\n </label>\n <input\n id=\"ada-pol-name\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n className={fieldClass}\n placeholder=\"Require owner + env tags\"\n />\n </div>\n\n <div>\n <label htmlFor=\"ada-pol-desc\" className={labelClass}>\n {t('adaptercloud.policies.form.description', 'Description')}\n </label>\n <textarea\n id=\"ada-pol-desc\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n className={fieldClass}\n placeholder={t(\n 'adaptercloud.policies.form.descriptionPlaceholder',\n 'What this policy enforces and why.'\n )}\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-5 sm:grid-cols-3\">\n <div>\n <label htmlFor=\"ada-pol-kind\" className={labelClass}>\n {t('adaptercloud.policies.form.kind', 'Kind')}\n </label>\n <select\n id=\"ada-pol-kind\"\n value={kind}\n onChange={(e) => setKind(e.target.value as AdaPolicyKind)}\n className={fieldClass}\n >\n {(Object.keys(policyKindLabels) as AdaPolicyKind[]).map((k) => (\n <option key={k} value={k}>\n {policyKindLabels[k]}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"ada-pol-enf\" className={labelClass}>\n {t('adaptercloud.policies.form.enforcement', 'Enforcement')}\n </label>\n <select\n id=\"ada-pol-enf\"\n value={enforcement}\n onChange={(e) => setEnforcement(e.target.value as AdaPolicyEnforcement)}\n className={fieldClass}\n >\n {(Object.keys(policyEnforcementLabels) as AdaPolicyEnforcement[]).map((en) => (\n <option key={en} value={en}>\n {policyEnforcementLabels[en]}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"ada-pol-sev\" className={labelClass}>\n {t('adaptercloud.policies.form.severity', 'Severity')}\n </label>\n <select\n id=\"ada-pol-sev\"\n value={severity}\n onChange={(e) => setSeverity(e.target.value as AdaSeverity)}\n className={fieldClass}\n >\n {(Object.keys(severityLabels) as AdaSeverity[]).map((s) => (\n <option key={s} value={s}>\n {severityLabels[s]}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n <div>\n <label htmlFor=\"ada-pol-applies\" className={labelClass}>\n {t('adaptercloud.policies.form.appliesTo', 'Applies To')}\n </label>\n <input\n id=\"ada-pol-applies\"\n type=\"text\"\n value={appliesTo}\n onChange={(e) => setAppliesTo(e.target.value)}\n className={fieldClass}\n placeholder=\"aws:ec2:instance, aws:s3:bucket\"\n />\n <p className=\"mt-1 text-xs text-text-secondary\">\n {t('adaptercloud.common.commaSeparated', 'Comma-separated.')}\n </p>\n </div>\n\n <div>\n <label htmlFor=\"ada-pol-expr\" className={labelClass}>\n {t('adaptercloud.policies.form.expression', 'Expression (JSON)')} *\n </label>\n <textarea\n id=\"ada-pol-expr\"\n value={expression}\n onChange={(e) => setExpression(e.target.value)}\n rows={8}\n spellCheck={false}\n className={`${fieldClass} font-mono`}\n />\n </div>\n\n <div>\n <label htmlFor=\"ada-pol-tags\" className={labelClass}>\n {t('adaptercloud.common.tags', 'Tags')}\n </label>\n <input\n id=\"ada-pol-tags\"\n type=\"text\"\n value={tags}\n onChange={(e) => setTags(e.target.value)}\n className={fieldClass}\n placeholder=\"tagging, governance\"\n />\n </div>\n\n <label className=\"flex items-center gap-2 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={isActive}\n onChange={(e) => setIsActive(e.target.checked)}\n className=\"h-4 w-4 rounded border-border-subtle\"\n />\n {t('adaptercloud.policies.form.activeImmediately', 'Active immediately')}\n </label>\n\n {error && (\n <p className=\"rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\">\n {error}\n </p>\n )}\n\n <div className=\"flex justify-end gap-3 pt-2\">\n <button\n type=\"submit\"\n disabled={create.isPending}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-5 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90 disabled:opacity-50\"\n >\n {create.isPending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Save className=\"h-4 w-4\" />\n )}\n {t('adaptercloud.policies.create', 'Create policy')}\n </button>\n </div>\n </GlassCard>\n </form>\n </PageLayout>\n );\n}\n"],"mappings":"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"}