@burdenoff/microfe-adaptercloud 2026.825.3 → 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.
- package/dist/adaptercloud/components/ActiveSwitch.d.ts +17 -0
- package/dist/adaptercloud/components/ActiveSwitch.d.ts.map +1 -0
- package/dist/adaptercloud/components/ActiveSwitch.js +28 -0
- package/dist/adaptercloud/components/ActiveSwitch.js.map +1 -0
- package/dist/adaptercloud/components/index.d.ts +1 -0
- package/dist/adaptercloud/components/index.d.ts.map +1 -1
- package/dist/adaptercloud/hooks/useAdapterCloudApi.d.ts +28 -2
- package/dist/adaptercloud/hooks/useAdapterCloudApi.d.ts.map +1 -1
- package/dist/adaptercloud/hooks/useAdapterCloudApi.js +43 -18
- package/dist/adaptercloud/hooks/useAdapterCloudApi.js.map +1 -1
- package/dist/adaptercloud/pages/OverviewPage.d.ts.map +1 -1
- package/dist/adaptercloud/pages/OverviewPage.js +4 -4
- package/dist/adaptercloud/pages/OverviewPage.js.map +1 -1
- package/dist/adaptercloud/pages/adapters/AdaptersListPage.d.ts.map +1 -1
- package/dist/adaptercloud/pages/adapters/AdaptersListPage.js +6 -5
- package/dist/adaptercloud/pages/adapters/AdaptersListPage.js.map +1 -1
- package/dist/adaptercloud/pages/connections/ConnectionDetailPage.d.ts.map +1 -1
- package/dist/adaptercloud/pages/connections/ConnectionDetailPage.js +217 -104
- package/dist/adaptercloud/pages/connections/ConnectionDetailPage.js.map +1 -1
- package/dist/adaptercloud/pages/connections/ConnectionsListPage.d.ts.map +1 -1
- package/dist/adaptercloud/pages/connections/ConnectionsListPage.js +6 -5
- package/dist/adaptercloud/pages/connections/ConnectionsListPage.js.map +1 -1
- package/dist/adaptercloud/pages/costs/CostsPage.d.ts.map +1 -1
- package/dist/adaptercloud/pages/costs/CostsPage.js +183 -156
- package/dist/adaptercloud/pages/costs/CostsPage.js.map +1 -1
- package/dist/adaptercloud/pages/drift/DriftListPage.d.ts.map +1 -1
- package/dist/adaptercloud/pages/drift/DriftListPage.js +108 -107
- package/dist/adaptercloud/pages/drift/DriftListPage.js.map +1 -1
- package/dist/adaptercloud/pages/policies/PoliciesListPage.d.ts.map +1 -1
- package/dist/adaptercloud/pages/policies/PoliciesListPage.js +141 -131
- package/dist/adaptercloud/pages/policies/PoliciesListPage.js.map +1 -1
- package/dist/adaptercloud/pages/policies/PolicyDetailPage.d.ts.map +1 -1
- package/dist/adaptercloud/pages/policies/PolicyDetailPage.js +171 -117
- package/dist/adaptercloud/pages/policies/PolicyDetailPage.js.map +1 -1
- package/dist/adaptercloud/pages/resources/ResourcesListPage.d.ts.map +1 -1
- package/dist/adaptercloud/pages/resources/ResourcesListPage.js +85 -66
- package/dist/adaptercloud/pages/resources/ResourcesListPage.js.map +1 -1
- package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.d.ts.map +1 -1
- package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.js +148 -121
- package/dist/adaptercloud/pages/sync-runs/SyncRunsListPage.js.map +1 -1
- package/dist/adaptercloud/pages/violations/ViolationsListPage.d.ts.map +1 -1
- package/dist/adaptercloud/pages/violations/ViolationsListPage.js +145 -144
- package/dist/adaptercloud/pages/violations/ViolationsListPage.js.map +1 -1
- package/dist/utils/pageContext.d.ts +0 -2
- package/dist/utils/pageContext.d.ts.map +1 -1
- package/dist/utils/pageContext.js +25 -10
- package/dist/utils/pageContext.js.map +1 -1
- package/package.json +8 -5
|
@@ -4,244 +4,254 @@ import { PageLayout as n } from "../../components/PageLayout.js";
|
|
|
4
4
|
import { policyEnforcementLabels as r, policyKindLabels as i } from "../../utils/domain.js";
|
|
5
5
|
import { SeverityBadge as a } from "../../components/SeverityBadge.js";
|
|
6
6
|
import { DataState as o } from "../../components/DataState.js";
|
|
7
|
-
import { usePolicies as s, useUpdatePolicy as c } from "../../hooks/useAdapterCloudApi.js";
|
|
8
|
-
import { formatRelativeTime as
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
7
|
+
import { usePolicies as s, useUpdatePolicy as c, useViolations as l } from "../../hooks/useAdapterCloudApi.js";
|
|
8
|
+
import { formatRelativeTime as u } from "../../utils/formatters.js";
|
|
9
|
+
import { ActiveSwitch as d } from "../../components/ActiveSwitch.js";
|
|
10
|
+
import { useCallback as f, useState as p } from "react";
|
|
11
|
+
import { useI18n as m } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
12
|
+
import { ChevronLeft as h, ChevronRight as g, Plus as _, ScrollText as v } from "lucide-react";
|
|
13
|
+
import { jsx as y, jsxs as b } from "react/jsx-runtime";
|
|
14
|
+
import { GlassCard as x } from "@burdenoff/fe-libs/ui";
|
|
14
15
|
//#region src/adaptercloud/pages/policies/PoliciesListPage.tsx
|
|
15
|
-
var
|
|
16
|
+
var S = 20, C = "inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium", w = {
|
|
16
17
|
SECURITY: "bg-accent-blue-subtle text-accent-blue",
|
|
17
18
|
GUARDRAIL: "bg-accent-blue-subtle text-accent-blue",
|
|
18
19
|
COMPLIANCE: "bg-accent-blue-subtle text-accent-blue",
|
|
19
20
|
COST: "bg-status-success-bg-subtle text-status-success-text",
|
|
20
21
|
NAMING: "bg-bg-sunken text-text-secondary",
|
|
21
22
|
TAGGING: "bg-bg-sunken text-text-secondary"
|
|
22
|
-
},
|
|
23
|
+
}, T = {
|
|
23
24
|
BLOCK: "bg-status-error-bg-subtle text-status-error-text",
|
|
24
25
|
WARN: "bg-status-warning-bg-subtle text-status-warning-text",
|
|
25
26
|
ADVISORY: "bg-bg-sunken text-text-secondary"
|
|
26
27
|
};
|
|
27
|
-
function
|
|
28
|
-
return /* @__PURE__ */
|
|
29
|
-
className: t(
|
|
28
|
+
function E({ kind: e }) {
|
|
29
|
+
return /* @__PURE__ */ y("span", {
|
|
30
|
+
className: t(C, w[e]),
|
|
30
31
|
children: i[e]
|
|
31
32
|
});
|
|
32
33
|
}
|
|
33
|
-
function
|
|
34
|
-
return /* @__PURE__ */
|
|
35
|
-
className: t(
|
|
34
|
+
function D({ enforcement: e }) {
|
|
35
|
+
return /* @__PURE__ */ y("span", {
|
|
36
|
+
className: t(C, T[e]),
|
|
36
37
|
children: r[e]
|
|
37
38
|
});
|
|
38
39
|
}
|
|
39
|
-
function
|
|
40
|
-
|
|
40
|
+
function O({ policyId: e }) {
|
|
41
|
+
let n = l({
|
|
42
|
+
policyId: e,
|
|
43
|
+
status: "OPEN",
|
|
44
|
+
pagination: {
|
|
45
|
+
limit: 1,
|
|
46
|
+
offset: 0
|
|
47
|
+
}
|
|
48
|
+
}).data?.pageInfo.totalCount;
|
|
49
|
+
return n == null ? /* @__PURE__ */ y("span", {
|
|
50
|
+
className: "text-sm text-text-tertiary",
|
|
51
|
+
children: "—"
|
|
52
|
+
}) : /* @__PURE__ */ y("span", {
|
|
53
|
+
className: t("text-base font-semibold tabular-nums", n > 0 ? "text-status-error-text" : "text-text-secondary"),
|
|
54
|
+
children: n
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function k({ label: e, children: t }) {
|
|
58
|
+
return /* @__PURE__ */ b("div", {
|
|
41
59
|
className: "flex flex-col gap-1",
|
|
42
|
-
children: [/* @__PURE__ */
|
|
60
|
+
children: [/* @__PURE__ */ y("span", {
|
|
43
61
|
className: "text-xs font-semibold uppercase tracking-wide text-text-secondary",
|
|
44
62
|
children: e
|
|
45
63
|
}), t]
|
|
46
64
|
});
|
|
47
65
|
}
|
|
48
|
-
function
|
|
49
|
-
let { navigateTo:
|
|
50
|
-
let n =
|
|
66
|
+
function A() {
|
|
67
|
+
let { navigateTo: t } = e(), { t: r } = m(), l = f((e, t) => {
|
|
68
|
+
let n = r(e);
|
|
51
69
|
return n === e ? t : n;
|
|
52
|
-
}, [
|
|
70
|
+
}, [r]), [C, w] = p(""), [T, A] = p("all"), [j, M] = p(0), [N, P] = p({}), F = s({
|
|
53
71
|
kind: C || void 0,
|
|
54
|
-
isActive:
|
|
72
|
+
isActive: T === "all" ? void 0 : T === "active",
|
|
55
73
|
pagination: {
|
|
56
|
-
limit:
|
|
57
|
-
offset:
|
|
74
|
+
limit: S,
|
|
75
|
+
offset: j
|
|
58
76
|
}
|
|
59
|
-
}),
|
|
60
|
-
let t = !(
|
|
61
|
-
|
|
77
|
+
}), I = c(), L = F.data?.items ?? [], R = F.data?.pageInfo.hasMore ?? !1, z = F.data?.pageInfo.totalCount, B = f((e) => {
|
|
78
|
+
let t = !(N[e.id] ?? e.isActive);
|
|
79
|
+
P((n) => ({
|
|
62
80
|
...n,
|
|
63
81
|
[e.id]: t
|
|
64
|
-
})),
|
|
82
|
+
})), I.mutate({
|
|
65
83
|
id: e.id,
|
|
66
84
|
input: { isActive: t }
|
|
67
|
-
}, { onSettled: () =>
|
|
85
|
+
}, { onSettled: () => P((t) => {
|
|
68
86
|
let n = { ...t };
|
|
69
87
|
return delete n[e.id], n;
|
|
70
88
|
}) });
|
|
71
|
-
}, [
|
|
72
|
-
return /* @__PURE__ */
|
|
73
|
-
title:
|
|
74
|
-
description:
|
|
75
|
-
actions: /* @__PURE__ */
|
|
89
|
+
}, [I, N]);
|
|
90
|
+
return /* @__PURE__ */ b(n, {
|
|
91
|
+
title: l("adaptercloud.policies.title", "Policies"),
|
|
92
|
+
description: l("adaptercloud.policies.subtitle", "Governance rules that evaluate the inventory — guardrail, tagging, security, cost, compliance and naming."),
|
|
93
|
+
actions: /* @__PURE__ */ b("button", {
|
|
76
94
|
type: "button",
|
|
77
|
-
onClick: () =>
|
|
95
|
+
onClick: () => t("/policies/new"),
|
|
78
96
|
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",
|
|
79
|
-
children: [/* @__PURE__ */ _
|
|
97
|
+
children: [/* @__PURE__ */ y(_, { className: "h-4 w-4" }), l("adaptercloud.policies.new", "New policy")]
|
|
80
98
|
}),
|
|
81
|
-
children: [/* @__PURE__ */
|
|
99
|
+
children: [/* @__PURE__ */ b("div", {
|
|
82
100
|
className: "mb-6 flex flex-wrap gap-3",
|
|
83
|
-
children: [/* @__PURE__ */
|
|
101
|
+
children: [/* @__PURE__ */ b("select", {
|
|
84
102
|
value: C,
|
|
85
103
|
onChange: (e) => {
|
|
86
|
-
|
|
104
|
+
w(e.target.value), M(0);
|
|
87
105
|
},
|
|
88
|
-
"aria-label":
|
|
106
|
+
"aria-label": l("adaptercloud.policies.filterByKind", "Filter by kind"),
|
|
89
107
|
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)]",
|
|
90
|
-
children: [/* @__PURE__ */
|
|
108
|
+
children: [/* @__PURE__ */ y("option", {
|
|
91
109
|
value: "",
|
|
92
|
-
children:
|
|
93
|
-
}), Object.keys(i).map((e) => /* @__PURE__ */
|
|
110
|
+
children: l("adaptercloud.policies.allKinds", "All kinds")
|
|
111
|
+
}), Object.keys(i).map((e) => /* @__PURE__ */ y("option", {
|
|
94
112
|
value: e,
|
|
95
113
|
children: i[e]
|
|
96
114
|
}, e))]
|
|
97
|
-
}), /* @__PURE__ */
|
|
98
|
-
value:
|
|
115
|
+
}), /* @__PURE__ */ b("select", {
|
|
116
|
+
value: T,
|
|
99
117
|
onChange: (e) => {
|
|
100
|
-
|
|
118
|
+
A(e.target.value), M(0);
|
|
101
119
|
},
|
|
102
|
-
"aria-label":
|
|
120
|
+
"aria-label": l("adaptercloud.policies.filterByActive", "Filter by active state"),
|
|
103
121
|
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)]",
|
|
104
122
|
children: [
|
|
105
|
-
/* @__PURE__ */
|
|
123
|
+
/* @__PURE__ */ y("option", {
|
|
106
124
|
value: "all",
|
|
107
|
-
children:
|
|
125
|
+
children: l("adaptercloud.policies.allStates", "All")
|
|
108
126
|
}),
|
|
109
|
-
/* @__PURE__ */
|
|
127
|
+
/* @__PURE__ */ y("option", {
|
|
110
128
|
value: "active",
|
|
111
|
-
children:
|
|
129
|
+
children: l("adaptercloud.policies.active", "Active")
|
|
112
130
|
}),
|
|
113
|
-
/* @__PURE__ */
|
|
131
|
+
/* @__PURE__ */ y("option", {
|
|
114
132
|
value: "inactive",
|
|
115
|
-
children:
|
|
133
|
+
children: l("adaptercloud.policies.inactive", "Inactive")
|
|
116
134
|
})
|
|
117
135
|
]
|
|
118
136
|
})]
|
|
119
|
-
}), /* @__PURE__ */
|
|
120
|
-
isLoading:
|
|
121
|
-
isError:
|
|
122
|
-
isEmpty:
|
|
123
|
-
error:
|
|
124
|
-
onRetry: () => void
|
|
125
|
-
emptyTitle:
|
|
126
|
-
emptyDescription:
|
|
127
|
-
emptyIcon: /* @__PURE__ */
|
|
128
|
-
emptyAction: /* @__PURE__ */
|
|
137
|
+
}), /* @__PURE__ */ b(o, {
|
|
138
|
+
isLoading: F.isLoading,
|
|
139
|
+
isError: F.isError,
|
|
140
|
+
isEmpty: L.length === 0,
|
|
141
|
+
error: F.error,
|
|
142
|
+
onRetry: () => void F.refetch(),
|
|
143
|
+
emptyTitle: l("adaptercloud.policies.emptyTitle", "No policies yet"),
|
|
144
|
+
emptyDescription: l("adaptercloud.policies.emptyDescription", "Author your first governance policy to put compliance into the system."),
|
|
145
|
+
emptyIcon: /* @__PURE__ */ y(v, { className: "h-10 w-10" }),
|
|
146
|
+
emptyAction: /* @__PURE__ */ y("button", {
|
|
129
147
|
type: "button",
|
|
130
|
-
onClick: () =>
|
|
148
|
+
onClick: () => t("/policies/new"),
|
|
131
149
|
className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90",
|
|
132
|
-
children:
|
|
150
|
+
children: l("adaptercloud.policies.new", "New policy")
|
|
133
151
|
}),
|
|
134
|
-
children: [/* @__PURE__ */
|
|
152
|
+
children: [/* @__PURE__ */ y("div", {
|
|
135
153
|
className: "space-y-3",
|
|
136
|
-
children:
|
|
137
|
-
let n =
|
|
138
|
-
return /* @__PURE__ */
|
|
154
|
+
children: L.map((e) => {
|
|
155
|
+
let n = N[e.id] ?? e.isActive, r = e.id in N;
|
|
156
|
+
return /* @__PURE__ */ b(x, {
|
|
139
157
|
role: "button",
|
|
140
158
|
tabIndex: 0,
|
|
141
|
-
onClick: () =>
|
|
142
|
-
onKeyDown: (
|
|
143
|
-
(
|
|
159
|
+
onClick: () => t(`/policies/${e.id}`),
|
|
160
|
+
onKeyDown: (n) => {
|
|
161
|
+
(n.key === "Enter" || n.key === " ") && (n.preventDefault(), t(`/policies/${e.id}`));
|
|
144
162
|
},
|
|
145
163
|
className: "cursor-pointer p-5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]",
|
|
146
|
-
children: [/* @__PURE__ */
|
|
164
|
+
children: [/* @__PURE__ */ b("div", {
|
|
147
165
|
className: "flex flex-col gap-4 lg:flex-row lg:items-center lg:gap-6",
|
|
148
166
|
children: [
|
|
149
|
-
/* @__PURE__ */
|
|
167
|
+
/* @__PURE__ */ b("div", {
|
|
150
168
|
className: "min-w-0 lg:flex-1",
|
|
151
|
-
children: [/* @__PURE__ */
|
|
169
|
+
children: [/* @__PURE__ */ y("h3", {
|
|
152
170
|
className: "truncate text-base font-semibold text-text-primary",
|
|
153
171
|
children: e.name
|
|
154
|
-
}), e.description && /* @__PURE__ */
|
|
172
|
+
}), e.description && /* @__PURE__ */ y("p", {
|
|
155
173
|
className: "mt-0.5 line-clamp-1 text-sm text-text-secondary",
|
|
156
174
|
children: e.description
|
|
157
175
|
})]
|
|
158
176
|
}),
|
|
159
|
-
/* @__PURE__ */
|
|
160
|
-
label:
|
|
161
|
-
children: /* @__PURE__ */
|
|
177
|
+
/* @__PURE__ */ y(k, {
|
|
178
|
+
label: l("adaptercloud.policies.kind", "Kind"),
|
|
179
|
+
children: /* @__PURE__ */ y(E, { kind: e.kind })
|
|
162
180
|
}),
|
|
163
|
-
/* @__PURE__ */
|
|
164
|
-
label:
|
|
165
|
-
children: /* @__PURE__ */
|
|
181
|
+
/* @__PURE__ */ y(k, {
|
|
182
|
+
label: l("adaptercloud.policies.enforcement", "Enforcement"),
|
|
183
|
+
children: /* @__PURE__ */ y(D, { enforcement: e.enforcement })
|
|
166
184
|
}),
|
|
167
|
-
/* @__PURE__ */
|
|
168
|
-
label:
|
|
169
|
-
children: /* @__PURE__ */
|
|
185
|
+
/* @__PURE__ */ y(k, {
|
|
186
|
+
label: l("adaptercloud.policies.severity", "Severity"),
|
|
187
|
+
children: /* @__PURE__ */ y(a, { severity: e.severity })
|
|
170
188
|
}),
|
|
171
|
-
/* @__PURE__ */
|
|
172
|
-
label:
|
|
173
|
-
children: /* @__PURE__ */
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
disabled: i,
|
|
181
|
-
onClick: (t) => {
|
|
182
|
-
t.stopPropagation(), R(e);
|
|
183
|
-
},
|
|
184
|
-
className: t("relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] disabled:opacity-60", n ? "border-transparent bg-action-primary-bg" : "border-border-subtle bg-bg-sunken"),
|
|
185
|
-
children: /* @__PURE__ */ _("span", {
|
|
186
|
-
"aria-hidden": "true",
|
|
187
|
-
className: t("inline-block h-3.5 w-3.5 transform rounded-full shadow-sm transition-transform", n ? "translate-x-4 bg-action-primary-text" : "translate-x-0.5 bg-text-secondary")
|
|
188
|
-
})
|
|
189
|
-
}), /* @__PURE__ */ _("span", {
|
|
190
|
-
className: "text-xs text-text-secondary",
|
|
191
|
-
children: n ? S("adaptercloud.policies.active", "Active") : S("adaptercloud.policies.inactive", "Inactive")
|
|
192
|
-
})]
|
|
189
|
+
/* @__PURE__ */ y(k, {
|
|
190
|
+
label: l("adaptercloud.policies.activeLabel", "Active"),
|
|
191
|
+
children: /* @__PURE__ */ y(d, {
|
|
192
|
+
checked: n,
|
|
193
|
+
disabled: r,
|
|
194
|
+
stopPropagation: !0,
|
|
195
|
+
onToggle: () => B(e),
|
|
196
|
+
label: n ? l("adaptercloud.policies.deactivate", "Deactivate policy") : l("adaptercloud.policies.activate", "Activate policy"),
|
|
197
|
+
children: n ? l("adaptercloud.policies.active", "Active") : l("adaptercloud.policies.inactive", "Inactive")
|
|
193
198
|
})
|
|
194
199
|
}),
|
|
195
|
-
|
|
196
|
-
label:
|
|
197
|
-
children: /* @__PURE__ */
|
|
200
|
+
/* @__PURE__ */ y(k, {
|
|
201
|
+
label: l("adaptercloud.policies.openViolations", "Open violations"),
|
|
202
|
+
children: /* @__PURE__ */ y(O, { policyId: e.id })
|
|
203
|
+
}),
|
|
204
|
+
e.appliesTo.length > 0 && /* @__PURE__ */ y(k, {
|
|
205
|
+
label: l("adaptercloud.policies.appliesTo", "Applies to"),
|
|
206
|
+
children: /* @__PURE__ */ b("div", {
|
|
198
207
|
className: "flex flex-wrap items-center gap-1.5",
|
|
199
|
-
children: [e.appliesTo.slice(0, 2).map((e) => /* @__PURE__ */
|
|
208
|
+
children: [e.appliesTo.slice(0, 2).map((e) => /* @__PURE__ */ y("span", {
|
|
200
209
|
className: "inline-flex items-center rounded-full bg-accent-blue-subtle px-2 py-0.5 font-mono text-xs text-accent-blue",
|
|
201
210
|
children: e
|
|
202
|
-
}, e)), e.appliesTo.length > 2 && /* @__PURE__ */
|
|
211
|
+
}, e)), e.appliesTo.length > 2 && /* @__PURE__ */ b("span", {
|
|
203
212
|
className: "inline-flex items-center rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary",
|
|
204
213
|
children: ["+", e.appliesTo.length - 2]
|
|
205
214
|
})]
|
|
206
215
|
})
|
|
207
216
|
})
|
|
208
217
|
]
|
|
209
|
-
}), /* @__PURE__ */
|
|
218
|
+
}), /* @__PURE__ */ b("p", {
|
|
210
219
|
className: "mt-3 text-xs text-text-secondary",
|
|
211
220
|
children: [
|
|
212
|
-
|
|
221
|
+
l("adaptercloud.common.updated", "Updated"),
|
|
213
222
|
" ",
|
|
214
|
-
|
|
223
|
+
u(e.updatedAt)
|
|
215
224
|
]
|
|
216
225
|
})]
|
|
217
226
|
}, e.id);
|
|
218
227
|
})
|
|
219
|
-
}), (
|
|
228
|
+
}), (j > 0 || R) && /* @__PURE__ */ b("div", {
|
|
220
229
|
className: "mt-6 flex items-center justify-between",
|
|
221
230
|
children: [
|
|
222
|
-
/* @__PURE__ */
|
|
231
|
+
/* @__PURE__ */ b("button", {
|
|
223
232
|
type: "button",
|
|
224
|
-
disabled:
|
|
225
|
-
onClick: () =>
|
|
233
|
+
disabled: j === 0,
|
|
234
|
+
onClick: () => M((e) => Math.max(0, e - S)),
|
|
226
235
|
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",
|
|
227
|
-
children: [/* @__PURE__ */
|
|
236
|
+
children: [/* @__PURE__ */ y(h, { className: "h-4 w-4" }), l("adaptercloud.common.prev", "Previous")]
|
|
228
237
|
}),
|
|
229
|
-
/* @__PURE__ */
|
|
230
|
-
className: "text-sm text-text-secondary",
|
|
238
|
+
/* @__PURE__ */ b("span", {
|
|
239
|
+
className: "text-sm tabular-nums text-text-secondary",
|
|
231
240
|
children: [
|
|
232
|
-
|
|
241
|
+
l("adaptercloud.common.showing", "Showing"),
|
|
233
242
|
" ",
|
|
234
|
-
|
|
243
|
+
j + 1,
|
|
235
244
|
"–",
|
|
236
|
-
|
|
245
|
+
j + L.length,
|
|
246
|
+
z != null && ` ${l("adaptercloud.common.of", "of")} ${z}`
|
|
237
247
|
]
|
|
238
248
|
}),
|
|
239
|
-
/* @__PURE__ */
|
|
249
|
+
/* @__PURE__ */ b("button", {
|
|
240
250
|
type: "button",
|
|
241
|
-
disabled: !
|
|
242
|
-
onClick: () =>
|
|
251
|
+
disabled: !R,
|
|
252
|
+
onClick: () => M((e) => e + S),
|
|
243
253
|
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",
|
|
244
|
-
children: [
|
|
254
|
+
children: [l("adaptercloud.common.next", "Next"), /* @__PURE__ */ y(g, { className: "h-4 w-4" })]
|
|
245
255
|
})
|
|
246
256
|
]
|
|
247
257
|
})]
|
|
@@ -249,6 +259,6 @@ function D() {
|
|
|
249
259
|
});
|
|
250
260
|
}
|
|
251
261
|
//#endregion
|
|
252
|
-
export {
|
|
262
|
+
export { A as PoliciesListPage };
|
|
253
263
|
|
|
254
264
|
//# sourceMappingURL=PoliciesListPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PoliciesListPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/policies/PoliciesListPage.tsx"],"sourcesContent":["/**\n * Policies List Page\n * @module adaptercloud/pages/policies\n *\n * Governance rules evaluated against the inventory (`adaListPolicies`). Filters\n * by kind and active flag; offset pagination. Each row surfaces color-coded\n * KIND / ENFORCEMENT / SEVERITY badges, an applies-to chip set, and an inline\n * Active toggle wired to `adaUpdatePolicy` (optimistic, toasts on success).\n */\n\nimport { useState, useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { ScrollText, Plus, ChevronLeft, ChevronRight } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { SeverityBadge } from '../../components/SeverityBadge';\nimport { DataState } from '../../components/DataState';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { usePolicies, useUpdatePolicy } from '../../hooks/useAdapterCloudApi';\nimport { policyKindLabels, policyEnforcementLabels } from '../../utils/domain';\nimport { formatRelativeTime } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { AdaPolicy, AdaPolicyEnforcement, AdaPolicyKind } from '../../types';\n\nconst PAGE_SIZE = 20;\n\ntype ActiveFilter = 'all' | 'active' | 'inactive';\n\n// ---------------------------------------------------------------------------\n// Color-coded governance badges (semantic tokens only), mirroring SeverityBadge.\n// ---------------------------------------------------------------------------\n\nconst badgeBase = 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium';\n\n/** Kind → semantic token. Security/Guardrail/Compliance read as governance\n * (accent-blue), Cost as spend (success/green), the rest as neutral. */\nconst policyKindBadgeClass: Record<AdaPolicyKind, string> = {\n SECURITY: 'bg-accent-blue-subtle text-accent-blue',\n GUARDRAIL: 'bg-accent-blue-subtle text-accent-blue',\n COMPLIANCE: 'bg-accent-blue-subtle text-accent-blue',\n COST: 'bg-status-success-bg-subtle text-status-success-text',\n NAMING: 'bg-bg-sunken text-text-secondary',\n TAGGING: 'bg-bg-sunken text-text-secondary',\n};\n\n/** Enforcement → semantic token. Block = error, Warn = warning, Advisory = neutral. */\nconst policyEnforcementBadgeClass: Record<AdaPolicyEnforcement, string> = {\n BLOCK: 'bg-status-error-bg-subtle text-status-error-text',\n WARN: 'bg-status-warning-bg-subtle text-status-warning-text',\n ADVISORY: 'bg-bg-sunken text-text-secondary',\n};\n\nfunction KindBadge({ kind }: { kind: AdaPolicyKind }) {\n return (\n <span className={cn(badgeBase, policyKindBadgeClass[kind])}>{policyKindLabels[kind]}</span>\n );\n}\n\nfunction EnforcementBadge({ enforcement }: { enforcement: AdaPolicyEnforcement }) {\n return (\n <span className={cn(badgeBase, policyEnforcementBadgeClass[enforcement])}>\n {policyEnforcementLabels[enforcement]}\n </span>\n );\n}\n\n/** Labeled meta column (eyebrow + value) used across each policy row. */\nfunction MetaCol({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n {label}\n </span>\n {children}\n </div>\n );\n}\n\nexport function PoliciesListPage() {\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<AdaPolicyKind | ''>('');\n const [active, setActive] = useState<ActiveFilter>('all');\n const [offset, setOffset] = useState(0);\n // Local optimistic override of isActive per policy id while the mutation is in\n // flight, so the toggle flips instantly instead of waiting for the refetch.\n const [pendingActive, setPendingActive] = useState<Record<string, boolean>>({});\n\n const query = usePolicies({\n kind: kind || undefined,\n isActive: active === 'all' ? undefined : active === 'active',\n pagination: { limit: PAGE_SIZE, offset },\n });\n const update = useUpdatePolicy();\n\n const items = query.data?.items ?? [];\n const hasMore = query.data?.pageInfo.hasMore ?? false;\n\n const toggleActive = useCallback(\n (policy: AdaPolicy) => {\n const next = !(pendingActive[policy.id] ?? policy.isActive);\n setPendingActive((m) => ({ ...m, [policy.id]: next }));\n update.mutate(\n { id: policy.id, input: { isActive: next } },\n {\n onSettled: () =>\n setPendingActive((m) => {\n const copy = { ...m };\n delete copy[policy.id];\n return copy;\n }),\n }\n );\n },\n [update, pendingActive]\n );\n\n return (\n <PageLayout\n title={t('adaptercloud.policies.title', 'Policies')}\n description={t(\n 'adaptercloud.policies.subtitle',\n 'Governance rules that evaluate the inventory — guardrail, tagging, security, cost, compliance and naming.'\n )}\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/policies/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.policies.new', 'New policy')}\n </button>\n }\n >\n <div className=\"mb-6 flex flex-wrap gap-3\">\n <select\n value={kind}\n onChange={(e) => {\n setKind(e.target.value as AdaPolicyKind | '');\n setOffset(0);\n }}\n aria-label={t('adaptercloud.policies.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.policies.allKinds', 'All kinds')}</option>\n {(Object.keys(policyKindLabels) as AdaPolicyKind[]).map((k) => (\n <option key={k} value={k}>\n {policyKindLabels[k]}\n </option>\n ))}\n </select>\n <select\n value={active}\n onChange={(e) => {\n setActive(e.target.value as ActiveFilter);\n setOffset(0);\n }}\n aria-label={t('adaptercloud.policies.filterByActive', 'Filter by active state')}\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=\"all\">{t('adaptercloud.policies.allStates', 'All')}</option>\n <option value=\"active\">{t('adaptercloud.policies.active', 'Active')}</option>\n <option value=\"inactive\">{t('adaptercloud.policies.inactive', 'Inactive')}</option>\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.policies.emptyTitle', 'No policies yet')}\n emptyDescription={t(\n 'adaptercloud.policies.emptyDescription',\n 'Author your first governance policy to put compliance into the system.'\n )}\n emptyIcon={<ScrollText className=\"h-10 w-10\" />}\n emptyAction={\n <button\n type=\"button\"\n onClick={() => navigateTo('/policies/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.policies.new', 'New policy')}\n </button>\n }\n >\n <div className=\"space-y-3\">\n {items.map((policy) => {\n const isActiveNow = pendingActive[policy.id] ?? policy.isActive;\n const isToggling = policy.id in pendingActive;\n return (\n <GlassCard\n key={policy.id}\n role=\"button\"\n tabIndex={0}\n onClick={() => navigateTo(`/policies/${policy.id}`)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n navigateTo(`/policies/${policy.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 flex-col gap-4 lg:flex-row lg:items-center lg:gap-6\">\n <div className=\"min-w-0 lg:flex-1\">\n <h3 className=\"truncate text-base font-semibold text-text-primary\">\n {policy.name}\n </h3>\n {policy.description && (\n <p className=\"mt-0.5 line-clamp-1 text-sm text-text-secondary\">\n {policy.description}\n </p>\n )}\n </div>\n\n <MetaCol label={t('adaptercloud.policies.kind', 'Kind')}>\n <KindBadge kind={policy.kind} />\n </MetaCol>\n\n <MetaCol label={t('adaptercloud.policies.enforcement', 'Enforcement')}>\n <EnforcementBadge enforcement={policy.enforcement} />\n </MetaCol>\n\n <MetaCol label={t('adaptercloud.policies.severity', 'Severity')}>\n <SeverityBadge severity={policy.severity} />\n </MetaCol>\n\n <MetaCol label={t('adaptercloud.policies.activeLabel', 'Active')}>\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={isActiveNow}\n aria-label={\n isActiveNow\n ? t('adaptercloud.policies.deactivate', 'Deactivate policy')\n : t('adaptercloud.policies.activate', 'Activate policy')\n }\n disabled={isToggling}\n onClick={(e) => {\n e.stopPropagation();\n toggleActive(policy);\n }}\n className={cn(\n 'relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] disabled:opacity-60',\n isActiveNow\n ? 'border-transparent bg-action-primary-bg'\n : 'border-border-subtle bg-bg-sunken'\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n 'inline-block h-3.5 w-3.5 transform rounded-full shadow-sm transition-transform',\n isActiveNow\n ? 'translate-x-4 bg-action-primary-text'\n : 'translate-x-0.5 bg-text-secondary'\n )}\n />\n </button>\n <span className=\"text-xs text-text-secondary\">\n {isActiveNow\n ? t('adaptercloud.policies.active', 'Active')\n : t('adaptercloud.policies.inactive', 'Inactive')}\n </span>\n </div>\n </MetaCol>\n\n {policy.appliesTo.length > 0 && (\n <MetaCol label={t('adaptercloud.policies.appliesTo', 'Applies to')}>\n <div className=\"flex flex-wrap items-center gap-1.5\">\n {policy.appliesTo.slice(0, 2).map((sel) => (\n <span\n key={sel}\n className=\"inline-flex items-center rounded-full bg-accent-blue-subtle px-2 py-0.5 font-mono text-xs text-accent-blue\"\n >\n {sel}\n </span>\n ))}\n {policy.appliesTo.length > 2 && (\n <span className=\"inline-flex items-center rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary\">\n +{policy.appliesTo.length - 2}\n </span>\n )}\n </div>\n </MetaCol>\n )}\n </div>\n\n <p className=\"mt-3 text-xs text-text-secondary\">\n {t('adaptercloud.common.updated', 'Updated')}{' '}\n {formatRelativeTime(policy.updatedAt)}\n </p>\n </GlassCard>\n );\n })}\n </div>\n\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":"PoliciesListPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/policies/PoliciesListPage.tsx"],"sourcesContent":["/**\n * Policies List Page\n * @module adaptercloud/pages/policies\n *\n * Governance rules evaluated against the inventory (`adaListPolicies`). Filters\n * by kind and active flag; offset pagination. Each row surfaces color-coded\n * KIND / ENFORCEMENT / SEVERITY badges, an applies-to chip set, and an inline\n * Active toggle wired to `adaUpdatePolicy` (optimistic, toasts on success).\n */\n\nimport { useState, useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { ScrollText, Plus, ChevronLeft, ChevronRight } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { SeverityBadge } from '../../components/SeverityBadge';\nimport { DataState } from '../../components/DataState';\nimport { ActiveSwitch } from '../../components/ActiveSwitch';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { usePolicies, useUpdatePolicy, useViolations } from '../../hooks/useAdapterCloudApi';\nimport { policyKindLabels, policyEnforcementLabels } from '../../utils/domain';\nimport { formatRelativeTime } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\nimport type { AdaPolicy, AdaPolicyEnforcement, AdaPolicyKind } from '../../types';\n\nconst PAGE_SIZE = 20;\n\ntype ActiveFilter = 'all' | 'active' | 'inactive';\n\n// ---------------------------------------------------------------------------\n// Color-coded governance badges (semantic tokens only), mirroring SeverityBadge.\n// ---------------------------------------------------------------------------\n\nconst badgeBase = 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium';\n\n/** Kind → semantic token. Security/Guardrail/Compliance read as governance\n * (accent-blue), Cost as spend (success/green), the rest as neutral. */\nconst policyKindBadgeClass: Record<AdaPolicyKind, string> = {\n SECURITY: 'bg-accent-blue-subtle text-accent-blue',\n GUARDRAIL: 'bg-accent-blue-subtle text-accent-blue',\n COMPLIANCE: 'bg-accent-blue-subtle text-accent-blue',\n COST: 'bg-status-success-bg-subtle text-status-success-text',\n NAMING: 'bg-bg-sunken text-text-secondary',\n TAGGING: 'bg-bg-sunken text-text-secondary',\n};\n\n/** Enforcement → semantic token. Block = error, Warn = warning, Advisory = neutral. */\nconst policyEnforcementBadgeClass: Record<AdaPolicyEnforcement, string> = {\n BLOCK: 'bg-status-error-bg-subtle text-status-error-text',\n WARN: 'bg-status-warning-bg-subtle text-status-warning-text',\n ADVISORY: 'bg-bg-sunken text-text-secondary',\n};\n\nfunction KindBadge({ kind }: { kind: AdaPolicyKind }) {\n return (\n <span className={cn(badgeBase, policyKindBadgeClass[kind])}>{policyKindLabels[kind]}</span>\n );\n}\n\nfunction EnforcementBadge({ enforcement }: { enforcement: AdaPolicyEnforcement }) {\n return (\n <span className={cn(badgeBase, policyEnforcementBadgeClass[enforcement])}>\n {policyEnforcementLabels[enforcement]}\n </span>\n );\n}\n\n/**\n * Live open-violation count for one policy.\n *\n * Reads the estate-wide `pageInfo.totalCount` from a `limit: 1`\n * `adaListViolations(policyId, status: OPEN)` query — the same exact-count\n * pattern the violations queue uses for its status tabs. Renders an em dash\n * rather than a guess when the count is not (yet) known.\n */\nfunction OpenViolationCount({ policyId }: { policyId: string }) {\n const query = useViolations({\n policyId,\n status: 'OPEN',\n pagination: { limit: 1, offset: 0 },\n });\n const count = query.data?.pageInfo.totalCount;\n\n if (count == null) {\n return <span className=\"text-sm text-text-tertiary\">—</span>;\n }\n return (\n <span\n className={cn(\n 'text-base font-semibold tabular-nums',\n count > 0 ? 'text-status-error-text' : 'text-text-secondary'\n )}\n >\n {count}\n </span>\n );\n}\n\n/** Labeled meta column (eyebrow + value) used across each policy row. */\nfunction MetaCol({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n {label}\n </span>\n {children}\n </div>\n );\n}\n\nexport function PoliciesListPage() {\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<AdaPolicyKind | ''>('');\n const [active, setActive] = useState<ActiveFilter>('all');\n const [offset, setOffset] = useState(0);\n // Local optimistic override of isActive per policy id while the mutation is in\n // flight, so the toggle flips instantly instead of waiting for the refetch.\n const [pendingActive, setPendingActive] = useState<Record<string, boolean>>({});\n\n const query = usePolicies({\n kind: kind || undefined,\n isActive: active === 'all' ? undefined : active === 'active',\n pagination: { limit: PAGE_SIZE, offset },\n });\n const update = useUpdatePolicy();\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 toggleActive = useCallback(\n (policy: AdaPolicy) => {\n const next = !(pendingActive[policy.id] ?? policy.isActive);\n setPendingActive((m) => ({ ...m, [policy.id]: next }));\n update.mutate(\n { id: policy.id, input: { isActive: next } },\n {\n onSettled: () =>\n setPendingActive((m) => {\n const copy = { ...m };\n delete copy[policy.id];\n return copy;\n }),\n }\n );\n },\n [update, pendingActive]\n );\n\n return (\n <PageLayout\n title={t('adaptercloud.policies.title', 'Policies')}\n description={t(\n 'adaptercloud.policies.subtitle',\n 'Governance rules that evaluate the inventory — guardrail, tagging, security, cost, compliance and naming.'\n )}\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/policies/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.policies.new', 'New policy')}\n </button>\n }\n >\n <div className=\"mb-6 flex flex-wrap gap-3\">\n <select\n value={kind}\n onChange={(e) => {\n setKind(e.target.value as AdaPolicyKind | '');\n setOffset(0);\n }}\n aria-label={t('adaptercloud.policies.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.policies.allKinds', 'All kinds')}</option>\n {(Object.keys(policyKindLabels) as AdaPolicyKind[]).map((k) => (\n <option key={k} value={k}>\n {policyKindLabels[k]}\n </option>\n ))}\n </select>\n <select\n value={active}\n onChange={(e) => {\n setActive(e.target.value as ActiveFilter);\n setOffset(0);\n }}\n aria-label={t('adaptercloud.policies.filterByActive', 'Filter by active state')}\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=\"all\">{t('adaptercloud.policies.allStates', 'All')}</option>\n <option value=\"active\">{t('adaptercloud.policies.active', 'Active')}</option>\n <option value=\"inactive\">{t('adaptercloud.policies.inactive', 'Inactive')}</option>\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.policies.emptyTitle', 'No policies yet')}\n emptyDescription={t(\n 'adaptercloud.policies.emptyDescription',\n 'Author your first governance policy to put compliance into the system.'\n )}\n emptyIcon={<ScrollText className=\"h-10 w-10\" />}\n emptyAction={\n <button\n type=\"button\"\n onClick={() => navigateTo('/policies/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.policies.new', 'New policy')}\n </button>\n }\n >\n <div className=\"space-y-3\">\n {items.map((policy) => {\n const isActiveNow = pendingActive[policy.id] ?? policy.isActive;\n const isToggling = policy.id in pendingActive;\n return (\n <GlassCard\n key={policy.id}\n role=\"button\"\n tabIndex={0}\n onClick={() => navigateTo(`/policies/${policy.id}`)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n navigateTo(`/policies/${policy.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 flex-col gap-4 lg:flex-row lg:items-center lg:gap-6\">\n <div className=\"min-w-0 lg:flex-1\">\n <h3 className=\"truncate text-base font-semibold text-text-primary\">\n {policy.name}\n </h3>\n {policy.description && (\n <p className=\"mt-0.5 line-clamp-1 text-sm text-text-secondary\">\n {policy.description}\n </p>\n )}\n </div>\n\n <MetaCol label={t('adaptercloud.policies.kind', 'Kind')}>\n <KindBadge kind={policy.kind} />\n </MetaCol>\n\n <MetaCol label={t('adaptercloud.policies.enforcement', 'Enforcement')}>\n <EnforcementBadge enforcement={policy.enforcement} />\n </MetaCol>\n\n <MetaCol label={t('adaptercloud.policies.severity', 'Severity')}>\n <SeverityBadge severity={policy.severity} />\n </MetaCol>\n\n <MetaCol label={t('adaptercloud.policies.activeLabel', 'Active')}>\n <ActiveSwitch\n checked={isActiveNow}\n disabled={isToggling}\n stopPropagation\n onToggle={() => toggleActive(policy)}\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 </MetaCol>\n\n <MetaCol label={t('adaptercloud.policies.openViolations', 'Open violations')}>\n <OpenViolationCount policyId={policy.id} />\n </MetaCol>\n\n {policy.appliesTo.length > 0 && (\n <MetaCol label={t('adaptercloud.policies.appliesTo', 'Applies to')}>\n <div className=\"flex flex-wrap items-center gap-1.5\">\n {policy.appliesTo.slice(0, 2).map((sel) => (\n <span\n key={sel}\n className=\"inline-flex items-center rounded-full bg-accent-blue-subtle px-2 py-0.5 font-mono text-xs text-accent-blue\"\n >\n {sel}\n </span>\n ))}\n {policy.appliesTo.length > 2 && (\n <span className=\"inline-flex items-center rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary\">\n +{policy.appliesTo.length - 2}\n </span>\n )}\n </div>\n </MetaCol>\n )}\n </div>\n\n <p className=\"mt-3 text-xs text-text-secondary\">\n {t('adaptercloud.common.updated', 'Updated')}{' '}\n {formatRelativeTime(policy.updatedAt)}\n </p>\n </GlassCard>\n );\n })}\n </div>\n\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":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PolicyDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/adaptercloud/pages/policies/PolicyDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"PolicyDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/adaptercloud/pages/policies/PolicyDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuBH,wBAAgB,gBAAgB,gCAuS/B"}
|