@burdenoff/microfe-adaptercloud 2026.825.4 → 2026.827.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 (48) hide show
  1. package/dist/adaptercloud/components/ActiveSwitch.d.ts +17 -0
  2. package/dist/adaptercloud/components/ActiveSwitch.d.ts.map +1 -0
  3. package/dist/adaptercloud/components/ActiveSwitch.js +28 -0
  4. package/dist/adaptercloud/components/ActiveSwitch.js.map +1 -0
  5. package/dist/adaptercloud/components/index.d.ts +1 -0
  6. package/dist/adaptercloud/components/index.d.ts.map +1 -1
  7. package/dist/adaptercloud/hooks/useAdapterCloudApi.d.ts +28 -2
  8. package/dist/adaptercloud/hooks/useAdapterCloudApi.d.ts.map +1 -1
  9. package/dist/adaptercloud/hooks/useAdapterCloudApi.js +43 -18
  10. package/dist/adaptercloud/hooks/useAdapterCloudApi.js.map +1 -1
  11. package/dist/adaptercloud/pages/OverviewPage.d.ts.map +1 -1
  12. package/dist/adaptercloud/pages/OverviewPage.js +4 -4
  13. package/dist/adaptercloud/pages/OverviewPage.js.map +1 -1
  14. package/dist/adaptercloud/pages/adapters/AdaptersListPage.d.ts.map +1 -1
  15. package/dist/adaptercloud/pages/adapters/AdaptersListPage.js +6 -5
  16. package/dist/adaptercloud/pages/adapters/AdaptersListPage.js.map +1 -1
  17. package/dist/adaptercloud/pages/connections/ConnectionDetailPage.d.ts.map +1 -1
  18. package/dist/adaptercloud/pages/connections/ConnectionDetailPage.js +217 -104
  19. package/dist/adaptercloud/pages/connections/ConnectionDetailPage.js.map +1 -1
  20. package/dist/adaptercloud/pages/connections/ConnectionsListPage.d.ts.map +1 -1
  21. package/dist/adaptercloud/pages/connections/ConnectionsListPage.js +6 -5
  22. package/dist/adaptercloud/pages/connections/ConnectionsListPage.js.map +1 -1
  23. package/dist/adaptercloud/pages/costs/CostsPage.d.ts.map +1 -1
  24. package/dist/adaptercloud/pages/costs/CostsPage.js +183 -156
  25. package/dist/adaptercloud/pages/costs/CostsPage.js.map +1 -1
  26. package/dist/adaptercloud/pages/drift/DriftListPage.d.ts.map +1 -1
  27. package/dist/adaptercloud/pages/drift/DriftListPage.js +108 -107
  28. package/dist/adaptercloud/pages/drift/DriftListPage.js.map +1 -1
  29. package/dist/adaptercloud/pages/policies/PoliciesListPage.d.ts.map +1 -1
  30. package/dist/adaptercloud/pages/policies/PoliciesListPage.js +141 -131
  31. package/dist/adaptercloud/pages/policies/PoliciesListPage.js.map +1 -1
  32. package/dist/adaptercloud/pages/policies/PolicyDetailPage.d.ts.map +1 -1
  33. package/dist/adaptercloud/pages/policies/PolicyDetailPage.js +171 -117
  34. package/dist/adaptercloud/pages/policies/PolicyDetailPage.js.map +1 -1
  35. package/dist/adaptercloud/pages/resources/ResourcesListPage.d.ts.map +1 -1
  36. package/dist/adaptercloud/pages/resources/ResourcesListPage.js +85 -66
  37. package/dist/adaptercloud/pages/resources/ResourcesListPage.js.map +1 -1
  38. package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.d.ts.map +1 -1
  39. package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.js +148 -121
  40. package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.js.map +1 -1
  41. package/dist/adaptercloud/pages/violations/ViolationsListPage.d.ts.map +1 -1
  42. package/dist/adaptercloud/pages/violations/ViolationsListPage.js +145 -144
  43. package/dist/adaptercloud/pages/violations/ViolationsListPage.js.map +1 -1
  44. package/dist/utils/pageContext.d.ts +0 -2
  45. package/dist/utils/pageContext.d.ts.map +1 -1
  46. package/dist/utils/pageContext.js +1 -3
  47. package/dist/utils/pageContext.js.map +1 -1
  48. package/package.json +1 -1
@@ -1,134 +1,160 @@
1
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 { ConfirmDialog as f } from "../../components/ConfirmDialog.js";
11
- import { useCallback as p, useState as m } from "react";
12
- import { useI18n as h } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
13
- import { AlertCircle as g, Archive as _, ArrowLeft as v, Pencil as y } from "lucide-react";
14
- import { useParams as b } from "react-router";
15
- import { Fragment as x, jsx as S, jsxs as C } from "react/jsx-runtime";
16
- import { GlassCard as w } from "@burdenoff/fe-libs/ui";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { policyEnforcementLabels as n, policyKindLabels as r } from "../../utils/domain.js";
4
+ import { StatusBadge as i } from "../../components/StatusBadge.js";
5
+ import { SeverityBadge as a } from "../../components/SeverityBadge.js";
6
+ import { DataState as o } from "../../components/DataState.js";
7
+ import { useArchivePolicy as s, usePolicy as c, useUpdatePolicy as l, useViolations as u } from "../../hooks/useAdapterCloudApi.js";
8
+ import { formatDate as d, formatRelativeTime as f } from "../../utils/formatters.js";
9
+ import { ConfirmDialog as p } from "../../components/ConfirmDialog.js";
10
+ import { ActiveSwitch as m } from "../../components/ActiveSwitch.js";
11
+ import { useCallback as h, useState as g } from "react";
12
+ import { useI18n as _ } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
13
+ import { AlertCircle as v, Archive as y, ArrowLeft as b, Pencil as x } from "lucide-react";
14
+ import { useParams as S } from "react-router";
15
+ import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
16
+ import { GlassCard as E } from "@burdenoff/fe-libs/ui";
17
17
  //#region src/adaptercloud/pages/policies/PolicyDetailPage.tsx
18
- function T() {
19
- let { id: T } = b(), { navigateTo: E } = e(), { t: D } = h(), O = p((e, t) => {
20
- let n = D(e);
18
+ function D() {
19
+ let { id: D } = S(), { navigateTo: O } = e(), { t: k } = _(), A = h((e, t) => {
20
+ let n = k(e);
21
21
  return n === e ? t : n;
22
- }, [D]), k = l(T), A = c(), j = k.data, [M, N] = m(!1), P = p(() => {
23
- T && A.mutate(T, { onSuccess: () => {
24
- N(!1), E("/policies");
22
+ }, [k]), j = c(D), M = s(), N = l(), P = j.data, [F, I] = g(!1), [L, R] = g(null), z = L ?? P?.isActive ?? !1, B = h(() => {
23
+ if (!P) return;
24
+ let e = !z;
25
+ R(e), N.mutate({
26
+ id: P.id,
27
+ input: { isActive: e }
28
+ }, { onSettled: () => R(null) });
29
+ }, [
30
+ P,
31
+ z,
32
+ N
33
+ ]), V = {
34
+ policyId: D,
35
+ pagination: {
36
+ limit: 1,
37
+ offset: 0
38
+ }
39
+ }, H = { enabled: !!D }, U = u({
40
+ ...V,
41
+ status: "OPEN"
42
+ }, H), W = u({
43
+ ...V,
44
+ status: "ACKNOWLEDGED"
45
+ }, H), G = U.data?.pageInfo.totalCount, K = W.data?.pageInfo.totalCount, q = h(() => {
46
+ D && M.mutate(D, { onSuccess: () => {
47
+ I(!1), O("/policies");
25
48
  } });
26
49
  }, [
27
- A,
28
- T,
29
- E
50
+ M,
51
+ D,
52
+ O
30
53
  ]);
31
- return /* @__PURE__ */ C(n, {
32
- title: j?.name ?? O("adaptercloud.policies.detailTitle", "Policy"),
33
- description: j ? i[j.kind] : void 0,
34
- actions: /* @__PURE__ */ C("div", {
54
+ return /* @__PURE__ */ T(t, {
55
+ title: P?.name ?? A("adaptercloud.policies.detailTitle", "Policy"),
56
+ description: P ? r[P.kind] : void 0,
57
+ actions: /* @__PURE__ */ T("div", {
35
58
  className: "flex items-center gap-2",
36
- children: [/* @__PURE__ */ C("button", {
59
+ children: [/* @__PURE__ */ T("button", {
37
60
  type: "button",
38
- onClick: () => E("/policies"),
61
+ onClick: () => O("/policies"),
39
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",
40
- children: [/* @__PURE__ */ S(v, { className: "h-4 w-4" }), O("adaptercloud.common.back", "Back")]
41
- }), j && /* @__PURE__ */ C(x, { children: [/* @__PURE__ */ C("button", {
63
+ children: [/* @__PURE__ */ w(b, { className: "h-4 w-4" }), A("adaptercloud.common.back", "Back")]
64
+ }), P && /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ T("button", {
42
65
  type: "button",
43
- onClick: () => E(`/policies/${j.id}/edit`),
66
+ onClick: () => O(`/policies/${P.id}/edit`),
44
67
  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",
45
- children: [/* @__PURE__ */ S(y, { className: "h-4 w-4" }), O("adaptercloud.common.edit", "Edit")]
46
- }), /* @__PURE__ */ C("button", {
68
+ children: [/* @__PURE__ */ w(x, { className: "h-4 w-4" }), A("adaptercloud.common.edit", "Edit")]
69
+ }), /* @__PURE__ */ T("button", {
47
70
  type: "button",
48
- onClick: () => N(!0),
49
- disabled: A.isPending,
71
+ onClick: () => I(!0),
72
+ disabled: M.isPending,
50
73
  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",
51
- children: [/* @__PURE__ */ S(_, { className: "h-4 w-4" }), O("adaptercloud.common.archive", "Archive")]
74
+ children: [/* @__PURE__ */ w(y, { className: "h-4 w-4" }), A("adaptercloud.common.archive", "Archive")]
52
75
  })] })]
53
76
  }),
54
- children: [/* @__PURE__ */ S(s, {
55
- isLoading: k.isLoading,
56
- isError: k.isError,
57
- isEmpty: !k.isLoading && !j,
58
- error: k.error,
59
- onRetry: () => void k.refetch(),
60
- emptyTitle: O("adaptercloud.policies.notFound", "Policy not found"),
61
- children: j && /* @__PURE__ */ C("div", {
77
+ children: [/* @__PURE__ */ w(o, {
78
+ isLoading: j.isLoading,
79
+ isError: j.isError,
80
+ isEmpty: !j.isLoading && !P,
81
+ error: j.error,
82
+ onRetry: () => void j.refetch(),
83
+ emptyTitle: A("adaptercloud.policies.notFound", "Policy not found"),
84
+ children: P && /* @__PURE__ */ T("div", {
62
85
  className: "space-y-6",
63
86
  children: [
64
- /* @__PURE__ */ C(w, {
87
+ /* @__PURE__ */ T(E, {
65
88
  className: "p-6",
66
89
  children: [
67
- /* @__PURE__ */ C("div", {
90
+ /* @__PURE__ */ T("div", {
68
91
  className: "mb-4 flex flex-wrap items-center gap-3",
69
92
  children: [
70
- /* @__PURE__ */ S(o, { severity: j.severity }),
71
- /* @__PURE__ */ S("span", {
93
+ /* @__PURE__ */ w(a, { severity: P.severity }),
94
+ /* @__PURE__ */ w("span", {
72
95
  className: "inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
73
- children: r[j.enforcement]
96
+ children: n[P.enforcement]
74
97
  }),
75
- /* @__PURE__ */ S("span", {
76
- className: t("inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium", j.isActive ? "bg-status-success-bg-subtle text-status-success-text" : "bg-bg-sunken text-text-secondary"),
77
- children: j.isActive ? O("adaptercloud.policies.active", "Active") : O("adaptercloud.policies.inactive", "Inactive")
98
+ /* @__PURE__ */ w(m, {
99
+ checked: z,
100
+ disabled: N.isPending,
101
+ onToggle: B,
102
+ label: z ? A("adaptercloud.policies.deactivate", "Deactivate policy") : A("adaptercloud.policies.activate", "Activate policy"),
103
+ children: z ? A("adaptercloud.policies.active", "Active") : A("adaptercloud.policies.inactive", "Inactive")
78
104
  })
79
105
  ]
80
106
  }),
81
- j.description && /* @__PURE__ */ S("p", {
107
+ P.description && /* @__PURE__ */ w("p", {
82
108
  className: "mb-4 text-sm text-text-secondary",
83
- children: j.description
109
+ children: P.description
84
110
  }),
85
- /* @__PURE__ */ C("dl", {
111
+ /* @__PURE__ */ T("dl", {
86
112
  className: "grid grid-cols-2 gap-4 text-sm sm:grid-cols-3",
87
113
  children: [
88
- /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ S("dt", {
114
+ /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
89
115
  className: "text-text-secondary",
90
- children: O("adaptercloud.policies.kind", "Kind")
91
- }), /* @__PURE__ */ S("dd", {
116
+ children: A("adaptercloud.policies.kind", "Kind")
117
+ }), /* @__PURE__ */ w("dd", {
92
118
  className: "mt-0.5 font-medium text-text-primary",
93
- children: i[j.kind]
119
+ children: r[P.kind]
94
120
  })] }),
95
- /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ S("dt", {
121
+ /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
96
122
  className: "text-text-secondary",
97
- children: O("adaptercloud.common.created", "Created")
98
- }), /* @__PURE__ */ S("dd", {
123
+ children: A("adaptercloud.common.created", "Created")
124
+ }), /* @__PURE__ */ w("dd", {
99
125
  className: "mt-0.5 font-medium text-text-primary",
100
- children: u(j.createdAt)
126
+ children: d(P.createdAt)
101
127
  })] }),
102
- /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ S("dt", {
128
+ /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("dt", {
103
129
  className: "text-text-secondary",
104
- children: O("adaptercloud.common.updated", "Updated")
105
- }), /* @__PURE__ */ S("dd", {
130
+ children: A("adaptercloud.common.updated", "Updated")
131
+ }), /* @__PURE__ */ w("dd", {
106
132
  className: "mt-0.5 font-medium text-text-primary",
107
- children: u(j.updatedAt)
133
+ children: d(P.updatedAt)
108
134
  })] })
109
135
  ]
110
136
  }),
111
- j.appliesTo.length > 0 && /* @__PURE__ */ C("div", {
137
+ P.appliesTo.length > 0 && /* @__PURE__ */ T("div", {
112
138
  className: "mt-5",
113
- children: [/* @__PURE__ */ S("h3", {
139
+ children: [/* @__PURE__ */ w("h3", {
114
140
  className: "mb-2 text-sm font-semibold text-text-primary",
115
- children: O("adaptercloud.policies.appliesTo", "Applies To")
116
- }), /* @__PURE__ */ S("div", {
141
+ children: A("adaptercloud.policies.appliesTo", "Applies To")
142
+ }), /* @__PURE__ */ w("div", {
117
143
  className: "flex flex-wrap gap-1.5",
118
- children: j.appliesTo.map((e) => /* @__PURE__ */ S("span", {
144
+ children: P.appliesTo.map((e) => /* @__PURE__ */ w("span", {
119
145
  className: "inline-flex items-center rounded-full bg-accent-blue-subtle px-2.5 py-0.5 font-mono text-xs text-accent-blue",
120
146
  children: e
121
147
  }, e))
122
148
  })]
123
149
  }),
124
- j.tags.length > 0 && /* @__PURE__ */ C("div", {
150
+ P.tags.length > 0 && /* @__PURE__ */ T("div", {
125
151
  className: "mt-4",
126
- children: [/* @__PURE__ */ S("h3", {
152
+ children: [/* @__PURE__ */ w("h3", {
127
153
  className: "mb-2 text-sm font-semibold text-text-primary",
128
- children: O("adaptercloud.common.tags", "Tags")
129
- }), /* @__PURE__ */ S("div", {
154
+ children: A("adaptercloud.common.tags", "Tags")
155
+ }), /* @__PURE__ */ w("div", {
130
156
  className: "flex flex-wrap gap-1.5",
131
- children: j.tags.map((e) => /* @__PURE__ */ S("span", {
157
+ children: P.tags.map((e) => /* @__PURE__ */ w("span", {
132
158
  className: "inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary",
133
159
  children: e
134
160
  }, e))
@@ -136,81 +162,109 @@ function T() {
136
162
  })
137
163
  ]
138
164
  }),
139
- /* @__PURE__ */ C(w, {
165
+ /* @__PURE__ */ T(E, {
140
166
  className: "p-6",
141
- children: [/* @__PURE__ */ S("h3", {
167
+ children: [/* @__PURE__ */ w("h3", {
142
168
  className: "mb-3 text-sm font-semibold text-text-primary",
143
- children: O("adaptercloud.policies.expression", "Expression")
144
- }), /* @__PURE__ */ S("pre", {
169
+ children: A("adaptercloud.policies.expression", "Expression")
170
+ }), /* @__PURE__ */ w("pre", {
145
171
  className: "overflow-auto rounded-lg bg-bg-sunken p-4 text-xs text-text-secondary",
146
- children: JSON.stringify(j.expression, null, 2)
172
+ children: JSON.stringify(P.expression, null, 2)
147
173
  })]
148
174
  }),
149
- /* @__PURE__ */ C("section", { children: [/* @__PURE__ */ C("div", {
150
- className: "mb-3 flex items-center justify-between",
151
- children: [/* @__PURE__ */ S("h3", {
152
- className: "text-base font-semibold text-text-primary",
153
- children: O("adaptercloud.policies.violations", "Violations")
154
- }), /* @__PURE__ */ S("button", {
175
+ /* @__PURE__ */ T("section", { children: [/* @__PURE__ */ T("div", {
176
+ className: "mb-3 flex flex-wrap items-center justify-between gap-3",
177
+ children: [/* @__PURE__ */ T("div", {
178
+ className: "flex flex-wrap items-baseline gap-3",
179
+ children: [/* @__PURE__ */ w("h3", {
180
+ className: "text-base font-semibold text-text-primary",
181
+ children: A("adaptercloud.policies.violations", "Violations")
182
+ }), (G != null || K != null) && /* @__PURE__ */ T("p", {
183
+ className: "flex items-center gap-2 text-xs",
184
+ children: [
185
+ G != null && /* @__PURE__ */ T("span", {
186
+ className: "font-medium text-status-error-text",
187
+ children: [
188
+ G,
189
+ " ",
190
+ A("adaptercloud.policies.openCount", "open")
191
+ ]
192
+ }),
193
+ G != null && K != null && /* @__PURE__ */ w("span", {
194
+ "aria-hidden": "true",
195
+ className: "text-text-tertiary",
196
+ children: "·"
197
+ }),
198
+ K != null && /* @__PURE__ */ T("span", {
199
+ className: "font-medium text-status-warning-text",
200
+ children: [
201
+ K,
202
+ " ",
203
+ A("adaptercloud.policies.acknowledgedCount", "acknowledged")
204
+ ]
205
+ })
206
+ ]
207
+ })]
208
+ }), /* @__PURE__ */ w("button", {
155
209
  type: "button",
156
- onClick: () => E(`/violations?policyId=${j.id}`),
210
+ onClick: () => O(`/violations?policyId=${P.id}`),
157
211
  className: "text-sm font-medium text-accent-blue hover:underline",
158
- children: O("adaptercloud.common.viewAll", "View all")
212
+ children: A("adaptercloud.common.viewAll", "View all")
159
213
  })]
160
- }), j.violations && j.violations.length > 0 ? /* @__PURE__ */ S("div", {
214
+ }), P.violations && P.violations.length > 0 ? /* @__PURE__ */ w("div", {
161
215
  className: "divide-y divide-border rounded-xl border border-border-subtle bg-bg-surface",
162
- children: j.violations.slice(0, 10).map((e) => /* @__PURE__ */ C("div", {
216
+ children: P.violations.slice(0, 10).map((e) => /* @__PURE__ */ T("div", {
163
217
  className: "flex w-full items-start gap-3 px-4 py-3 transition-colors hover:bg-accent/50",
164
218
  children: [
165
- /* @__PURE__ */ S(g, { className: "mt-0.5 h-4 w-4 shrink-0 text-status-error-text" }),
166
- /* @__PURE__ */ C("div", {
219
+ /* @__PURE__ */ w(v, { className: "mt-0.5 h-4 w-4 shrink-0 text-status-error-text" }),
220
+ /* @__PURE__ */ T("div", {
167
221
  className: "min-w-0 flex-1",
168
- children: [/* @__PURE__ */ S("p", {
222
+ children: [/* @__PURE__ */ w("p", {
169
223
  className: "truncate text-sm font-medium text-text-primary",
170
224
  children: e.message
171
- }), /* @__PURE__ */ C("p", {
225
+ }), /* @__PURE__ */ T("p", {
172
226
  className: "mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-text-secondary",
173
227
  children: [
174
- /* @__PURE__ */ S("span", { children: d(e.detectedAt) }),
175
- /* @__PURE__ */ S("span", {
228
+ /* @__PURE__ */ w("span", { children: f(e.detectedAt) }),
229
+ /* @__PURE__ */ w("span", {
176
230
  "aria-hidden": "true",
177
231
  children: "·"
178
232
  }),
179
- /* @__PURE__ */ S("button", {
233
+ /* @__PURE__ */ w("button", {
180
234
  type: "button",
181
- onClick: () => E(`/resources/${e.resourceId}`),
235
+ onClick: () => O(`/resources/${e.resourceId}`),
182
236
  className: "font-medium text-accent-blue hover:underline",
183
- children: O("adaptercloud.violations.viewResource", "View resource")
237
+ children: A("adaptercloud.violations.viewResource", "View resource")
184
238
  })
185
239
  ]
186
240
  })]
187
241
  }),
188
- /* @__PURE__ */ C("div", {
242
+ /* @__PURE__ */ T("div", {
189
243
  className: "flex shrink-0 items-center gap-2",
190
- children: [/* @__PURE__ */ S(o, { severity: e.severity }), /* @__PURE__ */ S(a, { status: e.status })]
244
+ children: [/* @__PURE__ */ w(a, { severity: e.severity }), /* @__PURE__ */ w(i, { status: e.status })]
191
245
  })
192
246
  ]
193
247
  }, e.id))
194
- }) : /* @__PURE__ */ S("p", {
248
+ }) : /* @__PURE__ */ w("p", {
195
249
  className: "rounded-xl border border-border-subtle bg-bg-surface px-4 py-6 text-center text-sm text-text-secondary",
196
- children: O("adaptercloud.policies.noViolations", "No violations recorded for this policy.")
250
+ children: A("adaptercloud.policies.noViolations", "No violations recorded for this policy.")
197
251
  })] })
198
252
  ]
199
253
  })
200
- }), /* @__PURE__ */ S(f, {
201
- open: M,
202
- onOpenChange: N,
203
- title: O("adaptercloud.policies.archiveTitle", "Archive this policy?"),
204
- description: O("adaptercloud.policies.archivePrompt", "The policy will be archived and removed from every governance view. This cannot be undone from the UI."),
205
- confirmLabel: O("adaptercloud.common.archive", "Archive"),
206
- cancelLabel: O("adaptercloud.common.cancel", "Cancel"),
207
- onConfirm: P,
208
- isPending: A.isPending,
254
+ }), /* @__PURE__ */ w(p, {
255
+ open: F,
256
+ onOpenChange: I,
257
+ title: A("adaptercloud.policies.archiveTitle", "Archive this policy?"),
258
+ description: A("adaptercloud.policies.archivePrompt", "The policy will be archived and removed from every governance view. This cannot be undone from the UI."),
259
+ confirmLabel: A("adaptercloud.common.archive", "Archive"),
260
+ cancelLabel: A("adaptercloud.common.cancel", "Cancel"),
261
+ onConfirm: q,
262
+ isPending: M.isPending,
209
263
  tone: "danger"
210
264
  })]
211
265
  });
212
266
  }
213
267
  //#endregion
214
- export { T as PolicyDetailPage };
268
+ export { D as PolicyDetailPage };
215
269
 
216
270
  //# sourceMappingURL=PolicyDetailPage.js.map
@@ -1 +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, useState } from 'react';\nimport { useParams } from 'react-router';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { ArrowLeft, Archive, AlertCircle, Pencil } 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 { ConfirmDialog } from '../../components/ConfirmDialog';\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 [confirmArchiveOpen, setConfirmArchiveOpen] = useState(false);\n\n const handleArchive = useCallback(() => {\n if (!id) return;\n archive.mutate(id, {\n onSuccess: () => {\n setConfirmArchiveOpen(false);\n navigateTo('/policies');\n },\n });\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 <>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/policies/${policy.id}/edit`)}\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 <Pencil className=\"h-4 w-4\" />\n {t('adaptercloud.common.edit', 'Edit')}\n </button>\n <button\n type=\"button\"\n onClick={() => setConfirmArchiveOpen(true)}\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 )}\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-accent-blue 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 <div\n key={v.id}\n className=\"flex w-full items-start gap-3 px-4 py-3 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 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-text-secondary\">\n <span>{formatRelativeTime(v.detectedAt)}</span>\n <span aria-hidden=\"true\">·</span>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/resources/${v.resourceId}`)}\n className=\"font-medium text-accent-blue hover:underline\"\n >\n {t('adaptercloud.violations.viewResource', 'View resource')}\n </button>\n </p>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <SeverityBadge severity={v.severity} />\n <StatusBadge status={v.status} />\n </div>\n </div>\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(\n 'adaptercloud.policies.noViolations',\n 'No violations recorded for this policy.'\n )}\n </p>\n )}\n </section>\n </div>\n )}\n </DataState>\n\n <ConfirmDialog\n open={confirmArchiveOpen}\n onOpenChange={setConfirmArchiveOpen}\n title={t('adaptercloud.policies.archiveTitle', 'Archive this policy?')}\n description={t(\n 'adaptercloud.policies.archivePrompt',\n 'The policy will be archived and removed from every governance view. This cannot be undone from the UI.'\n )}\n confirmLabel={t('adaptercloud.common.archive', 'Archive')}\n cancelLabel={t('adaptercloud.common.cancel', 'Cancel')}\n onConfirm={handleArchive}\n isPending={archive.isPending}\n tone=\"danger\"\n />\n </PageLayout>\n );\n}\n"],"mappings":"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"}
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, useState } from 'react';\nimport { useParams } from 'react-router';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { ArrowLeft, Archive, AlertCircle, Pencil } 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 { ConfirmDialog } from '../../components/ConfirmDialog';\nimport { ActiveSwitch } from '../../components/ActiveSwitch';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport {\n usePolicy,\n useArchivePolicy,\n useUpdatePolicy,\n useViolations,\n} from '../../hooks/useAdapterCloudApi';\nimport { policyKindLabels, policyEnforcementLabels } from '../../utils/domain';\nimport { formatDate, formatRelativeTime } from '../../utils/formatters';\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 update = useUpdatePolicy();\n const policy = query.data;\n\n const [confirmArchiveOpen, setConfirmArchiveOpen] = useState(false);\n // Optimistic override of `isActive` while the mutation is in flight, so the\n // switch flips immediately instead of waiting for the refetch.\n const [pendingActive, setPendingActive] = useState<boolean | null>(null);\n\n const isActiveNow = pendingActive ?? policy?.isActive ?? false;\n\n const toggleActive = useCallback(() => {\n if (!policy) return;\n const next = !isActiveNow;\n setPendingActive(next);\n update.mutate(\n { id: policy.id, input: { isActive: next } },\n { onSettled: () => setPendingActive(null) }\n );\n }, [policy, isActiveNow, update]);\n\n // Exact per-status counts for this policy's violations. Each is a `limit: 1`\n // read of `pageInfo.totalCount` — the estate-wide total for that filter, not\n // a count of the (relation-capped) `policy.violations` array.\n const countBase = { policyId: id, pagination: { limit: 1, offset: 0 } };\n const countsEnabled = { enabled: Boolean(id) };\n const openCount = useViolations({ ...countBase, status: 'OPEN' }, countsEnabled);\n const ackCount = useViolations({ ...countBase, status: 'ACKNOWLEDGED' }, countsEnabled);\n const openTotal = openCount.data?.pageInfo.totalCount;\n const ackTotal = ackCount.data?.pageInfo.totalCount;\n\n const handleArchive = useCallback(() => {\n if (!id) return;\n archive.mutate(id, {\n onSuccess: () => {\n setConfirmArchiveOpen(false);\n navigateTo('/policies');\n },\n });\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 <>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/policies/${policy.id}/edit`)}\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 <Pencil className=\"h-4 w-4\" />\n {t('adaptercloud.common.edit', 'Edit')}\n </button>\n <button\n type=\"button\"\n onClick={() => setConfirmArchiveOpen(true)}\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 )}\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 <ActiveSwitch\n checked={isActiveNow}\n disabled={update.isPending}\n onToggle={toggleActive}\n label={\n isActiveNow\n ? t('adaptercloud.policies.deactivate', 'Deactivate policy')\n : t('adaptercloud.policies.activate', 'Activate policy')\n }\n >\n {isActiveNow\n ? t('adaptercloud.policies.active', 'Active')\n : t('adaptercloud.policies.inactive', 'Inactive')}\n </ActiveSwitch>\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 flex-wrap items-center justify-between gap-3\">\n <div className=\"flex flex-wrap items-baseline gap-3\">\n <h3 className=\"text-base font-semibold text-text-primary\">\n {t('adaptercloud.policies.violations', 'Violations')}\n </h3>\n {(openTotal != null || ackTotal != null) && (\n <p className=\"flex items-center gap-2 text-xs\">\n {openTotal != null && (\n <span className=\"font-medium text-status-error-text\">\n {openTotal} {t('adaptercloud.policies.openCount', 'open')}\n </span>\n )}\n {openTotal != null && ackTotal != null && (\n <span aria-hidden=\"true\" className=\"text-text-tertiary\">\n ·\n </span>\n )}\n {ackTotal != null && (\n <span className=\"font-medium text-status-warning-text\">\n {ackTotal} {t('adaptercloud.policies.acknowledgedCount', 'acknowledged')}\n </span>\n )}\n </p>\n )}\n </div>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/violations?policyId=${policy.id}`)}\n className=\"text-sm font-medium text-accent-blue 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 <div\n key={v.id}\n className=\"flex w-full items-start gap-3 px-4 py-3 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 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-text-secondary\">\n <span>{formatRelativeTime(v.detectedAt)}</span>\n <span aria-hidden=\"true\">·</span>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/resources/${v.resourceId}`)}\n className=\"font-medium text-accent-blue hover:underline\"\n >\n {t('adaptercloud.violations.viewResource', 'View resource')}\n </button>\n </p>\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n <SeverityBadge severity={v.severity} />\n <StatusBadge status={v.status} />\n </div>\n </div>\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(\n 'adaptercloud.policies.noViolations',\n 'No violations recorded for this policy.'\n )}\n </p>\n )}\n </section>\n </div>\n )}\n </DataState>\n\n <ConfirmDialog\n open={confirmArchiveOpen}\n onOpenChange={setConfirmArchiveOpen}\n title={t('adaptercloud.policies.archiveTitle', 'Archive this policy?')}\n description={t(\n 'adaptercloud.policies.archivePrompt',\n 'The policy will be archived and removed from every governance view. This cannot be undone from the UI.'\n )}\n confirmLabel={t('adaptercloud.common.archive', 'Archive')}\n cancelLabel={t('adaptercloud.common.cancel', 'Cancel')}\n onConfirm={handleArchive}\n isPending={archive.isPending}\n tone=\"danger\"\n />\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA8BA,SAAgB,IAAmB;CACjC,IAAM,EAAE,UAAO,EAA0B,GACnC,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,IAAQ,EAAU,CAAE,GACpB,IAAU,EAAiB,GAC3B,IAAS,EAAgB,GACzB,IAAS,EAAM,MAEf,CAAC,GAAoB,KAAyB,EAAS,EAAK,GAG5D,CAAC,GAAe,KAAoB,EAAyB,IAAI,GAEjE,IAAc,KAAiB,GAAQ,YAAY,IAEnD,IAAe,QAAkB;EACrC,IAAI,CAAC,GAAQ;EACb,IAAM,IAAO,CAAC;EAEd,AADA,EAAiB,CAAI,GACrB,EAAO,OACL;GAAE,IAAI,EAAO;GAAI,OAAO,EAAE,UAAU,EAAK;EAAE,GAC3C,EAAE,iBAAiB,EAAiB,IAAI,EAAE,CAC5C;CACF,GAAG;EAAC;EAAQ;EAAa;CAAM,CAAC,GAK1B,IAAY;EAAE,UAAU;EAAI,YAAY;GAAE,OAAO;GAAG,QAAQ;EAAE;CAAE,GAChE,IAAgB,EAAE,SAAS,EAAQ,EAAI,GACvC,IAAY,EAAc;EAAE,GAAG;EAAW,QAAQ;CAAO,GAAG,CAAa,GACzE,IAAW,EAAc;EAAE,GAAG;EAAW,QAAQ;CAAe,GAAG,CAAa,GAChF,IAAY,EAAU,MAAM,SAAS,YACrC,IAAW,EAAS,MAAM,SAAS,YAEnC,IAAgB,QAAkB;EACjC,KACL,EAAQ,OAAO,GAAI,EACjB,iBAAiB;GAEf,AADA,EAAsB,EAAK,GAC3B,EAAW,WAAW;EACxB,EACF,CAAC;CACH,GAAG;EAAC;EAAS;EAAI;CAAU,CAAC;CAE5B,OACE,kBAAC,GAAD;EACE,OAAO,GAAQ,QAAQ,EAAE,qCAAqC,QAAQ;EACtE,aAAa,IAAS,EAAiB,EAAO,QAAQ,KAAA;EACtD,SACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAW,WAAW;IACrC,WAAU;cAHZ,CAKE,kBAAC,GAAD,EAAW,WAAU,UAAW,CAAA,GAC/B,EAAE,4BAA4B,MAAM,CAC/B;OACP,KACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAW,aAAa,EAAO,GAAG,MAAM;IACvD,WAAU;cAHZ,CAKE,kBAAC,GAAD,EAAQ,WAAU,UAAW,CAAA,GAC5B,EAAE,4BAA4B,MAAM,CAC/B;OACR,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAsB,EAAI;IACzC,UAAU,EAAQ;IAClB,WAAU;cAJZ,CAME,kBAAC,GAAD,EAAS,WAAU,UAAW,CAAA,GAC7B,EAAE,+BAA+B,SAAS,CACrC;KACR,EAAA,CAAA,CAED;;YAlCT,CAqCE,kBAAC,GAAD;GACE,WAAW,EAAM;GACjB,SAAS,EAAM;GACf,SAAS,CAAC,EAAM,aAAa,CAAC;GAC9B,OAAO,EAAM;GACb,eAAe,KAAK,EAAM,QAAQ;GAClC,YAAY,EAAE,kCAAkC,kBAAkB;aAEjE,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MAAW,WAAU;gBAArB;OACE,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,GAAD,EAAe,UAAU,EAAO,SAAW,CAAA;SAC3C,kBAAC,QAAD;UAAM,WAAU;oBACb,EAAwB,EAAO;SAC5B,CAAA;SACN,kBAAC,GAAD;UACE,SAAS;UACT,UAAU,EAAO;UACjB,UAAU;UACV,OACE,IACI,EAAE,oCAAoC,mBAAmB,IACzD,EAAE,kCAAkC,iBAAiB;oBAG1D,IACG,EAAE,gCAAgC,QAAQ,IAC1C,EAAE,kCAAkC,UAAU;SACtC,CAAA;QACX;;OAEJ,EAAO,eACN,kBAAC,KAAD;QAAG,WAAU;kBAAoC,EAAO;OAAe,CAAA;OAGzE,kBAAC,MAAD;QAAI,WAAU;kBAAd;SACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;UAAI,WAAU;oBAAuB,EAAE,8BAA8B,MAAM;SAAM,CAAA,GACjF,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAiB,EAAO;SACvB,CAAA,CACD,EAAA,CAAA;SACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAE,+BAA+B,SAAS;SACzC,CAAA,GACJ,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAW,EAAO,SAAS;SAC1B,CAAA,CACD,EAAA,CAAA;SACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAE,+BAA+B,SAAS;SACzC,CAAA,GACJ,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAW,EAAO,SAAS;SAC1B,CAAA,CACD,EAAA,CAAA;QACH;;OAEH,EAAO,UAAU,SAAS,KACzB,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,mCAAmC,YAAY;QAChD,CAAA,GACJ,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAO,UAAU,KAAK,MACrB,kBAAC,QAAD;UAEE,WAAU;oBAET;SACG,GAJC,CAID,CACP;QACE,CAAA,CACF;;OAGN,EAAO,KAAK,SAAS,KACpB,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,4BAA4B,MAAM;QACnC,CAAA,GACJ,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAO,KAAK,KAAK,MAChB,kBAAC,QAAD;UAEE,WAAU;oBAET;SACG,GAJC,CAID,CACP;QACE,CAAA,CACF;;MAEE;;KAGX,kBAAC,GAAD;MAAW,WAAU;gBAArB,CACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAE,oCAAoC,YAAY;MACjD,CAAA,GACJ,kBAAC,OAAD;OAAK,WAAU;iBACZ,KAAK,UAAU,EAAO,YAAY,MAAM,CAAC;MACvC,CAAA,CACI;;KAGX,kBAAC,WAAD,EAAA,UAAA,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAE,oCAAoC,YAAY;OACjD,CAAA,IACF,KAAa,QAAQ,KAAY,SACjC,kBAAC,KAAD;QAAG,WAAU;kBAAb;SACG,KAAa,QACZ,kBAAC,QAAD;UAAM,WAAU;oBAAhB;WACG;WAAU;WAAE,EAAE,mCAAmC,MAAM;UACpD;;SAEP,KAAa,QAAQ,KAAY,QAChC,kBAAC,QAAD;UAAM,eAAY;UAAO,WAAU;oBAAqB;SAElD,CAAA;SAEP,KAAY,QACX,kBAAC,QAAD;UAAM,WAAU;oBAAhB;WACG;WAAS;WAAE,EAAE,2CAA2C,cAAc;UACnE;;QAEP;SAEF;UACL,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,EAAW,wBAAwB,EAAO,IAAI;OAC7D,WAAU;iBAET,EAAE,+BAA+B,UAAU;MACtC,CAAA,CACL;SACJ,EAAO,cAAc,EAAO,WAAW,SAAS,IAC/C,kBAAC,OAAD;MAAK,WAAU;gBACZ,EAAO,WAAW,MAAM,GAAG,EAAE,EAAE,KAAK,MACnC,kBAAC,OAAD;OAEE,WAAU;iBAFZ;QAIE,kBAAC,GAAD,EAAa,WAAU,iDAAkD,CAAA;QACzE,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,KAAD;UAAG,WAAU;oBACV,EAAE;SACF,CAAA,GACH,kBAAC,KAAD;UAAG,WAAU;oBAAb;WACE,kBAAC,QAAD,EAAA,UAAO,EAAmB,EAAE,UAAU,EAAQ,CAAA;WAC9C,kBAAC,QAAD;YAAM,eAAY;sBAAO;WAAO,CAAA;WAChC,kBAAC,UAAD;YACE,MAAK;YACL,eAAe,EAAW,cAAc,EAAE,YAAY;YACtD,WAAU;sBAET,EAAE,wCAAwC,eAAe;WACpD,CAAA;UACP;WACA;;QACL,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD,EAAe,UAAU,EAAE,SAAW,CAAA,GACtC,kBAAC,GAAD,EAAa,QAAQ,EAAE,OAAS,CAAA,CAC7B;;OACF;SAxBE,EAAE,EAwBJ,CACN;KACE,CAAA,IAEL,kBAAC,KAAD;MAAG,WAAU;gBACV,EACC,sCACA,yCACF;KACC,CAAA,CAEE,EAAA,CAAA;IACN;;EAEE,CAAA,GAEX,kBAAC,GAAD;GACE,MAAM;GACN,cAAc;GACd,OAAO,EAAE,sCAAsC,sBAAsB;GACrE,aAAa,EACX,uCACA,wGACF;GACA,cAAc,EAAE,+BAA+B,SAAS;GACxD,aAAa,EAAE,8BAA8B,QAAQ;GACrD,WAAW;GACX,WAAW,EAAQ;GACnB,MAAK;EACN,CAAA,CACS;;AAEhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"ResourcesListPage.d.ts","sourceRoot":"","sources":["../../../../src/adaptercloud/pages/resources/ResourcesListPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkBH,wBAAgB,iBAAiB,gCAmPhC"}
1
+ {"version":3,"file":"ResourcesListPage.d.ts","sourceRoot":"","sources":["../../../../src/adaptercloud/pages/resources/ResourcesListPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAqBH,wBAAgB,iBAAiB,gCA8QhC"}