@leverege/imaginarium-ui 1.7.2 → 1.8.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/lib/PluginSetup-CBFwSR1s.js +2532 -0
- package/lib/PluginSetup-CBFwSR1s.js.map +1 -0
- package/lib/PluginSetup-bDYZGAaC.cjs +116 -0
- package/lib/PluginSetup-bDYZGAaC.cjs.map +1 -0
- package/lib/imp/release/ChangesPreviewDialog.d.ts +15 -0
- package/lib/imp/release/ChangesPreviewDialog.d.ts.map +1 -0
- package/lib/imp/release/PushDialog.d.ts.map +1 -1
- package/lib/imp/release/PushPreviewList.d.ts +27 -0
- package/lib/imp/release/PushPreviewList.d.ts.map +1 -0
- package/lib/imp/release/ReleaseDetail.d.ts.map +1 -1
- package/lib/imp/release/types.d.ts +24 -0
- package/lib/imp/release/types.d.ts.map +1 -1
- package/lib/index.cjs +1 -1
- package/lib/index.js +1 -1
- package/lib/mdComponents-BM9poVvh.cjs.map +1 -1
- package/lib/mdComponents-DTSag34Z.js.map +1 -1
- package/lib/release.cjs +1 -1
- package/lib/release.js +1 -1
- package/package.json +2 -2
- package/src/imp/release/ChangesPreviewDialog.tsx +93 -0
- package/src/imp/release/DiffPanel.tsx +1 -1
- package/src/imp/release/PushDialog.tsx +13 -10
- package/src/imp/release/PushPreviewList.tsx +229 -0
- package/src/imp/release/ReleaseDetail.tsx +37 -7
- package/src/imp/release/types.ts +30 -0
- package/lib/PluginSetup-CXxIBrSM.js +0 -2301
- package/lib/PluginSetup-CXxIBrSM.js.map +0 -1
- package/lib/PluginSetup-Cc-kl5b8.cjs +0 -116
- package/lib/PluginSetup-Cc-kl5b8.cjs.map +0 -1
|
@@ -0,0 +1,2532 @@
|
|
|
1
|
+
import { P as Mt, N as Dt } from "./PluginTypes-mZ4TjxPV.js";
|
|
2
|
+
import { M as Ft, u as be, P as qt } from "./MarkdownPageDoc-D-4LY8Fg.js";
|
|
3
|
+
import { jsx as e, jsxs as n, Fragment as ze } from "react/jsx-runtime";
|
|
4
|
+
import { useState as R, useMemo as q, useEffect as Qe, Fragment as yt } from "react";
|
|
5
|
+
import { u as oe, a as te, B as E, C as Ae, f as Me, c as ce } from "./Card-D2LdIJwJ.js";
|
|
6
|
+
import { useQueryClient as de, useMutation as _, useQuery as ae } from "@tanstack/react-query";
|
|
7
|
+
import { X as Ne, Loader2 as Ve, Save as bt, Plus as je, Ban as Be, RotateCcw as zt, AlertTriangle as ye, Check as Nt, ChevronDown as ue, ChevronRight as he, Send as jt, Circle as Bt, ArrowLeft as Le, RefreshCw as vt, ListChecks as Lt, BarChart2 as Jt, Pencil as Qt, Trash2 as wt, Bot as Vt } from "lucide-react";
|
|
8
|
+
import { Config as Ue } from "@leverege/plugin";
|
|
9
|
+
import { D as ve, a as we, b as ke, c as Ce, d as Te, L as le, I as ge, e as Pe } from "./Label-v0wUXs4O.js";
|
|
10
|
+
import { b as Ut, T as Ht, c as _t, a as Yt } from "./Tooltip-CIwKmgzA.js";
|
|
11
|
+
const Wt = Ft.create({
|
|
12
|
+
path: "/imp",
|
|
13
|
+
markdown: `# imp
|
|
14
|
+
|
|
15
|
+
Manage cross-cluster releases for your Imagine project. A release captures a snapshot of entities from an origin cluster and lets you review diffs and push to one or more destination clusters.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Releases tab
|
|
20
|
+
|
|
21
|
+
### Creating a release
|
|
22
|
+
|
|
23
|
+
A release snapshots all entities (blueprints, rules, scripts, attributes, enums, roles, etc.) from an origin cluster at a point in time and tracks what differs from one or more destination clusters.
|
|
24
|
+
|
|
25
|
+
### Reading the diff
|
|
26
|
+
|
|
27
|
+
Each row is one entity. The status column tells you what changed:
|
|
28
|
+
|
|
29
|
+
- new: exists on origin, not on any destination
|
|
30
|
+
- updated: exists on both but differs
|
|
31
|
+
- removed: exists on destination(s) but no longer on origin
|
|
32
|
+
- skip: automatically excluded (e.g. a rule with no published version, or all versions already exist on the destination)
|
|
33
|
+
|
|
34
|
+
Selecting a row opens the diff panel on the right, which shows a side-by-side JSON diff for updated items.
|
|
35
|
+
|
|
36
|
+
### Including / excluding items
|
|
37
|
+
|
|
38
|
+
The toggle at the left of each row controls whether that item is included in the push. The type chips and Enabled / Disabled filter help narrow down what you're looking at.
|
|
39
|
+
|
|
40
|
+
Items with children (e.g. a blueprint with changed attributes) show a child count chip. Expanding the row lets you include or exclude individual child changes. The top-level toggle only controls the parent entity's own changes (tags, metadata, etc.) and does not automatically include or exclude its children.
|
|
41
|
+
|
|
42
|
+
### Previously skipped
|
|
43
|
+
|
|
44
|
+
Items that were excluded in the most recent previous release are automatically carried over as excluded in the next one and marked "previously skipped." This prevents accidentally re-including something you intentionally left out last time. Manually toggling the item clears the badge and the carry-over behavior.
|
|
45
|
+
|
|
46
|
+
### Refreshing a snapshot
|
|
47
|
+
|
|
48
|
+
Refresh re-snapshots the origin against the current state of the destinations. New items appear, removed items drop out, and diffs update. Manual overrides (excluded tags, metadata keys, etc.) are preserved across refreshes.
|
|
49
|
+
|
|
50
|
+
### Pushing
|
|
51
|
+
|
|
52
|
+
Pushing sends all included items to the selected destination clusters. The release becomes read-only after a push. Each row surfaces its result as a success or failure chip. Hover a chip for error detail if something failed.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Manual overrides (diff panel)
|
|
57
|
+
|
|
58
|
+
When you click a row, the diff panel shows per-field overrides for that item. These let you include an item but exclude specific sub-fields from the push.
|
|
59
|
+
|
|
60
|
+
### Tags
|
|
61
|
+
|
|
62
|
+
Uncheck a tag to exclude it. The destination will keep its existing value for that tag and the origin's other tags will still be pushed.
|
|
63
|
+
|
|
64
|
+
### Metadata keys
|
|
65
|
+
|
|
66
|
+
Each key in the entity's \`metadata\` object can be individually excluded. Useful when one cluster carries environment-specific metadata (e.g. an API base URL or a feature flag) that should not be overwritten.
|
|
67
|
+
|
|
68
|
+
### i18n paths
|
|
69
|
+
|
|
70
|
+
Individual translation paths can be excluded so the destination keeps its own localized strings for specific fields while receiving the rest of the entity update.
|
|
71
|
+
|
|
72
|
+
### Permissions (roles)
|
|
73
|
+
|
|
74
|
+
For role entities, individual permission entries (module/action pairs) can be excluded. Useful when destination clusters have different access policies for specific modules.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Ignoring items permanently
|
|
79
|
+
|
|
80
|
+
The ⊘ button on a release row permanently ignores that item for the origin cluster. Ignored items are excluded from this and all future releases for that origin, show an "Ignored" pill in the release list, and are not pushed even if their toggle is on.
|
|
81
|
+
|
|
82
|
+
The ⊘ button on a release row creates an ignore rule for that item, which excludes it immediately and refreshes the snapshot.
|
|
83
|
+
|
|
84
|
+
To remove an ignore, delete it from the Ignored tab. The item will reappear in any release draft the next time you refresh the snapshot.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Status tab
|
|
89
|
+
|
|
90
|
+
Shows a matrix of every entity in the origin cluster vs. every destination cluster. Cell states:
|
|
91
|
+
|
|
92
|
+
- match: origin and destination are identical
|
|
93
|
+
- diff: values differ
|
|
94
|
+
- translated: differs but a translation rule accounts for the difference (counts as match)
|
|
95
|
+
- missing: exists on origin, not on destination
|
|
96
|
+
- extra: exists on destination, not on origin
|
|
97
|
+
- skip: excluded from comparison
|
|
98
|
+
|
|
99
|
+
The Reference dropdown controls which cluster is treated as the source of truth.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Translations tab
|
|
104
|
+
|
|
105
|
+
Translation rules let you declare that two different values across clusters are intentionally equivalent. The Status matrix shows those cells as translated instead of diff.
|
|
106
|
+
|
|
107
|
+
A common use case: an API base URL that differs between dev and prod clusters. Without a translation rule, every blueprint referencing that URL shows as diff. With a rule mapping \`https://api.dev.example.com\` → \`https://api.prod.example.com\`, the diff is suppressed in the matrix.
|
|
108
|
+
|
|
109
|
+
Each rule has a name and a value per cluster. Leaving a cluster's field blank skips it for that pairing.
|
|
110
|
+
|
|
111
|
+
Translation rules affect both the Status matrix and releases. In the matrix they suppress diffs that are explained by a translation rule, showing the cell as translated instead of diff. In releases the substitutions are applied during push, so destination clusters receive the remapped values rather than the origin values verbatim.
|
|
112
|
+
|
|
113
|
+
### Systems with different aliases
|
|
114
|
+
|
|
115
|
+
If a system has a different alias on each cluster, add its aliases as a translation rule (the alias on each cluster) and imp will map them to the same system, so the Status matrix matches them instead of flagging missing/extra and rules that reference the system stop false-diffing.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Ignored tab
|
|
120
|
+
|
|
121
|
+
Lists all permanently-ignored items for the selected origin cluster. Removing a single item (trash icon) makes it reappear in future release snapshots. Clear all removes every ignore rule for that cluster at once.
|
|
122
|
+
|
|
123
|
+
After removing an ignore, refreshing an existing release draft will bring the item back.
|
|
124
|
+
`
|
|
125
|
+
});
|
|
126
|
+
function Gt({ open: t, onOpenChange: s, onCreated: i }) {
|
|
127
|
+
const a = Ue.get("Release", "apiPath", "/releases"), { toast: r } = oe(), { fetchJson: d } = te(), l = de(), { configs: m } = be(), [h, b] = R(""), [x, c] = R(""), [p, P] = R(""), [M, D] = R([]), Q = ["imaginarium", "releases", a], U = () => {
|
|
128
|
+
b(""), c(""), P(""), D([]);
|
|
129
|
+
}, j = q(
|
|
130
|
+
() => m.filter((g) => g.id !== p),
|
|
131
|
+
[m, p]
|
|
132
|
+
), Y = (g) => {
|
|
133
|
+
P(g), D((w) => w.filter((V) => V !== g));
|
|
134
|
+
}, B = (g) => {
|
|
135
|
+
D(
|
|
136
|
+
(w) => w.includes(g) ? w.filter((V) => V !== g) : [...w, g]
|
|
137
|
+
);
|
|
138
|
+
}, k = _({
|
|
139
|
+
mutationFn: async () => {
|
|
140
|
+
const g = await d(a, {
|
|
141
|
+
method: "POST",
|
|
142
|
+
body: JSON.stringify({
|
|
143
|
+
name: h.trim(),
|
|
144
|
+
description: x.trim() || null,
|
|
145
|
+
originConfigId: p,
|
|
146
|
+
targetConfigIds: M
|
|
147
|
+
})
|
|
148
|
+
});
|
|
149
|
+
return await d(`${a}/${g.id}/snapshot-from-compare`, {
|
|
150
|
+
method: "POST",
|
|
151
|
+
body: JSON.stringify({})
|
|
152
|
+
}), g;
|
|
153
|
+
},
|
|
154
|
+
onSuccess: (g) => {
|
|
155
|
+
l.invalidateQueries({ queryKey: Q }), r({ title: "Success", description: "Release created and snapshotted" }), s(!1), U(), i(g.id);
|
|
156
|
+
},
|
|
157
|
+
onError: (g) => {
|
|
158
|
+
r({ title: "Error", description: g.message, variant: "destructive" });
|
|
159
|
+
},
|
|
160
|
+
// Refetch regardless of outcome: if create succeeds but snapshot fails, the
|
|
161
|
+
// new release would otherwise be orphaned and missing from the list.
|
|
162
|
+
onSettled: () => {
|
|
163
|
+
l.invalidateQueries({ queryKey: Q });
|
|
164
|
+
}
|
|
165
|
+
}), C = (g) => {
|
|
166
|
+
g || U(), s(g);
|
|
167
|
+
}, $ = !!(h.trim() && p && M.length > 0);
|
|
168
|
+
return /* @__PURE__ */ e(ve, { open: t, onOpenChange: C, children: /* @__PURE__ */ n(we, { children: [
|
|
169
|
+
/* @__PURE__ */ n(ke, { children: [
|
|
170
|
+
/* @__PURE__ */ e(Ce, { children: "New Release" }),
|
|
171
|
+
/* @__PURE__ */ e(Te, { children: "Create a release from an origin cluster and snapshot the diff against its targets." })
|
|
172
|
+
] }),
|
|
173
|
+
/* @__PURE__ */ n("div", { className: "space-y-4 py-4", children: [
|
|
174
|
+
/* @__PURE__ */ n("div", { className: "space-y-2", children: [
|
|
175
|
+
/* @__PURE__ */ e(le, { htmlFor: "release-name", children: "Name" }),
|
|
176
|
+
/* @__PURE__ */ e(
|
|
177
|
+
ge,
|
|
178
|
+
{
|
|
179
|
+
id: "release-name",
|
|
180
|
+
value: h,
|
|
181
|
+
onChange: (g) => b(g.target.value),
|
|
182
|
+
placeholder: "2026.05 Release"
|
|
183
|
+
}
|
|
184
|
+
)
|
|
185
|
+
] }),
|
|
186
|
+
/* @__PURE__ */ n("div", { className: "space-y-2", children: [
|
|
187
|
+
/* @__PURE__ */ e(le, { htmlFor: "release-description", children: "Description (Optional)" }),
|
|
188
|
+
/* @__PURE__ */ e(
|
|
189
|
+
ge,
|
|
190
|
+
{
|
|
191
|
+
id: "release-description",
|
|
192
|
+
value: x,
|
|
193
|
+
onChange: (g) => c(g.target.value),
|
|
194
|
+
placeholder: "What this release contains"
|
|
195
|
+
}
|
|
196
|
+
)
|
|
197
|
+
] }),
|
|
198
|
+
/* @__PURE__ */ n("div", { className: "space-y-2", children: [
|
|
199
|
+
/* @__PURE__ */ e(le, { htmlFor: "release-origin", children: "Origin Cluster" }),
|
|
200
|
+
/* @__PURE__ */ n(
|
|
201
|
+
"select",
|
|
202
|
+
{
|
|
203
|
+
id: "release-origin",
|
|
204
|
+
value: p,
|
|
205
|
+
onChange: (g) => Y(g.target.value),
|
|
206
|
+
className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
|
|
207
|
+
children: [
|
|
208
|
+
/* @__PURE__ */ e("option", { value: "", children: "Select origin…" }),
|
|
209
|
+
m.map((g) => /* @__PURE__ */ e("option", { value: g.id, children: g.displayName }, g.id))
|
|
210
|
+
]
|
|
211
|
+
}
|
|
212
|
+
)
|
|
213
|
+
] }),
|
|
214
|
+
/* @__PURE__ */ n("div", { className: "space-y-2", children: [
|
|
215
|
+
/* @__PURE__ */ e(le, { children: "Target Clusters" }),
|
|
216
|
+
j.length > 0 ? /* @__PURE__ */ e("div", { className: "space-y-1 rounded-md border border-input p-2 max-h-48 overflow-y-auto", children: j.map((g) => /* @__PURE__ */ n("label", { className: "flex items-center gap-2 text-sm cursor-pointer", children: [
|
|
217
|
+
/* @__PURE__ */ e(
|
|
218
|
+
"input",
|
|
219
|
+
{
|
|
220
|
+
type: "checkbox",
|
|
221
|
+
checked: M.includes(g.id),
|
|
222
|
+
onChange: () => B(g.id)
|
|
223
|
+
}
|
|
224
|
+
),
|
|
225
|
+
g.displayName
|
|
226
|
+
] }, g.id)) }) : /* @__PURE__ */ e("p", { className: "text-xs text-muted-foreground", children: p ? "No other clusters available as targets." : "Select an origin first." })
|
|
227
|
+
] })
|
|
228
|
+
] }),
|
|
229
|
+
/* @__PURE__ */ n(Pe, { children: [
|
|
230
|
+
/* @__PURE__ */ n(E, { variant: "outline", onClick: () => C(!1), disabled: k.isPending, children: [
|
|
231
|
+
/* @__PURE__ */ e(Ne, { className: "w-4 h-4 mr-2" }),
|
|
232
|
+
"Cancel"
|
|
233
|
+
] }),
|
|
234
|
+
/* @__PURE__ */ e(E, { onClick: () => k.mutate(), disabled: !$ || k.isPending, children: k.isPending ? /* @__PURE__ */ n(ze, { children: [
|
|
235
|
+
/* @__PURE__ */ e(Ve, { className: "w-4 h-4 mr-2 animate-spin" }),
|
|
236
|
+
"Snapshotting…"
|
|
237
|
+
] }) : /* @__PURE__ */ n(ze, { children: [
|
|
238
|
+
/* @__PURE__ */ e(bt, { className: "w-4 h-4 mr-2" }),
|
|
239
|
+
"Create & snapshot"
|
|
240
|
+
] }) })
|
|
241
|
+
] })
|
|
242
|
+
] }) });
|
|
243
|
+
}
|
|
244
|
+
function kt({ status: t }) {
|
|
245
|
+
return /* @__PURE__ */ e("span", { className: `inline-flex items-center rounded px-1.5 py-0.5 text-xs font-medium border ${t === "pushed" ? "bg-emerald-500/15 text-emerald-700 dark:text-emerald-300 border-emerald-500/30" : "bg-muted text-muted-foreground border-border"}`, children: t });
|
|
246
|
+
}
|
|
247
|
+
function Xt({ onOpen: t }) {
|
|
248
|
+
const s = Ue.get("Release", "apiPath", "/releases"), { fetchJson: i } = te(), { configs: a } = be(), [r, d] = R(!1), l = ["imaginarium", "releases", s], { data: m, isLoading: h } = ae({
|
|
249
|
+
queryKey: l,
|
|
250
|
+
queryFn: async () => {
|
|
251
|
+
const c = await i(s);
|
|
252
|
+
return [...Array.isArray(c) ? c : (c == null ? void 0 : c.items) ?? []].sort((P, M) => (M.createdAt ?? "").localeCompare(P.createdAt ?? ""));
|
|
253
|
+
}
|
|
254
|
+
}), b = q(() => {
|
|
255
|
+
const c = /* @__PURE__ */ new Map();
|
|
256
|
+
return a.forEach((p) => c.set(String(p.id), p.displayName)), c;
|
|
257
|
+
}, [a]), x = (c) => b.get(c) ?? c;
|
|
258
|
+
return /* @__PURE__ */ n("div", { className: "space-y-4", children: [
|
|
259
|
+
/* @__PURE__ */ e("div", { className: "flex items-center justify-end", children: /* @__PURE__ */ n(E, { onClick: () => d(!0), children: [
|
|
260
|
+
/* @__PURE__ */ e(je, { className: "w-4 h-4 mr-2" }),
|
|
261
|
+
"New Release"
|
|
262
|
+
] }) }),
|
|
263
|
+
h ? /* @__PURE__ */ e("div", { className: "text-center text-muted-foreground", children: "Loading…" }) : m && m.length > 0 ? /* @__PURE__ */ e(Ae, { children: /* @__PURE__ */ e(Me, { className: "p-0", children: /* @__PURE__ */ n("table", { className: "w-full text-sm", children: [
|
|
264
|
+
/* @__PURE__ */ e("thead", { children: /* @__PURE__ */ n("tr", { className: "border-b text-left text-muted-foreground", children: [
|
|
265
|
+
/* @__PURE__ */ e("th", { className: "p-3 font-medium", children: "Name" }),
|
|
266
|
+
/* @__PURE__ */ e("th", { className: "p-3 font-medium", children: "Origin" }),
|
|
267
|
+
/* @__PURE__ */ e("th", { className: "p-3 font-medium", children: "Targets" }),
|
|
268
|
+
/* @__PURE__ */ e("th", { className: "p-3 font-medium", children: "Status" }),
|
|
269
|
+
/* @__PURE__ */ e("th", { className: "p-3 font-medium", children: "Snapshot" }),
|
|
270
|
+
/* @__PURE__ */ e("th", { className: "p-3 font-medium", children: "Pushed" }),
|
|
271
|
+
/* @__PURE__ */ e("th", { className: "p-3 font-medium" })
|
|
272
|
+
] }) }),
|
|
273
|
+
/* @__PURE__ */ e("tbody", { children: m.map((c) => /* @__PURE__ */ n(
|
|
274
|
+
"tr",
|
|
275
|
+
{
|
|
276
|
+
className: "border-b last:border-0 cursor-pointer hover:bg-muted/50",
|
|
277
|
+
onClick: () => t(c.id),
|
|
278
|
+
children: [
|
|
279
|
+
/* @__PURE__ */ n("td", { className: "p-3", children: [
|
|
280
|
+
/* @__PURE__ */ e("div", { className: "font-medium", children: c.name }),
|
|
281
|
+
c.description ? /* @__PURE__ */ e("div", { className: "text-xs text-muted-foreground", children: c.description }) : null
|
|
282
|
+
] }),
|
|
283
|
+
/* @__PURE__ */ e("td", { className: "p-3", children: x(c.originConfigId) }),
|
|
284
|
+
/* @__PURE__ */ e("td", { className: "p-3", children: /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-1", children: (c.targetConfigIds ?? []).map((p) => /* @__PURE__ */ e(
|
|
285
|
+
"span",
|
|
286
|
+
{
|
|
287
|
+
className: "inline-flex items-center rounded bg-muted px-1.5 py-0.5 text-xs",
|
|
288
|
+
children: x(p)
|
|
289
|
+
},
|
|
290
|
+
p
|
|
291
|
+
)) }) }),
|
|
292
|
+
/* @__PURE__ */ e("td", { className: "p-3", children: /* @__PURE__ */ e(kt, { status: c.status }) }),
|
|
293
|
+
/* @__PURE__ */ e("td", { className: "p-3 text-muted-foreground", children: c.snapshotAt ? new Date(c.snapshotAt).toLocaleString() : "—" }),
|
|
294
|
+
/* @__PURE__ */ e("td", { className: "p-3 text-muted-foreground", children: c.pushedAt ? new Date(c.pushedAt).toLocaleString() : "—" }),
|
|
295
|
+
/* @__PURE__ */ e("td", { className: "p-3 text-right", children: /* @__PURE__ */ e(
|
|
296
|
+
E,
|
|
297
|
+
{
|
|
298
|
+
variant: "ghost",
|
|
299
|
+
size: "sm",
|
|
300
|
+
onClick: (p) => {
|
|
301
|
+
p.stopPropagation(), t(c.id);
|
|
302
|
+
},
|
|
303
|
+
children: "Open →"
|
|
304
|
+
}
|
|
305
|
+
) })
|
|
306
|
+
]
|
|
307
|
+
},
|
|
308
|
+
c.id
|
|
309
|
+
)) })
|
|
310
|
+
] }) }) }) : /* @__PURE__ */ e(Ae, { children: /* @__PURE__ */ n(Me, { className: "py-12 text-center", children: [
|
|
311
|
+
/* @__PURE__ */ e("p", { className: "text-muted-foreground mb-4", children: "No releases yet" }),
|
|
312
|
+
/* @__PURE__ */ n(E, { onClick: () => d(!0), children: [
|
|
313
|
+
/* @__PURE__ */ e(je, { className: "w-4 h-4 mr-2" }),
|
|
314
|
+
"Create Your First Release"
|
|
315
|
+
] })
|
|
316
|
+
] }) }),
|
|
317
|
+
/* @__PURE__ */ e(
|
|
318
|
+
Gt,
|
|
319
|
+
{
|
|
320
|
+
open: r,
|
|
321
|
+
onOpenChange: d,
|
|
322
|
+
onCreated: t
|
|
323
|
+
}
|
|
324
|
+
)
|
|
325
|
+
] });
|
|
326
|
+
}
|
|
327
|
+
function Zt({
|
|
328
|
+
originName: t,
|
|
329
|
+
className: s
|
|
330
|
+
}) {
|
|
331
|
+
const i = t ? `Skipped in your last release from ${t}.` : "Skipped in your last release.";
|
|
332
|
+
return /* @__PURE__ */ e(Ut, { children: /* @__PURE__ */ n(Ht, { children: [
|
|
333
|
+
/* @__PURE__ */ e(_t, { asChild: !0, children: /* @__PURE__ */ e(
|
|
334
|
+
"span",
|
|
335
|
+
{
|
|
336
|
+
className: ce(
|
|
337
|
+
"inline-flex items-center rounded px-1.5 py-0.5 text-xs font-medium",
|
|
338
|
+
"bg-muted text-muted-foreground cursor-default select-none",
|
|
339
|
+
s
|
|
340
|
+
),
|
|
341
|
+
children: "previously skipped"
|
|
342
|
+
}
|
|
343
|
+
) }),
|
|
344
|
+
/* @__PURE__ */ e(Yt, { side: "top", children: i })
|
|
345
|
+
] }) });
|
|
346
|
+
}
|
|
347
|
+
function en({ className: t }) {
|
|
348
|
+
return /* @__PURE__ */ e(
|
|
349
|
+
"span",
|
|
350
|
+
{
|
|
351
|
+
className: ce(
|
|
352
|
+
"inline-flex items-center rounded px-1.5 py-0.5 text-xs font-medium",
|
|
353
|
+
"bg-red-500/10 text-red-600 dark:text-red-400 border border-red-500/25",
|
|
354
|
+
t
|
|
355
|
+
),
|
|
356
|
+
children: "ignored"
|
|
357
|
+
}
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
function tn({
|
|
361
|
+
ignoreRule: t,
|
|
362
|
+
createPayload: s,
|
|
363
|
+
apiPath: i = "/release-ignores",
|
|
364
|
+
onChange: a,
|
|
365
|
+
className: r
|
|
366
|
+
}) {
|
|
367
|
+
const { toast: d } = oe(), { fetchJson: l } = te(), m = de(), [h, b] = R(!1), x = !!t, c = () => {
|
|
368
|
+
m.invalidateQueries({ queryKey: ["imaginarium", "release-ignores"] }), a == null || a();
|
|
369
|
+
}, p = _({
|
|
370
|
+
mutationFn: () => l(i, {
|
|
371
|
+
method: "POST",
|
|
372
|
+
body: JSON.stringify(s)
|
|
373
|
+
}),
|
|
374
|
+
onSuccess: () => {
|
|
375
|
+
d({ title: "Item ignored", description: "Will be excluded from all future snapshots." }), b(!1), c();
|
|
376
|
+
},
|
|
377
|
+
onError: (D) => {
|
|
378
|
+
d({ title: "Error", description: D.message, variant: "destructive" });
|
|
379
|
+
}
|
|
380
|
+
}), P = _({
|
|
381
|
+
mutationFn: () => l(`${i}/${t.id}`, { method: "DELETE" }),
|
|
382
|
+
onSuccess: () => {
|
|
383
|
+
d({ title: "Item un-ignored", description: "Will appear normally in future snapshots." }), c();
|
|
384
|
+
},
|
|
385
|
+
onError: (D) => {
|
|
386
|
+
d({ title: "Error", description: D.message, variant: "destructive" });
|
|
387
|
+
}
|
|
388
|
+
}), M = p.isPending || P.isPending;
|
|
389
|
+
return /* @__PURE__ */ n(ze, { children: [
|
|
390
|
+
/* @__PURE__ */ e(
|
|
391
|
+
E,
|
|
392
|
+
{
|
|
393
|
+
variant: "ghost",
|
|
394
|
+
size: "icon",
|
|
395
|
+
title: x ? "Remove from ignore list" : "Ignore this item",
|
|
396
|
+
disabled: M,
|
|
397
|
+
onClick: () => x ? P.mutate() : b(!0),
|
|
398
|
+
className: ce(x && "text-red-500 hover:text-red-500 dark:text-red-400 dark:hover:text-red-400", r),
|
|
399
|
+
children: /* @__PURE__ */ e(Be, {})
|
|
400
|
+
}
|
|
401
|
+
),
|
|
402
|
+
/* @__PURE__ */ e(ve, { open: h, onOpenChange: b, children: /* @__PURE__ */ n(we, { children: [
|
|
403
|
+
/* @__PURE__ */ n(ke, { children: [
|
|
404
|
+
/* @__PURE__ */ e(Ce, { children: "Ignore this item?" }),
|
|
405
|
+
/* @__PURE__ */ n(Te, { children: [
|
|
406
|
+
"Ignoring excludes this item from ",
|
|
407
|
+
/* @__PURE__ */ e("strong", { children: "this and all future releases" }),
|
|
408
|
+
" for this origin cluster — it will never be pushed to any destination. You can un-ignore it later from the Ignored tab."
|
|
409
|
+
] })
|
|
410
|
+
] }),
|
|
411
|
+
/* @__PURE__ */ n(Pe, { children: [
|
|
412
|
+
/* @__PURE__ */ e(
|
|
413
|
+
E,
|
|
414
|
+
{
|
|
415
|
+
variant: "outline",
|
|
416
|
+
onClick: () => b(!1),
|
|
417
|
+
disabled: p.isPending,
|
|
418
|
+
children: "Cancel"
|
|
419
|
+
}
|
|
420
|
+
),
|
|
421
|
+
/* @__PURE__ */ n(
|
|
422
|
+
E,
|
|
423
|
+
{
|
|
424
|
+
variant: "destructive",
|
|
425
|
+
onClick: () => p.mutate(),
|
|
426
|
+
disabled: p.isPending,
|
|
427
|
+
children: [
|
|
428
|
+
/* @__PURE__ */ e(Be, { className: "w-4 h-4 mr-2" }),
|
|
429
|
+
"Ignore item"
|
|
430
|
+
]
|
|
431
|
+
}
|
|
432
|
+
)
|
|
433
|
+
] })
|
|
434
|
+
] }) })
|
|
435
|
+
] });
|
|
436
|
+
}
|
|
437
|
+
function nn({
|
|
438
|
+
releaseId: t,
|
|
439
|
+
apiPath: s = "/releases",
|
|
440
|
+
onReset: i
|
|
441
|
+
}) {
|
|
442
|
+
const { toast: a } = oe(), { fetchJson: r } = te(), d = de(), l = _({
|
|
443
|
+
mutationFn: () => r(`${s}/${t}/reset-exclusions`, {
|
|
444
|
+
method: "POST"
|
|
445
|
+
}),
|
|
446
|
+
onSuccess: (m) => {
|
|
447
|
+
d.invalidateQueries({ queryKey: ["imaginarium", "release-items", t] }), a({
|
|
448
|
+
title: "Exclusions reset",
|
|
449
|
+
description: `${m.reset} item${m.reset === 1 ? "" : "s"} re-enabled.`
|
|
450
|
+
}), i == null || i(m.reset);
|
|
451
|
+
},
|
|
452
|
+
onError: (m) => {
|
|
453
|
+
a({ title: "Error", description: m.message, variant: "destructive" });
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
return /* @__PURE__ */ n(
|
|
457
|
+
E,
|
|
458
|
+
{
|
|
459
|
+
variant: "outline",
|
|
460
|
+
size: "sm",
|
|
461
|
+
onClick: () => l.mutate(),
|
|
462
|
+
disabled: l.isPending,
|
|
463
|
+
children: [
|
|
464
|
+
/* @__PURE__ */ e(zt, {}),
|
|
465
|
+
l.isPending ? "Resetting…" : "Reset exclusions"
|
|
466
|
+
]
|
|
467
|
+
}
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
function De({ label: t, value: s, highlightLines: i }) {
|
|
471
|
+
return /* @__PURE__ */ n("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
472
|
+
/* @__PURE__ */ e("div", { className: "mb-1 text-xs font-medium text-muted-foreground", children: t }),
|
|
473
|
+
/* @__PURE__ */ e("pre", { className: "flex-1 overflow-auto rounded border bg-muted/30 p-3 text-xs", children: i === void 0 ? s === void 0 ? "null" : JSON.stringify(s, null, 2) : (s === void 0 ? "null" : JSON.stringify(s, null, 2)).split(`
|
|
474
|
+
`).map((a, r) => (
|
|
475
|
+
// eslint-disable-next-line react/no-array-index-key
|
|
476
|
+
/* @__PURE__ */ e(
|
|
477
|
+
"div",
|
|
478
|
+
{
|
|
479
|
+
className: i[r] ? "bg-yellow-200/70 text-yellow-950 dark:bg-yellow-400/20 dark:text-yellow-100" : void 0,
|
|
480
|
+
children: a === "" ? " " : a
|
|
481
|
+
},
|
|
482
|
+
r
|
|
483
|
+
)
|
|
484
|
+
)) })
|
|
485
|
+
] });
|
|
486
|
+
}
|
|
487
|
+
function st(t) {
|
|
488
|
+
return t === void 0 ? "null" : JSON.stringify(t, null, 2);
|
|
489
|
+
}
|
|
490
|
+
function Ct(t, s, i) {
|
|
491
|
+
let a = st(t);
|
|
492
|
+
if (i && i.length > 0)
|
|
493
|
+
for (const { replace: p, with: P } of i)
|
|
494
|
+
p && (a = a.split(p).join(P));
|
|
495
|
+
const r = a.split(`
|
|
496
|
+
`), d = st(s).split(`
|
|
497
|
+
`), l = r.length, m = d.length, h = Array.from({ length: l + 1 }, () => new Array(m + 1).fill(0));
|
|
498
|
+
for (let p = l - 1; p >= 0; p -= 1)
|
|
499
|
+
for (let P = m - 1; P >= 0; P -= 1)
|
|
500
|
+
h[p][P] = r[p] === d[P] ? h[p + 1][P + 1] + 1 : Math.max(h[p + 1][P], h[p][P + 1]);
|
|
501
|
+
const b = new Array(l).fill(!0);
|
|
502
|
+
let x = 0, c = 0;
|
|
503
|
+
for (; x < l && c < m; )
|
|
504
|
+
r[x] === d[c] ? (b[x] = !1, x += 1, c += 1) : h[x + 1][c] >= h[x][c + 1] ? x += 1 : c += 1;
|
|
505
|
+
return b;
|
|
506
|
+
}
|
|
507
|
+
function Oe({
|
|
508
|
+
title: t,
|
|
509
|
+
values: s,
|
|
510
|
+
excluded: i,
|
|
511
|
+
editable: a,
|
|
512
|
+
onToggle: r,
|
|
513
|
+
formatLabel: d
|
|
514
|
+
}) {
|
|
515
|
+
const [l, m] = R(i.length > 0);
|
|
516
|
+
return Qe(() => {
|
|
517
|
+
i.length > 0 && m(!0);
|
|
518
|
+
}, [i.length]), /* @__PURE__ */ n("div", { className: "border-b p-2", children: [
|
|
519
|
+
/* @__PURE__ */ n(
|
|
520
|
+
"button",
|
|
521
|
+
{
|
|
522
|
+
type: "button",
|
|
523
|
+
className: "flex w-full items-center justify-between gap-2",
|
|
524
|
+
onClick: () => m((h) => !h),
|
|
525
|
+
"aria-expanded": l,
|
|
526
|
+
children: [
|
|
527
|
+
/* @__PURE__ */ n("span", { className: "flex items-center gap-1 text-xs font-medium text-muted-foreground", children: [
|
|
528
|
+
l ? /* @__PURE__ */ e(ue, { size: 12 }) : /* @__PURE__ */ e(he, { size: 12 }),
|
|
529
|
+
t,
|
|
530
|
+
" (",
|
|
531
|
+
i.length,
|
|
532
|
+
")"
|
|
533
|
+
] }),
|
|
534
|
+
a ? null : /* @__PURE__ */ e("span", { className: "text-[10px] text-muted-foreground", children: "read-only" })
|
|
535
|
+
]
|
|
536
|
+
}
|
|
537
|
+
),
|
|
538
|
+
l ? /* @__PURE__ */ e("div", { className: "mt-1 flex flex-col gap-1", children: s.map((h) => {
|
|
539
|
+
const b = !i.includes(h);
|
|
540
|
+
return /* @__PURE__ */ n(
|
|
541
|
+
"label",
|
|
542
|
+
{
|
|
543
|
+
className: "flex items-start gap-2 text-xs",
|
|
544
|
+
children: [
|
|
545
|
+
/* @__PURE__ */ e(
|
|
546
|
+
"input",
|
|
547
|
+
{
|
|
548
|
+
type: "checkbox",
|
|
549
|
+
className: "mt-0.5 shrink-0",
|
|
550
|
+
checked: b,
|
|
551
|
+
disabled: !a,
|
|
552
|
+
onChange: (x) => r == null ? void 0 : r(h, x.target.checked)
|
|
553
|
+
}
|
|
554
|
+
),
|
|
555
|
+
/* @__PURE__ */ e("span", { className: `min-w-0 break-all font-mono ${b ? "" : "text-muted-foreground line-through"}`, children: d ? d(h) : h })
|
|
556
|
+
]
|
|
557
|
+
},
|
|
558
|
+
h
|
|
559
|
+
);
|
|
560
|
+
}) }) : null
|
|
561
|
+
] });
|
|
562
|
+
}
|
|
563
|
+
function sn({
|
|
564
|
+
item: t,
|
|
565
|
+
targets: s,
|
|
566
|
+
onClose: i,
|
|
567
|
+
unmetDependencyNames: a = [],
|
|
568
|
+
tags: r = [],
|
|
569
|
+
excludedTags: d = [],
|
|
570
|
+
editable: l = !0,
|
|
571
|
+
onToggleTag: m,
|
|
572
|
+
metadataKeys: h = [],
|
|
573
|
+
excludedMetadataKeys: b = [],
|
|
574
|
+
onToggleMetadataKey: x,
|
|
575
|
+
i18nPaths: c = [],
|
|
576
|
+
excludedI18nPaths: p = [],
|
|
577
|
+
onToggleI18nPath: P,
|
|
578
|
+
permissionKeys: M = [],
|
|
579
|
+
excludedPermissions: D = [],
|
|
580
|
+
onTogglePermission: Q,
|
|
581
|
+
formatPermissionLabel: U,
|
|
582
|
+
replacementMaps: j
|
|
583
|
+
}) {
|
|
584
|
+
var X, f, F, J;
|
|
585
|
+
const Y = ((X = s[0]) == null ? void 0 : X.id) ?? null, [B, k] = R(Y);
|
|
586
|
+
Qe(() => {
|
|
587
|
+
var A;
|
|
588
|
+
k(((A = s[0]) == null ? void 0 : A.id) ?? null);
|
|
589
|
+
}, [t == null ? void 0 : t.id]);
|
|
590
|
+
const C = s.find((A) => A.id === B) ?? s[0] ?? null, $ = (f = t == null ? void 0 : t.diff) == null ? void 0 : f.byTarget, g = $ != null, w = g ? $[(C == null ? void 0 : C.id) ?? ""] : (F = t == null ? void 0 : t.diff) == null ? void 0 : F.target, V = g && C != null && !(C.id in $), L = q(
|
|
591
|
+
() => {
|
|
592
|
+
var A;
|
|
593
|
+
return V ? void 0 : Ct((A = t == null ? void 0 : t.diff) == null ? void 0 : A.origin, w, j == null ? void 0 : j[(C == null ? void 0 : C.id) ?? ""]);
|
|
594
|
+
},
|
|
595
|
+
[t, w, V, j, C == null ? void 0 : C.id]
|
|
596
|
+
);
|
|
597
|
+
return t ? /* @__PURE__ */ n("div", { className: "flex h-full flex-col rounded-md border bg-background", children: [
|
|
598
|
+
/* @__PURE__ */ n("div", { className: "flex items-center justify-between border-b p-3", children: [
|
|
599
|
+
/* @__PURE__ */ n("div", { className: "min-w-0", children: [
|
|
600
|
+
/* @__PURE__ */ e("div", { className: "truncate font-medium", children: t.itemName }),
|
|
601
|
+
/* @__PURE__ */ e("div", { className: "font-mono text-xs text-muted-foreground", children: t.itemType })
|
|
602
|
+
] }),
|
|
603
|
+
/* @__PURE__ */ e(E, { variant: "ghost", size: "icon", title: "Close", onClick: i, children: /* @__PURE__ */ e(Ne, {}) })
|
|
604
|
+
] }),
|
|
605
|
+
a.length > 0 ? /* @__PURE__ */ n("div", { className: "flex items-start gap-2 border-b bg-amber-50 p-2 text-xs text-amber-700 dark:bg-amber-500/10 dark:text-amber-300", children: [
|
|
606
|
+
/* @__PURE__ */ e(ye, { size: 14, className: "mt-0.5 shrink-0 text-amber-600 dark:text-amber-400" }),
|
|
607
|
+
/* @__PURE__ */ n("span", { children: [
|
|
608
|
+
"Depends on excluded items: ",
|
|
609
|
+
a.join(", "),
|
|
610
|
+
". Push will fail for this item until they're included."
|
|
611
|
+
] })
|
|
612
|
+
] }) : null,
|
|
613
|
+
r.length > 0 ? /* @__PURE__ */ e(
|
|
614
|
+
Oe,
|
|
615
|
+
{
|
|
616
|
+
title: "Tag Overrides",
|
|
617
|
+
values: r,
|
|
618
|
+
excluded: d,
|
|
619
|
+
editable: l,
|
|
620
|
+
onToggle: m
|
|
621
|
+
}
|
|
622
|
+
) : null,
|
|
623
|
+
h.length > 0 ? /* @__PURE__ */ e(
|
|
624
|
+
Oe,
|
|
625
|
+
{
|
|
626
|
+
title: "Metadata Overrides",
|
|
627
|
+
values: h,
|
|
628
|
+
excluded: b,
|
|
629
|
+
editable: l,
|
|
630
|
+
onToggle: x
|
|
631
|
+
}
|
|
632
|
+
) : null,
|
|
633
|
+
c.length > 0 ? /* @__PURE__ */ e(
|
|
634
|
+
Oe,
|
|
635
|
+
{
|
|
636
|
+
title: "Translation Overrides",
|
|
637
|
+
values: c,
|
|
638
|
+
excluded: p,
|
|
639
|
+
editable: l,
|
|
640
|
+
onToggle: P
|
|
641
|
+
}
|
|
642
|
+
) : null,
|
|
643
|
+
M.length > 0 ? /* @__PURE__ */ e(
|
|
644
|
+
Oe,
|
|
645
|
+
{
|
|
646
|
+
title: "Permission Overrides",
|
|
647
|
+
values: M,
|
|
648
|
+
excluded: D,
|
|
649
|
+
editable: l,
|
|
650
|
+
onToggle: Q,
|
|
651
|
+
formatLabel: U
|
|
652
|
+
}
|
|
653
|
+
) : null,
|
|
654
|
+
s.length > 0 ? /* @__PURE__ */ e("div", { className: "flex flex-wrap gap-1 border-b p-2", children: s.map((A) => {
|
|
655
|
+
const H = g && !(A.id in $);
|
|
656
|
+
return /* @__PURE__ */ n(
|
|
657
|
+
"button",
|
|
658
|
+
{
|
|
659
|
+
type: "button",
|
|
660
|
+
onClick: () => k(A.id),
|
|
661
|
+
className: `inline-flex items-center gap-1 rounded px-2 py-1 text-xs ${A.id === (C == null ? void 0 : C.id) ? "bg-muted font-medium" : "hover:bg-muted/50"}`,
|
|
662
|
+
children: [
|
|
663
|
+
H ? /* @__PURE__ */ e(Nt, { size: 12, className: "text-green-600" }) : /* @__PURE__ */ e("span", { className: "h-1.5 w-1.5 shrink-0 rounded-full bg-red-500", "aria-hidden": !0 }),
|
|
664
|
+
A.name
|
|
665
|
+
]
|
|
666
|
+
},
|
|
667
|
+
A.id
|
|
668
|
+
);
|
|
669
|
+
}) }) : null,
|
|
670
|
+
/* @__PURE__ */ n("div", { className: "flex flex-1 gap-3 overflow-auto p-3", children: [
|
|
671
|
+
/* @__PURE__ */ e(De, { label: "Origin", value: (J = t.diff) == null ? void 0 : J.origin, highlightLines: L }),
|
|
672
|
+
V ? /* @__PURE__ */ n("div", { className: "flex min-w-0 flex-1 items-center justify-center rounded border bg-muted/30 p-3 text-xs text-muted-foreground", children: [
|
|
673
|
+
"Matches ",
|
|
674
|
+
C == null ? void 0 : C.name,
|
|
675
|
+
" — no differences."
|
|
676
|
+
] }) : /* @__PURE__ */ e(De, { label: (C == null ? void 0 : C.name) ?? "Target", value: w })
|
|
677
|
+
] })
|
|
678
|
+
] }) : null;
|
|
679
|
+
}
|
|
680
|
+
const at = [
|
|
681
|
+
"blueprint",
|
|
682
|
+
"system",
|
|
683
|
+
"network",
|
|
684
|
+
"enum",
|
|
685
|
+
"resourceEnum",
|
|
686
|
+
// Device Control
|
|
687
|
+
"timer",
|
|
688
|
+
"messageRoute",
|
|
689
|
+
// Flow
|
|
690
|
+
"role",
|
|
691
|
+
"permission",
|
|
692
|
+
"module",
|
|
693
|
+
// Permissions
|
|
694
|
+
"scenario",
|
|
695
|
+
"template",
|
|
696
|
+
// Application Controls
|
|
697
|
+
"project",
|
|
698
|
+
"rule",
|
|
699
|
+
"script"
|
|
700
|
+
// Project
|
|
701
|
+
];
|
|
702
|
+
function Fe(t) {
|
|
703
|
+
const s = at.indexOf(t);
|
|
704
|
+
return s === -1 ? at.length : s;
|
|
705
|
+
}
|
|
706
|
+
function Je(t, s) {
|
|
707
|
+
const i = Fe(t) - Fe(s);
|
|
708
|
+
return i !== 0 ? i : t.localeCompare(s);
|
|
709
|
+
}
|
|
710
|
+
const Re = {
|
|
711
|
+
create: "text-emerald-600",
|
|
712
|
+
update: "text-amber-600",
|
|
713
|
+
remove: "text-destructive"
|
|
714
|
+
};
|
|
715
|
+
function it(t) {
|
|
716
|
+
const s = t.indexOf(":");
|
|
717
|
+
return s >= 0 ? { type: t.slice(0, s), name: t.slice(s + 1) } : { type: "", name: t };
|
|
718
|
+
}
|
|
719
|
+
function an(t) {
|
|
720
|
+
const s = /* @__PURE__ */ new Map(), i = (a, r, d) => {
|
|
721
|
+
let l = s.get(a);
|
|
722
|
+
return l || (l = { key: a, type: r, name: d, children: [] }, s.set(a, l)), l;
|
|
723
|
+
};
|
|
724
|
+
for (const a of t)
|
|
725
|
+
if (a.parentKey) {
|
|
726
|
+
const r = it(a.parentKey);
|
|
727
|
+
i(a.parentKey, r.type, r.name).children.push(a);
|
|
728
|
+
} else {
|
|
729
|
+
const r = i(a.itemKey, a.itemType, a.itemName || it(a.itemKey).name);
|
|
730
|
+
r.type = a.itemType, r.name = a.itemName || r.name, r.self = a;
|
|
731
|
+
}
|
|
732
|
+
return [...s.values()].sort(
|
|
733
|
+
(a, r) => Fe(a.type) - Fe(r.type) || a.name.localeCompare(r.name)
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
function rn(t, s, i, a) {
|
|
737
|
+
const { fetchJson: r } = te();
|
|
738
|
+
return ae({
|
|
739
|
+
queryKey: ["imaginarium", "release-push-preview", t, s],
|
|
740
|
+
queryFn: () => r(`${i}/${t}/push-preview`, {
|
|
741
|
+
method: "POST",
|
|
742
|
+
body: JSON.stringify({ destConfigIds: s })
|
|
743
|
+
}),
|
|
744
|
+
enabled: a,
|
|
745
|
+
// The dialog recomputes on every open (see refetch-on-open), so don't also
|
|
746
|
+
// auto-refetch on enable — that would double the (slow) compare.
|
|
747
|
+
staleTime: 1 / 0,
|
|
748
|
+
gcTime: 0
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
function ln({ summary: t }) {
|
|
752
|
+
return /* @__PURE__ */ n("span", { className: "text-xs", children: [
|
|
753
|
+
/* @__PURE__ */ n("span", { className: Re.create, children: [
|
|
754
|
+
t.create,
|
|
755
|
+
" create"
|
|
756
|
+
] }),
|
|
757
|
+
" · ",
|
|
758
|
+
/* @__PURE__ */ n("span", { className: Re.update, children: [
|
|
759
|
+
t.update,
|
|
760
|
+
" update"
|
|
761
|
+
] }),
|
|
762
|
+
" · ",
|
|
763
|
+
/* @__PURE__ */ n("span", { className: Re.remove, children: [
|
|
764
|
+
t.remove,
|
|
765
|
+
" remove"
|
|
766
|
+
] })
|
|
767
|
+
] });
|
|
768
|
+
}
|
|
769
|
+
function rt({ action: t }) {
|
|
770
|
+
return /* @__PURE__ */ e("span", { className: `font-mono text-xs uppercase ${Re[t] ?? ""}`, children: t });
|
|
771
|
+
}
|
|
772
|
+
function on() {
|
|
773
|
+
return /* @__PURE__ */ e("span", { className: "font-mono text-xs uppercase text-muted-foreground", children: "no_update" });
|
|
774
|
+
}
|
|
775
|
+
function dn({ preview: t, loading: s, error: i, onSelectItem: a }) {
|
|
776
|
+
if (s)
|
|
777
|
+
return /* @__PURE__ */ n("p", { className: "mt-1 inline-flex items-center gap-1 text-xs text-muted-foreground", children: [
|
|
778
|
+
/* @__PURE__ */ e(Ve, { className: "h-3 w-3 animate-spin" }),
|
|
779
|
+
" Computing changes…"
|
|
780
|
+
] });
|
|
781
|
+
if (t != null && t.error)
|
|
782
|
+
return /* @__PURE__ */ n("p", { className: "mt-1 text-xs text-destructive", children: [
|
|
783
|
+
"Couldn’t compute changes: ",
|
|
784
|
+
t.error
|
|
785
|
+
] });
|
|
786
|
+
if (i && !t)
|
|
787
|
+
return /* @__PURE__ */ e("p", { className: "mt-1 text-xs text-destructive", children: "Couldn’t compute changes for this target." });
|
|
788
|
+
if (!t || !t.summary)
|
|
789
|
+
return null;
|
|
790
|
+
if (t.summary.total === 0)
|
|
791
|
+
return /* @__PURE__ */ e("p", { className: "mt-1 text-xs text-muted-foreground", children: "No changes — already up to date." });
|
|
792
|
+
const r = an(t.items ?? []);
|
|
793
|
+
return /* @__PURE__ */ n("div", { className: "mt-1", children: [
|
|
794
|
+
/* @__PURE__ */ e(ln, { summary: t.summary }),
|
|
795
|
+
/* @__PURE__ */ e("div", { className: "mt-2 max-h-[55vh] space-y-3 overflow-auto border-t pt-2", children: r.map((d) => /* @__PURE__ */ n("div", { children: [
|
|
796
|
+
/* @__PURE__ */ n("div", { className: "flex items-baseline gap-2", children: [
|
|
797
|
+
d.self ? /* @__PURE__ */ e(rt, { action: d.self.action }) : /* @__PURE__ */ e(on, {}),
|
|
798
|
+
d.self && a ? /* @__PURE__ */ e(
|
|
799
|
+
"button",
|
|
800
|
+
{
|
|
801
|
+
type: "button",
|
|
802
|
+
className: "text-sm font-medium hover:underline",
|
|
803
|
+
onClick: () => a(d.self),
|
|
804
|
+
children: d.name
|
|
805
|
+
}
|
|
806
|
+
) : /* @__PURE__ */ e("span", { className: "text-sm font-medium", children: d.name }),
|
|
807
|
+
/* @__PURE__ */ e("span", { className: "text-xs text-muted-foreground", children: d.type })
|
|
808
|
+
] }),
|
|
809
|
+
d.children.length > 0 ? /* @__PURE__ */ e("ul", { className: "ml-4 mt-0.5 space-y-0.5 border-l pl-3", children: d.children.map((l, m) => /* @__PURE__ */ n("li", { className: "text-xs", children: [
|
|
810
|
+
/* @__PURE__ */ e(rt, { action: l.action }),
|
|
811
|
+
" ",
|
|
812
|
+
a ? /* @__PURE__ */ e("button", { type: "button", className: "hover:underline", onClick: () => a(l), children: l.itemName || l.itemKey }) : /* @__PURE__ */ e("span", { children: l.itemName || l.itemKey }),
|
|
813
|
+
l.itemType !== "attribute" ? /* @__PURE__ */ n("span", { className: "text-muted-foreground", children: [
|
|
814
|
+
" (",
|
|
815
|
+
l.itemType,
|
|
816
|
+
")"
|
|
817
|
+
] }) : null
|
|
818
|
+
] }, `${l.itemKey}-${m}`)) }) : null
|
|
819
|
+
] }, d.key)) })
|
|
820
|
+
] });
|
|
821
|
+
}
|
|
822
|
+
function Tt({
|
|
823
|
+
releaseId: t,
|
|
824
|
+
destConfigId: s,
|
|
825
|
+
name: i,
|
|
826
|
+
apiPath: a = "/releases",
|
|
827
|
+
onSelectItem: r,
|
|
828
|
+
headerRight: d,
|
|
829
|
+
footer: l,
|
|
830
|
+
defaultOpen: m = !1
|
|
831
|
+
}) {
|
|
832
|
+
var P, M, D, Q;
|
|
833
|
+
const [h, b] = R(m), x = q(() => [s], [s]), c = rn(t, x, a, h), p = ((M = (P = c.data) == null ? void 0 : P.previews) == null ? void 0 : M.find((U) => U.destConfigId === s)) ?? ((Q = (D = c.data) == null ? void 0 : D.previews) == null ? void 0 : Q[0]);
|
|
834
|
+
return /* @__PURE__ */ n("div", { className: "rounded border", children: [
|
|
835
|
+
/* @__PURE__ */ n("div", { className: "flex items-center justify-between px-3 py-2", children: [
|
|
836
|
+
/* @__PURE__ */ n(
|
|
837
|
+
"button",
|
|
838
|
+
{
|
|
839
|
+
type: "button",
|
|
840
|
+
className: "flex min-w-0 items-center gap-1 text-sm font-medium",
|
|
841
|
+
onClick: () => b((U) => !U),
|
|
842
|
+
children: [
|
|
843
|
+
h ? /* @__PURE__ */ e(ue, { className: "h-4 w-4 shrink-0" }) : /* @__PURE__ */ e(he, { className: "h-4 w-4 shrink-0" }),
|
|
844
|
+
/* @__PURE__ */ e("span", { className: "truncate", children: i })
|
|
845
|
+
]
|
|
846
|
+
}
|
|
847
|
+
),
|
|
848
|
+
d
|
|
849
|
+
] }),
|
|
850
|
+
h ? /* @__PURE__ */ n("div", { className: "border-t px-3 py-2", children: [
|
|
851
|
+
/* @__PURE__ */ e(
|
|
852
|
+
dn,
|
|
853
|
+
{
|
|
854
|
+
preview: p,
|
|
855
|
+
loading: c.isFetching,
|
|
856
|
+
error: c.isError,
|
|
857
|
+
onSelectItem: r
|
|
858
|
+
}
|
|
859
|
+
),
|
|
860
|
+
l
|
|
861
|
+
] }) : null
|
|
862
|
+
] });
|
|
863
|
+
}
|
|
864
|
+
function cn({ state: t }) {
|
|
865
|
+
switch (t.status) {
|
|
866
|
+
case "pushing":
|
|
867
|
+
return /* @__PURE__ */ n("span", { className: "inline-flex items-center gap-1 text-sm text-muted-foreground", children: [
|
|
868
|
+
/* @__PURE__ */ e(Ve, { className: "h-4 w-4 animate-spin" }),
|
|
869
|
+
"Pushing…"
|
|
870
|
+
] });
|
|
871
|
+
case "success":
|
|
872
|
+
return /* @__PURE__ */ n("span", { className: "inline-flex items-center gap-1 text-sm text-emerald-600", children: [
|
|
873
|
+
/* @__PURE__ */ e(Nt, { className: "h-4 w-4" }),
|
|
874
|
+
"Success"
|
|
875
|
+
] });
|
|
876
|
+
case "partial":
|
|
877
|
+
return /* @__PURE__ */ n("span", { className: "inline-flex items-center gap-1 text-sm text-amber-600", children: [
|
|
878
|
+
/* @__PURE__ */ e(ye, { className: "h-4 w-4" }),
|
|
879
|
+
"Partial — ",
|
|
880
|
+
t.failed ?? 0,
|
|
881
|
+
" failed"
|
|
882
|
+
] });
|
|
883
|
+
case "failed":
|
|
884
|
+
return /* @__PURE__ */ n(
|
|
885
|
+
"span",
|
|
886
|
+
{
|
|
887
|
+
className: "inline-flex items-center gap-1 text-sm text-destructive",
|
|
888
|
+
title: t.error,
|
|
889
|
+
children: [
|
|
890
|
+
/* @__PURE__ */ e(Ne, { className: "h-4 w-4" }),
|
|
891
|
+
"Failed"
|
|
892
|
+
]
|
|
893
|
+
}
|
|
894
|
+
);
|
|
895
|
+
default:
|
|
896
|
+
return /* @__PURE__ */ n("span", { className: "inline-flex items-center gap-1 text-sm text-muted-foreground", children: [
|
|
897
|
+
/* @__PURE__ */ e(Bt, { className: "h-3 w-3" }),
|
|
898
|
+
"Pending"
|
|
899
|
+
] });
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
function mn({
|
|
903
|
+
open: t,
|
|
904
|
+
onOpenChange: s,
|
|
905
|
+
releaseId: i,
|
|
906
|
+
targetConfigIds: a,
|
|
907
|
+
targetNames: r,
|
|
908
|
+
apiPath: d = "/releases",
|
|
909
|
+
onComplete: l,
|
|
910
|
+
dependencyWarnings: m = []
|
|
911
|
+
}) {
|
|
912
|
+
const { toast: h } = oe(), { fetchJson: b } = te(), x = de(), [c, p] = R(!1), [P, M] = R({}), [D, Q] = R(!1), U = (k) => (r == null ? void 0 : r[k]) ?? k, j = (k, C) => M(($) => ({ ...$, [k]: C })), Y = async () => {
|
|
913
|
+
p(!0), Q(!1), M(Object.fromEntries(a.map(($) => [$, { status: "idle" }])));
|
|
914
|
+
let k = 0, C = 0;
|
|
915
|
+
for (const $ of a) {
|
|
916
|
+
j($, { status: "pushing" });
|
|
917
|
+
try {
|
|
918
|
+
const g = await b(`${d}/${i}/push`, {
|
|
919
|
+
method: "POST",
|
|
920
|
+
body: JSON.stringify({ destConfigId: $ })
|
|
921
|
+
}), w = (g.results ?? []).filter((V) => !V.ok);
|
|
922
|
+
g.status === "success" ? (k += 1, j($, { status: "success" })) : g.status === "partial" ? (C += 1, j($, { status: "partial", failed: w.length, failures: w })) : (C += 1, j($, { status: "failed", failures: w }));
|
|
923
|
+
} catch (g) {
|
|
924
|
+
C += 1;
|
|
925
|
+
const w = g instanceof Error ? g.message : String(g);
|
|
926
|
+
j($, { status: "failed", error: w });
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
x.invalidateQueries({ queryKey: ["imaginarium", "releases"] }), x.invalidateQueries({ queryKey: ["imaginarium", "release", i] }), x.invalidateQueries({ queryKey: ["imaginarium", "release-items", i] }), x.invalidateQueries({ queryKey: ["imaginarium", "release-pushes", i] }), x.invalidateQueries({ queryKey: ["imaginarium", "release-push-preview", i] }), h(C === 0 ? { title: "Push complete", description: `Pushed to ${k} target${k === 1 ? "" : "s"}.` } : {
|
|
930
|
+
title: "Push finished with errors",
|
|
931
|
+
description: `${C} target${C === 1 ? "" : "s"} did not fully succeed.`,
|
|
932
|
+
variant: "destructive"
|
|
933
|
+
}), p(!1), Q(!0), l == null || l();
|
|
934
|
+
}, B = (k) => {
|
|
935
|
+
c || (k || (M({}), Q(!1)), s(k));
|
|
936
|
+
};
|
|
937
|
+
return /* @__PURE__ */ e(ve, { open: t, onOpenChange: B, children: /* @__PURE__ */ n(we, { className: "max-w-2xl", children: [
|
|
938
|
+
/* @__PURE__ */ n(ke, { children: [
|
|
939
|
+
/* @__PURE__ */ e(Ce, { children: "Push release" }),
|
|
940
|
+
/* @__PURE__ */ e(Te, { children: "Pushes the included items to each target cluster, one at a time. Each target re-compares against the latest origin before applying." })
|
|
941
|
+
] }),
|
|
942
|
+
m.length > 0 ? /* @__PURE__ */ n("div", { className: "space-y-1 rounded border border-amber-200 bg-amber-50 p-3 text-xs text-amber-700 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-300", children: [
|
|
943
|
+
/* @__PURE__ */ n("div", { className: "flex items-center gap-2 font-medium", children: [
|
|
944
|
+
/* @__PURE__ */ e(ye, { className: "h-4 w-4 shrink-0 text-amber-600 dark:text-amber-400" }),
|
|
945
|
+
m.length,
|
|
946
|
+
" item",
|
|
947
|
+
m.length === 1 ? "" : "s",
|
|
948
|
+
" reference excluded dependencies"
|
|
949
|
+
] }),
|
|
950
|
+
/* @__PURE__ */ e("ul", { className: "list-disc space-y-0.5 pl-8", children: m.map((k) => /* @__PURE__ */ n("li", { children: [
|
|
951
|
+
k.itemName,
|
|
952
|
+
" → ",
|
|
953
|
+
k.missing.join(", ")
|
|
954
|
+
] }, k.itemName)) }),
|
|
955
|
+
/* @__PURE__ */ e("p", { className: "pl-8 text-amber-600", children: "Push may fail for these items. You can proceed anyway." })
|
|
956
|
+
] }) : null,
|
|
957
|
+
/* @__PURE__ */ e("div", { className: "max-h-[60vh] space-y-2 overflow-y-auto py-2", children: a.length === 0 ? /* @__PURE__ */ e("p", { className: "text-sm text-muted-foreground", children: "This release has no targets." }) : a.map((k) => {
|
|
958
|
+
const C = P[k] ?? { status: "idle" }, $ = C.failures ?? [];
|
|
959
|
+
return /* @__PURE__ */ e(
|
|
960
|
+
Tt,
|
|
961
|
+
{
|
|
962
|
+
releaseId: i,
|
|
963
|
+
destConfigId: k,
|
|
964
|
+
name: U(k),
|
|
965
|
+
apiPath: d,
|
|
966
|
+
headerRight: /* @__PURE__ */ e(cn, { state: C }),
|
|
967
|
+
footer: $.length > 0 ? /* @__PURE__ */ e("ul", { className: "mt-2 max-h-48 space-y-1 overflow-auto border-t pt-2 text-xs", children: $.map((g, w) => /* @__PURE__ */ n("li", { className: "text-destructive", children: [
|
|
968
|
+
/* @__PURE__ */ n("span", { className: "font-mono", children: [
|
|
969
|
+
g.action ? `${g.action} ` : "",
|
|
970
|
+
g.itemKey ?? "item"
|
|
971
|
+
] }),
|
|
972
|
+
g.error ? /* @__PURE__ */ n("span", { className: "text-muted-foreground", children: [
|
|
973
|
+
" — ",
|
|
974
|
+
g.error
|
|
975
|
+
] }) : null
|
|
976
|
+
] }, `${g.itemKey ?? "item"}-${w}`)) }) : null
|
|
977
|
+
},
|
|
978
|
+
k
|
|
979
|
+
);
|
|
980
|
+
}) }),
|
|
981
|
+
/* @__PURE__ */ n(Pe, { children: [
|
|
982
|
+
/* @__PURE__ */ e(E, { variant: "outline", onClick: () => B(!1), disabled: c, children: "Close" }),
|
|
983
|
+
/* @__PURE__ */ n(
|
|
984
|
+
E,
|
|
985
|
+
{
|
|
986
|
+
variant: "destructive",
|
|
987
|
+
onClick: Y,
|
|
988
|
+
disabled: c || D || a.length === 0,
|
|
989
|
+
children: [
|
|
990
|
+
/* @__PURE__ */ e(jt, { className: "w-4 h-4 mr-2" }),
|
|
991
|
+
c ? "Pushing…" : "Confirm push"
|
|
992
|
+
]
|
|
993
|
+
}
|
|
994
|
+
)
|
|
995
|
+
] })
|
|
996
|
+
] }) });
|
|
997
|
+
}
|
|
998
|
+
function Pt({ item: t, onClose: s }) {
|
|
999
|
+
var a, r;
|
|
1000
|
+
const i = q(
|
|
1001
|
+
() => {
|
|
1002
|
+
var d, l;
|
|
1003
|
+
return Ct((d = t == null ? void 0 : t.diff) == null ? void 0 : d.origin, (l = t == null ? void 0 : t.diff) == null ? void 0 : l.target);
|
|
1004
|
+
},
|
|
1005
|
+
[t]
|
|
1006
|
+
);
|
|
1007
|
+
return t ? /* @__PURE__ */ n("div", { className: "flex h-full min-w-0 flex-col rounded-md border bg-background", children: [
|
|
1008
|
+
/* @__PURE__ */ n("div", { className: "flex items-center justify-between border-b p-3", children: [
|
|
1009
|
+
/* @__PURE__ */ n("div", { className: "min-w-0", children: [
|
|
1010
|
+
/* @__PURE__ */ e("div", { className: "truncate font-medium", children: t.itemName }),
|
|
1011
|
+
/* @__PURE__ */ e("div", { className: "font-mono text-xs text-muted-foreground", children: t.itemType })
|
|
1012
|
+
] }),
|
|
1013
|
+
/* @__PURE__ */ e(E, { variant: "ghost", size: "icon", title: "Close", onClick: s, children: /* @__PURE__ */ e(Ne, {}) })
|
|
1014
|
+
] }),
|
|
1015
|
+
/* @__PURE__ */ n("div", { className: "flex flex-1 gap-3 overflow-auto p-3", children: [
|
|
1016
|
+
/* @__PURE__ */ e(De, { label: "Origin", value: (a = t.diff) == null ? void 0 : a.origin, highlightLines: i }),
|
|
1017
|
+
/* @__PURE__ */ e(De, { label: "Target", value: (r = t.diff) == null ? void 0 : r.target })
|
|
1018
|
+
] })
|
|
1019
|
+
] }) : null;
|
|
1020
|
+
}
|
|
1021
|
+
function un(t) {
|
|
1022
|
+
return {
|
|
1023
|
+
itemName: t.itemName,
|
|
1024
|
+
itemType: t.itemType,
|
|
1025
|
+
diff: { origin: t.origin, target: t.target }
|
|
1026
|
+
};
|
|
1027
|
+
}
|
|
1028
|
+
function hn({
|
|
1029
|
+
open: t,
|
|
1030
|
+
onOpenChange: s,
|
|
1031
|
+
releaseId: i,
|
|
1032
|
+
targetConfigIds: a,
|
|
1033
|
+
targetNames: r,
|
|
1034
|
+
apiPath: d = "/releases"
|
|
1035
|
+
}) {
|
|
1036
|
+
const [l, m] = R(null), h = (x) => (r == null ? void 0 : r[x]) ?? x, b = (x) => {
|
|
1037
|
+
x || m(null), s(x);
|
|
1038
|
+
};
|
|
1039
|
+
return /* @__PURE__ */ e(ve, { open: t, onOpenChange: b, children: /* @__PURE__ */ n(we, { className: "max-w-4xl", children: [
|
|
1040
|
+
/* @__PURE__ */ n(ke, { children: [
|
|
1041
|
+
/* @__PURE__ */ e(Ce, { children: "Changes to push" }),
|
|
1042
|
+
/* @__PURE__ */ e(Te, { children: "Expand a target to compute and see exactly what it would receive, from a dry run of the push. Nothing is applied." })
|
|
1043
|
+
] }),
|
|
1044
|
+
/* @__PURE__ */ e("div", { className: l ? "hidden" : "min-w-0 max-h-[70vh] space-y-2 overflow-y-auto py-2", children: a.length === 0 ? /* @__PURE__ */ e("p", { className: "text-sm text-muted-foreground", children: "This release has no targets." }) : a.map((x) => /* @__PURE__ */ e(
|
|
1045
|
+
Tt,
|
|
1046
|
+
{
|
|
1047
|
+
releaseId: i,
|
|
1048
|
+
destConfigId: x,
|
|
1049
|
+
name: h(x),
|
|
1050
|
+
apiPath: d,
|
|
1051
|
+
onSelectItem: m
|
|
1052
|
+
},
|
|
1053
|
+
x
|
|
1054
|
+
)) }),
|
|
1055
|
+
l ? /* @__PURE__ */ n("div", { className: "min-w-0 space-y-2", children: [
|
|
1056
|
+
/* @__PURE__ */ n(E, { variant: "ghost", size: "sm", onClick: () => m(null), children: [
|
|
1057
|
+
/* @__PURE__ */ e(Le, {}),
|
|
1058
|
+
" Back to changes"
|
|
1059
|
+
] }),
|
|
1060
|
+
/* @__PURE__ */ e("div", { className: "h-[60vh] min-w-0", children: /* @__PURE__ */ e(Pt, { item: un(l), onClose: () => m(null) }) })
|
|
1061
|
+
] }) : null,
|
|
1062
|
+
/* @__PURE__ */ e(Pe, { children: /* @__PURE__ */ e(E, { variant: "outline", onClick: () => b(!1), children: "Close" }) })
|
|
1063
|
+
] }) });
|
|
1064
|
+
}
|
|
1065
|
+
function pn(t) {
|
|
1066
|
+
var s;
|
|
1067
|
+
return (((s = t.diff) == null ? void 0 : s.versions) ?? []).filter((i) => !i.existsOnTarget);
|
|
1068
|
+
}
|
|
1069
|
+
function fn({ item: t, disabled: s, onChange: i }) {
|
|
1070
|
+
var r;
|
|
1071
|
+
const a = ((r = t.diff) == null ? void 0 : r.versions) ?? [];
|
|
1072
|
+
return /* @__PURE__ */ n(
|
|
1073
|
+
"select",
|
|
1074
|
+
{
|
|
1075
|
+
value: t.selectedVersion ?? "",
|
|
1076
|
+
disabled: s,
|
|
1077
|
+
onClick: (d) => d.stopPropagation(),
|
|
1078
|
+
onChange: (d) => i(d.target.value),
|
|
1079
|
+
className: "h-7 rounded-md border border-input bg-background px-2 py-0.5 text-xs disabled:cursor-not-allowed disabled:opacity-50",
|
|
1080
|
+
"aria-label": "Rule version",
|
|
1081
|
+
children: [
|
|
1082
|
+
/* @__PURE__ */ e("option", { value: "", disabled: !0, children: "Select a version" }),
|
|
1083
|
+
a.map((d) => {
|
|
1084
|
+
const l = String(d.version), m = d.existsOnTarget ? `v${d.version} — already on target` : `v${d.version}${d.isPublished ? " (published)" : ""}`;
|
|
1085
|
+
return /* @__PURE__ */ e("option", { value: l, disabled: d.existsOnTarget, children: m }, l);
|
|
1086
|
+
})
|
|
1087
|
+
]
|
|
1088
|
+
}
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
const gn = {
|
|
1092
|
+
blueprint: "bg-blue-100 text-blue-700 dark:bg-blue-500/15 dark:text-blue-300",
|
|
1093
|
+
rule: "bg-orange-100 text-orange-700 dark:bg-orange-500/15 dark:text-orange-300",
|
|
1094
|
+
messageRoute: "bg-teal-100 text-teal-700 dark:bg-teal-500/15 dark:text-teal-300",
|
|
1095
|
+
role: "bg-purple-100 text-purple-700 dark:bg-purple-500/15 dark:text-purple-300",
|
|
1096
|
+
enum: "bg-yellow-100 text-amber-800 dark:bg-amber-500/15 dark:text-amber-300",
|
|
1097
|
+
resourceEnum: "bg-yellow-100 text-amber-800 dark:bg-amber-500/15 dark:text-amber-300",
|
|
1098
|
+
timer: "bg-slate-100 text-slate-600 dark:bg-slate-500/20 dark:text-slate-300",
|
|
1099
|
+
network: "bg-green-100 text-green-700 dark:bg-green-500/15 dark:text-green-300",
|
|
1100
|
+
module: "bg-indigo-100 text-indigo-700 dark:bg-indigo-500/15 dark:text-indigo-300",
|
|
1101
|
+
permission: "bg-pink-100 text-pink-700 dark:bg-pink-500/15 dark:text-pink-300",
|
|
1102
|
+
template: "bg-red-100 text-red-800 dark:bg-red-500/15 dark:text-red-300",
|
|
1103
|
+
script: "bg-amber-100 text-amber-800 dark:bg-amber-500/15 dark:text-amber-300",
|
|
1104
|
+
scenario: "bg-cyan-100 text-cyan-700 dark:bg-cyan-500/15 dark:text-cyan-300",
|
|
1105
|
+
system: "bg-gray-200 text-gray-700 dark:bg-gray-500/20 dark:text-gray-300",
|
|
1106
|
+
attribute: "bg-violet-100 text-violet-700 dark:bg-violet-500/15 dark:text-violet-300",
|
|
1107
|
+
enumValue: "bg-violet-100 text-violet-700 dark:bg-violet-500/15 dark:text-violet-300",
|
|
1108
|
+
project: "bg-fuchsia-50 text-fuchsia-800 dark:bg-fuchsia-500/15 dark:text-fuchsia-300"
|
|
1109
|
+
};
|
|
1110
|
+
function xe({ type: t }) {
|
|
1111
|
+
const s = gn[t] ?? "bg-muted text-muted-foreground";
|
|
1112
|
+
return /* @__PURE__ */ e("span", { className: `inline-flex items-center rounded px-1.5 py-0.5 text-xs font-semibold ${s}`, children: t });
|
|
1113
|
+
}
|
|
1114
|
+
function lt({ checked: t, onChange: s, disabled: i = !1 }) {
|
|
1115
|
+
return /* @__PURE__ */ n(
|
|
1116
|
+
"label",
|
|
1117
|
+
{
|
|
1118
|
+
className: `relative inline-block h-[18px] w-8 shrink-0 ${i ? "cursor-not-allowed opacity-40" : "cursor-pointer"}`,
|
|
1119
|
+
children: [
|
|
1120
|
+
/* @__PURE__ */ e(
|
|
1121
|
+
"input",
|
|
1122
|
+
{
|
|
1123
|
+
type: "checkbox",
|
|
1124
|
+
className: "peer sr-only",
|
|
1125
|
+
checked: t,
|
|
1126
|
+
disabled: i,
|
|
1127
|
+
onChange: (a) => s(a.target.checked)
|
|
1128
|
+
}
|
|
1129
|
+
),
|
|
1130
|
+
/* @__PURE__ */ e("span", { className: "absolute inset-0 rounded-full bg-input transition-colors peer-checked:bg-primary" }),
|
|
1131
|
+
/* @__PURE__ */ e("span", { className: "absolute left-0.5 top-0.5 h-3.5 w-3.5 rounded-full bg-white transition-transform peer-checked:translate-x-3.5" })
|
|
1132
|
+
]
|
|
1133
|
+
}
|
|
1134
|
+
);
|
|
1135
|
+
}
|
|
1136
|
+
function xn(t) {
|
|
1137
|
+
const s = /* @__PURE__ */ new Map();
|
|
1138
|
+
for (const a of t) {
|
|
1139
|
+
const r = s.get(a.destConfigId);
|
|
1140
|
+
(!r || a.createdAt > r.createdAt) && s.set(a.destConfigId, a);
|
|
1141
|
+
}
|
|
1142
|
+
const i = /* @__PURE__ */ new Map();
|
|
1143
|
+
for (const a of s.values())
|
|
1144
|
+
for (const r of a.results ?? []) {
|
|
1145
|
+
if (!r.itemKey)
|
|
1146
|
+
continue;
|
|
1147
|
+
let d = i.get(r.itemKey);
|
|
1148
|
+
d || (d = /* @__PURE__ */ new Map(), i.set(r.itemKey, d)), d.set(a.destConfigId, { ok: r.ok, error: r.error });
|
|
1149
|
+
}
|
|
1150
|
+
return i;
|
|
1151
|
+
}
|
|
1152
|
+
function yn(t, s, i) {
|
|
1153
|
+
var a;
|
|
1154
|
+
return (a = t.get(s)) == null ? void 0 : a.get(i);
|
|
1155
|
+
}
|
|
1156
|
+
function Gn(t, s) {
|
|
1157
|
+
return t.filter((i) => !(s.type !== "all" && i.itemType !== s.type || s.included === "enabled" && (!i.included || i.ignored) || s.included === "disabled" && i.included && !i.ignored));
|
|
1158
|
+
}
|
|
1159
|
+
function bn(t) {
|
|
1160
|
+
const s = {};
|
|
1161
|
+
for (const i of t)
|
|
1162
|
+
s[i.itemType] = (s[i.itemType] ?? 0) + 1;
|
|
1163
|
+
return s;
|
|
1164
|
+
}
|
|
1165
|
+
function Nn(t) {
|
|
1166
|
+
const s = t.indexOf(":"), i = s >= 0 ? t.slice(0, s) : t, a = s >= 0 ? t.slice(s + 1) : t;
|
|
1167
|
+
return {
|
|
1168
|
+
id: "",
|
|
1169
|
+
releaseId: "",
|
|
1170
|
+
itemKey: t,
|
|
1171
|
+
itemType: i,
|
|
1172
|
+
itemName: a,
|
|
1173
|
+
parentKey: null,
|
|
1174
|
+
selectedVersion: null,
|
|
1175
|
+
status: "updated",
|
|
1176
|
+
included: !0,
|
|
1177
|
+
carriedOver: !1,
|
|
1178
|
+
ignored: !1,
|
|
1179
|
+
diff: null,
|
|
1180
|
+
createdAt: "",
|
|
1181
|
+
updatedAt: ""
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
function vn(t) {
|
|
1185
|
+
var d;
|
|
1186
|
+
const s = new Set(
|
|
1187
|
+
t.filter((l) => !l.parentKey).map((l) => l.itemKey)
|
|
1188
|
+
), i = [], a = /* @__PURE__ */ new Map();
|
|
1189
|
+
for (const l of t) {
|
|
1190
|
+
if (l.parentKey)
|
|
1191
|
+
continue;
|
|
1192
|
+
const m = { item: l, children: [] };
|
|
1193
|
+
i.push(m), a.set(l.itemKey, m);
|
|
1194
|
+
}
|
|
1195
|
+
const r = /* @__PURE__ */ new Map();
|
|
1196
|
+
for (const l of t) {
|
|
1197
|
+
if (!l.parentKey)
|
|
1198
|
+
continue;
|
|
1199
|
+
if (s.has(l.parentKey)) {
|
|
1200
|
+
(d = a.get(l.parentKey)) == null || d.children.push(l);
|
|
1201
|
+
continue;
|
|
1202
|
+
}
|
|
1203
|
+
let m = r.get(l.parentKey);
|
|
1204
|
+
m || (m = { item: Nn(l.parentKey), children: [], synthetic: !0 }, r.set(l.parentKey, m), i.push(m)), m.children.push(l);
|
|
1205
|
+
}
|
|
1206
|
+
return i;
|
|
1207
|
+
}
|
|
1208
|
+
function wn(t) {
|
|
1209
|
+
const s = t.indexOf(":"), i = s >= 0 ? t.slice(0, s) : t, a = s >= 0 ? t.slice(s + 1) : t;
|
|
1210
|
+
return { itemKey: t, itemType: i, itemName: a, parentKey: null, cells: {} };
|
|
1211
|
+
}
|
|
1212
|
+
function kn(t) {
|
|
1213
|
+
var d;
|
|
1214
|
+
const s = new Set(
|
|
1215
|
+
t.filter((l) => !l.parentKey).map((l) => l.itemKey)
|
|
1216
|
+
), i = [], a = /* @__PURE__ */ new Map();
|
|
1217
|
+
for (const l of t) {
|
|
1218
|
+
if (l.parentKey)
|
|
1219
|
+
continue;
|
|
1220
|
+
const m = { row: l, children: [] };
|
|
1221
|
+
i.push(m), a.set(l.itemKey, m);
|
|
1222
|
+
}
|
|
1223
|
+
const r = /* @__PURE__ */ new Map();
|
|
1224
|
+
for (const l of t) {
|
|
1225
|
+
if (!l.parentKey)
|
|
1226
|
+
continue;
|
|
1227
|
+
if (s.has(l.parentKey)) {
|
|
1228
|
+
(d = a.get(l.parentKey)) == null || d.children.push(l);
|
|
1229
|
+
continue;
|
|
1230
|
+
}
|
|
1231
|
+
let m = r.get(l.parentKey);
|
|
1232
|
+
m || (m = { row: wn(l.parentKey), children: [], synthetic: !0 }, r.set(l.parentKey, m), i.push(m)), m.children.push(l);
|
|
1233
|
+
}
|
|
1234
|
+
return i;
|
|
1235
|
+
}
|
|
1236
|
+
function Cn(t) {
|
|
1237
|
+
let s = 0;
|
|
1238
|
+
for (const i of t.children)
|
|
1239
|
+
i.included && !i.ignored && (s += 1);
|
|
1240
|
+
return { included: s, total: t.children.length };
|
|
1241
|
+
}
|
|
1242
|
+
function Tn(t) {
|
|
1243
|
+
var a, r;
|
|
1244
|
+
const s = [];
|
|
1245
|
+
for (const d of t) {
|
|
1246
|
+
if (d.status !== "new")
|
|
1247
|
+
continue;
|
|
1248
|
+
const l = (a = d.diff) == null ? void 0 : a.origin, m = l == null ? void 0 : l.id;
|
|
1249
|
+
if (typeof m == "string" && m && s.push({ token: m, depKey: d.itemKey }), d.itemType === "enum") {
|
|
1250
|
+
const h = l == null ? void 0 : l.type;
|
|
1251
|
+
typeof h == "string" && h && s.push({ token: h, depKey: d.itemKey });
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
const i = /* @__PURE__ */ new Map();
|
|
1255
|
+
for (const d of t) {
|
|
1256
|
+
const l = /* @__PURE__ */ new Set(), m = JSON.stringify(((r = d.diff) == null ? void 0 : r.origin) ?? null);
|
|
1257
|
+
for (const { token: h, depKey: b } of s)
|
|
1258
|
+
b !== d.itemKey && m.includes(h) && l.add(b);
|
|
1259
|
+
i.set(d.itemKey, l);
|
|
1260
|
+
}
|
|
1261
|
+
return i;
|
|
1262
|
+
}
|
|
1263
|
+
function Ie(t, s, i) {
|
|
1264
|
+
const a = s.get(t.itemKey);
|
|
1265
|
+
if (!a || a.size === 0)
|
|
1266
|
+
return [];
|
|
1267
|
+
const r = [];
|
|
1268
|
+
for (const d of a) {
|
|
1269
|
+
const l = i.get(d);
|
|
1270
|
+
l && l.status === "new" && (!l.included || l.ignored) && r.push(l);
|
|
1271
|
+
}
|
|
1272
|
+
return r;
|
|
1273
|
+
}
|
|
1274
|
+
function Pn(t) {
|
|
1275
|
+
return t.tags + t.metadataKeys + t.i18nPaths + t.permissions;
|
|
1276
|
+
}
|
|
1277
|
+
function Sn(t) {
|
|
1278
|
+
const s = [];
|
|
1279
|
+
return t.tags > 0 && s.push(`${t.tags} tag${t.tags === 1 ? "" : "s"}`), t.metadataKeys > 0 && s.push(`${t.metadataKeys} metadata key${t.metadataKeys === 1 ? "" : "s"}`), t.i18nPaths > 0 && s.push(`${t.i18nPaths} translation${t.i18nPaths === 1 ? "" : "s"}`), t.permissions > 0 && s.push(`${t.permissions} permission${t.permissions === 1 ? "" : "s"}`), s.length === 0 ? "" : `${s.join(", ")} excluded from push`;
|
|
1280
|
+
}
|
|
1281
|
+
const Kn = [
|
|
1282
|
+
{ value: "all", label: "All" },
|
|
1283
|
+
{ value: "enabled", label: "Enabled" },
|
|
1284
|
+
{ value: "disabled", label: "Disabled" }
|
|
1285
|
+
];
|
|
1286
|
+
function ot(t, s) {
|
|
1287
|
+
return s === "all" ? !0 : s === "enabled" ? t.included && !t.ignored : !t.included || t.ignored;
|
|
1288
|
+
}
|
|
1289
|
+
function dt({ status: t }) {
|
|
1290
|
+
return /* @__PURE__ */ e("span", { className: "inline-flex items-center rounded px-1.5 py-0.5 text-xs font-medium border bg-muted text-muted-foreground border-border", children: t });
|
|
1291
|
+
}
|
|
1292
|
+
function Z(t) {
|
|
1293
|
+
if (Array.isArray(t))
|
|
1294
|
+
return t.filter((s) => typeof s == "string");
|
|
1295
|
+
if (typeof t == "string" && t.length > 0)
|
|
1296
|
+
try {
|
|
1297
|
+
const s = JSON.parse(t);
|
|
1298
|
+
return Array.isArray(s) ? s.filter((i) => typeof i == "string") : [];
|
|
1299
|
+
} catch {
|
|
1300
|
+
return [];
|
|
1301
|
+
}
|
|
1302
|
+
return [];
|
|
1303
|
+
}
|
|
1304
|
+
function ct({ item: t }) {
|
|
1305
|
+
const s = {
|
|
1306
|
+
tags: Z(t.excludedTags).length,
|
|
1307
|
+
metadataKeys: Z(t.excludedMetadataKeys).length,
|
|
1308
|
+
i18nPaths: Z(t.excludedI18nPaths).length,
|
|
1309
|
+
permissions: Z(t.excludedPermissions).length
|
|
1310
|
+
}, i = Pn(s);
|
|
1311
|
+
return i <= 0 ? null : /* @__PURE__ */ n(
|
|
1312
|
+
"span",
|
|
1313
|
+
{
|
|
1314
|
+
title: Sn(s),
|
|
1315
|
+
className: "inline-flex items-center rounded px-1.5 py-0.5 text-xs bg-red-100 text-red-700 dark:bg-red-500/15 dark:text-red-300",
|
|
1316
|
+
children: [
|
|
1317
|
+
i,
|
|
1318
|
+
" manual override",
|
|
1319
|
+
i === 1 ? "" : "s"
|
|
1320
|
+
]
|
|
1321
|
+
}
|
|
1322
|
+
);
|
|
1323
|
+
}
|
|
1324
|
+
function mt({
|
|
1325
|
+
item: t,
|
|
1326
|
+
targetConfigIds: s,
|
|
1327
|
+
results: i,
|
|
1328
|
+
pushedDests: a,
|
|
1329
|
+
displayName: r
|
|
1330
|
+
}) {
|
|
1331
|
+
const d = t.included && !t.ignored, l = s.filter((m) => a.has(m)).map((m) => ({ id: m, result: yn(i, t.itemKey, m) })).filter((m) => m.result != null || d);
|
|
1332
|
+
return l.length === 0 ? null : /* @__PURE__ */ e("div", { className: "flex flex-wrap justify-end gap-1", children: l.map(({ id: m, result: h }) => {
|
|
1333
|
+
const b = h ? h.ok ? "bg-green-100 text-green-700 dark:bg-green-500/15 dark:text-green-300" : "bg-red-100 text-red-700 dark:bg-red-500/15 dark:text-red-300" : "bg-muted text-muted-foreground", x = h ? h.ok ? "✓" : "✗" : "=", c = h ? h.ok ? void 0 : h.error : "No change — already in sync";
|
|
1334
|
+
return /* @__PURE__ */ n(
|
|
1335
|
+
"span",
|
|
1336
|
+
{
|
|
1337
|
+
title: c,
|
|
1338
|
+
className: `inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 text-[10px] font-semibold ${b}`,
|
|
1339
|
+
children: [
|
|
1340
|
+
r(m),
|
|
1341
|
+
" ",
|
|
1342
|
+
x
|
|
1343
|
+
]
|
|
1344
|
+
},
|
|
1345
|
+
m
|
|
1346
|
+
);
|
|
1347
|
+
}) });
|
|
1348
|
+
}
|
|
1349
|
+
function En({ releaseId: t, onBack: s }) {
|
|
1350
|
+
var Ye, We, Ge;
|
|
1351
|
+
const i = Ue.get("Release", "apiPath", "/releases"), { toast: a } = oe(), { fetchJson: r } = te(), { configs: d } = be(), l = de(), [m, h] = R("all"), [b, x] = R("all"), [c, p] = R(null), [P, M] = R(!1), [D, Q] = R(!1), [U, j] = R(() => /* @__PURE__ */ new Set()), Y = (o) => j((v) => {
|
|
1352
|
+
const u = new Set(v);
|
|
1353
|
+
return u.has(o) ? u.delete(o) : u.add(o), u;
|
|
1354
|
+
}), B = ["imaginarium", "release", t], k = ["imaginarium", "release-items", t], C = ["imaginarium", "release-pushes", t], $ = ["imaginarium", "release-push-preview", t], g = () => {
|
|
1355
|
+
l.invalidateQueries({ queryKey: k }), l.invalidateQueries({ queryKey: $ });
|
|
1356
|
+
}, { data: w, isLoading: V } = ae({
|
|
1357
|
+
queryKey: B,
|
|
1358
|
+
queryFn: () => r(`${i}/${t}`)
|
|
1359
|
+
}), { data: L, isLoading: X } = ae({
|
|
1360
|
+
queryKey: k,
|
|
1361
|
+
queryFn: async () => {
|
|
1362
|
+
const o = await r(`${i}/${t}/items`);
|
|
1363
|
+
return Array.isArray(o) ? o : (o == null ? void 0 : o.items) ?? [];
|
|
1364
|
+
}
|
|
1365
|
+
}), { data: f } = ae({
|
|
1366
|
+
queryKey: C,
|
|
1367
|
+
queryFn: async () => {
|
|
1368
|
+
const o = await r(`${i}/${t}/pushes`);
|
|
1369
|
+
return Array.isArray(o) ? o : (o == null ? void 0 : o.items) ?? [];
|
|
1370
|
+
}
|
|
1371
|
+
}), F = q(() => xn(f ?? []), [f]), J = q(
|
|
1372
|
+
() => new Set((f ?? []).map((o) => o.destConfigId)),
|
|
1373
|
+
[f]
|
|
1374
|
+
), A = (f ?? []).length > 0, H = q(() => (w == null ? void 0 : w.targetConfigIds) ?? [], [w]), z = q(() => {
|
|
1375
|
+
const o = /* @__PURE__ */ new Map();
|
|
1376
|
+
return d.forEach((v) => o.set(String(v.id), v.displayName)), o;
|
|
1377
|
+
}, [d]), y = (o) => z.get(o) ?? o, O = q(() => vn(L ?? []), [L]), T = q(() => O.map((o) => o.item), [O]), ee = q(() => Tn(L ?? []), [L]), ne = q(
|
|
1378
|
+
() => new Map((L ?? []).map((o) => [o.itemKey, o])),
|
|
1379
|
+
[L]
|
|
1380
|
+
), pe = (o) => {
|
|
1381
|
+
var u;
|
|
1382
|
+
let v;
|
|
1383
|
+
if (o.parentKey) {
|
|
1384
|
+
const I = (u = ne.get(o.parentKey)) == null ? void 0 : u.itemName, S = o.parentKey.indexOf(":");
|
|
1385
|
+
v = I ?? (S >= 0 ? o.parentKey.slice(S + 1) : void 0);
|
|
1386
|
+
}
|
|
1387
|
+
return `${v ? v + " " : ""}${o.itemType} "${o.itemName}"`;
|
|
1388
|
+
}, G = q(() => {
|
|
1389
|
+
var v, u;
|
|
1390
|
+
const o = /* @__PURE__ */ new Map();
|
|
1391
|
+
for (const I of L ?? []) {
|
|
1392
|
+
const S = (u = (v = I.diff) == null ? void 0 : v.origin) == null ? void 0 : u.id;
|
|
1393
|
+
typeof S == "string" && S && o.set(S, I.itemName);
|
|
1394
|
+
}
|
|
1395
|
+
return o;
|
|
1396
|
+
}, [L]), me = q(
|
|
1397
|
+
() => (L ?? []).filter((o) => o.included && !o.ignored).map((o) => ({
|
|
1398
|
+
itemName: o.itemName,
|
|
1399
|
+
missing: Ie(o, ee, ne).map(pe)
|
|
1400
|
+
})).filter((o) => o.missing.length > 0),
|
|
1401
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1402
|
+
[L, ee, ne]
|
|
1403
|
+
), qe = q(() => bn(T), [T]), St = q(() => Object.keys(qe).sort(Je), [qe]), He = q(() => O.filter((o) => m === "all" || o.item.itemType === m).map((o) => {
|
|
1404
|
+
const v = b === "all" ? o.children : o.children.filter((u) => ot(u, b));
|
|
1405
|
+
return { node: o, renderChildren: v };
|
|
1406
|
+
}).filter(
|
|
1407
|
+
({ node: o, renderChildren: v }) => b === "all" || ot(o.item, b) || v.length > 0
|
|
1408
|
+
).sort((o, v) => {
|
|
1409
|
+
const u = Je(o.node.item.itemType, v.node.item.itemType);
|
|
1410
|
+
return u !== 0 ? u : o.node.item.itemName.localeCompare(v.node.item.itemName);
|
|
1411
|
+
}), [O, m, b]), Se = _({
|
|
1412
|
+
mutationFn: () => r(`${i}/${t}/refresh`, { method: "POST" }),
|
|
1413
|
+
onSuccess: () => {
|
|
1414
|
+
g(), a({ title: "Snapshot refreshed", description: "Items re-computed from origin." });
|
|
1415
|
+
},
|
|
1416
|
+
onError: (o) => {
|
|
1417
|
+
a({ title: "Error", description: o.message, variant: "destructive" });
|
|
1418
|
+
}
|
|
1419
|
+
}), Ke = _({
|
|
1420
|
+
mutationFn: ({ itemId: o, included: v }) => r(`${i}/${t}/items/${o}`, {
|
|
1421
|
+
method: "PATCH",
|
|
1422
|
+
body: JSON.stringify({ included: v })
|
|
1423
|
+
}),
|
|
1424
|
+
onSuccess: () => {
|
|
1425
|
+
g();
|
|
1426
|
+
},
|
|
1427
|
+
onError: (o) => {
|
|
1428
|
+
a({ title: "Error", description: o.message, variant: "destructive" });
|
|
1429
|
+
}
|
|
1430
|
+
}), _e = _({
|
|
1431
|
+
mutationFn: ({ itemId: o, selectedVersion: v }) => r(`${i}/${t}/items/${o}`, {
|
|
1432
|
+
method: "PATCH",
|
|
1433
|
+
body: JSON.stringify({ selectedVersion: v })
|
|
1434
|
+
}),
|
|
1435
|
+
onSuccess: () => {
|
|
1436
|
+
g();
|
|
1437
|
+
},
|
|
1438
|
+
onError: (o) => {
|
|
1439
|
+
a({ title: "Error", description: o.message, variant: "destructive" });
|
|
1440
|
+
}
|
|
1441
|
+
}), Ee = (o) => ({
|
|
1442
|
+
mutationFn: ({ itemId: v, value: u }) => r(`${i}/${t}/items/${v}`, {
|
|
1443
|
+
method: "PATCH",
|
|
1444
|
+
body: JSON.stringify({ [o]: u })
|
|
1445
|
+
}),
|
|
1446
|
+
onMutate: async ({ itemId: v, value: u }) => {
|
|
1447
|
+
await l.cancelQueries({ queryKey: k });
|
|
1448
|
+
const I = l.getQueryData(k);
|
|
1449
|
+
return l.setQueryData(
|
|
1450
|
+
k,
|
|
1451
|
+
(S) => (S ?? []).map((ie) => ie.id === v ? { ...ie, [o]: u } : ie)
|
|
1452
|
+
), { prev: I };
|
|
1453
|
+
},
|
|
1454
|
+
onError: (v, u, I) => {
|
|
1455
|
+
I != null && I.prev && l.setQueryData(k, I.prev), a({ title: "Error", description: v.message, variant: "destructive" });
|
|
1456
|
+
},
|
|
1457
|
+
onSettled: () => {
|
|
1458
|
+
g();
|
|
1459
|
+
}
|
|
1460
|
+
}), Kt = _(Ee("excludedTags")), Et = _(Ee("excludedMetadataKeys")), $t = _(Ee("excludedI18nPaths")), Ot = _(Ee("excludedPermissions")), se = (w == null ? void 0 : w.status) === "pushed", N = c ? ne.get(c.itemKey) ?? c : null;
|
|
1461
|
+
return V ? /* @__PURE__ */ e("div", { className: "text-center text-muted-foreground py-8", children: "Loading…" }) : w ? /* @__PURE__ */ n("div", { className: "space-y-4", children: [
|
|
1462
|
+
se && /* @__PURE__ */ e("div", { className: "bg-muted text-muted-foreground rounded-md px-3 py-2 text-sm", children: "This release was pushed and is read-only." }),
|
|
1463
|
+
/* @__PURE__ */ n("div", { className: "space-y-3", children: [
|
|
1464
|
+
/* @__PURE__ */ n("div", { className: "flex items-center justify-between", children: [
|
|
1465
|
+
/* @__PURE__ */ n("div", { className: "flex items-center gap-3", children: [
|
|
1466
|
+
/* @__PURE__ */ n(E, { variant: "ghost", size: "sm", onClick: s, children: [
|
|
1467
|
+
/* @__PURE__ */ e(Le, {}),
|
|
1468
|
+
"Back"
|
|
1469
|
+
] }),
|
|
1470
|
+
/* @__PURE__ */ e("h3", { className: "text-lg font-semibold", children: w.name }),
|
|
1471
|
+
/* @__PURE__ */ e(kt, { status: w.status })
|
|
1472
|
+
] }),
|
|
1473
|
+
/* @__PURE__ */ n("div", { className: "flex items-center gap-2", children: [
|
|
1474
|
+
!se && /* @__PURE__ */ e(
|
|
1475
|
+
nn,
|
|
1476
|
+
{
|
|
1477
|
+
releaseId: t,
|
|
1478
|
+
apiPath: i,
|
|
1479
|
+
onReset: g
|
|
1480
|
+
}
|
|
1481
|
+
),
|
|
1482
|
+
/* @__PURE__ */ n(
|
|
1483
|
+
E,
|
|
1484
|
+
{
|
|
1485
|
+
variant: "outline",
|
|
1486
|
+
size: "sm",
|
|
1487
|
+
onClick: () => Se.mutate(),
|
|
1488
|
+
disabled: se || Se.isPending,
|
|
1489
|
+
children: [
|
|
1490
|
+
/* @__PURE__ */ e(vt, {}),
|
|
1491
|
+
Se.isPending ? "Refreshing…" : "Refresh"
|
|
1492
|
+
]
|
|
1493
|
+
}
|
|
1494
|
+
),
|
|
1495
|
+
/* @__PURE__ */ n(
|
|
1496
|
+
E,
|
|
1497
|
+
{
|
|
1498
|
+
variant: "outline",
|
|
1499
|
+
size: "sm",
|
|
1500
|
+
onClick: () => Q(!0),
|
|
1501
|
+
disabled: (w.targetConfigIds ?? []).length === 0,
|
|
1502
|
+
children: [
|
|
1503
|
+
/* @__PURE__ */ e(Lt, {}),
|
|
1504
|
+
"Preview changes"
|
|
1505
|
+
]
|
|
1506
|
+
}
|
|
1507
|
+
),
|
|
1508
|
+
se ? /* @__PURE__ */ e(E, { size: "sm", disabled: !0, children: "Pushed ✓" }) : /* @__PURE__ */ e(
|
|
1509
|
+
E,
|
|
1510
|
+
{
|
|
1511
|
+
size: "sm",
|
|
1512
|
+
onClick: () => M(!0),
|
|
1513
|
+
disabled: (w.targetConfigIds ?? []).length === 0,
|
|
1514
|
+
children: "Push"
|
|
1515
|
+
}
|
|
1516
|
+
)
|
|
1517
|
+
] })
|
|
1518
|
+
] }),
|
|
1519
|
+
/* @__PURE__ */ n("div", { className: "flex flex-wrap items-center gap-2 text-sm text-muted-foreground", children: [
|
|
1520
|
+
/* @__PURE__ */ e("span", { className: "inline-flex items-center rounded bg-muted px-1.5 py-0.5 text-xs", children: y(w.originConfigId) }),
|
|
1521
|
+
/* @__PURE__ */ e("span", { children: "→" }),
|
|
1522
|
+
(w.targetConfigIds ?? []).map((o) => /* @__PURE__ */ e("span", { className: "inline-flex items-center rounded bg-muted px-1.5 py-0.5 text-xs", children: y(o) }, o)),
|
|
1523
|
+
/* @__PURE__ */ n("span", { className: "ml-2", children: [
|
|
1524
|
+
"Snapshot: ",
|
|
1525
|
+
w.snapshotAt ? new Date(w.snapshotAt).toLocaleString() : "—"
|
|
1526
|
+
] }),
|
|
1527
|
+
/* @__PURE__ */ n("span", { children: [
|
|
1528
|
+
"Pushed: ",
|
|
1529
|
+
w.pushedAt ? new Date(w.pushedAt).toLocaleString() : "—"
|
|
1530
|
+
] })
|
|
1531
|
+
] })
|
|
1532
|
+
] }),
|
|
1533
|
+
/* @__PURE__ */ n("div", { className: "space-y-2", children: [
|
|
1534
|
+
/* @__PURE__ */ n("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
1535
|
+
/* @__PURE__ */ n(
|
|
1536
|
+
E,
|
|
1537
|
+
{
|
|
1538
|
+
variant: m === "all" ? "secondary" : "ghost",
|
|
1539
|
+
size: "sm",
|
|
1540
|
+
onClick: () => h("all"),
|
|
1541
|
+
children: [
|
|
1542
|
+
"All types (",
|
|
1543
|
+
T.length,
|
|
1544
|
+
")"
|
|
1545
|
+
]
|
|
1546
|
+
}
|
|
1547
|
+
),
|
|
1548
|
+
St.map((o) => /* @__PURE__ */ n(
|
|
1549
|
+
E,
|
|
1550
|
+
{
|
|
1551
|
+
variant: m === o ? "secondary" : "ghost",
|
|
1552
|
+
size: "sm",
|
|
1553
|
+
onClick: () => h(o),
|
|
1554
|
+
children: [
|
|
1555
|
+
o,
|
|
1556
|
+
" (",
|
|
1557
|
+
qe[o],
|
|
1558
|
+
")"
|
|
1559
|
+
]
|
|
1560
|
+
},
|
|
1561
|
+
o
|
|
1562
|
+
))
|
|
1563
|
+
] }),
|
|
1564
|
+
/* @__PURE__ */ e("div", { className: "flex flex-wrap items-center gap-1", children: Kn.map((o) => /* @__PURE__ */ e(
|
|
1565
|
+
E,
|
|
1566
|
+
{
|
|
1567
|
+
variant: b === o.value ? "secondary" : "outline",
|
|
1568
|
+
size: "sm",
|
|
1569
|
+
onClick: () => x(o.value),
|
|
1570
|
+
children: o.label
|
|
1571
|
+
},
|
|
1572
|
+
o.value
|
|
1573
|
+
)) })
|
|
1574
|
+
] }),
|
|
1575
|
+
/* @__PURE__ */ n("div", { className: "flex gap-4", children: [
|
|
1576
|
+
/* @__PURE__ */ e("div", { className: "min-w-0 flex-1", children: X ? /* @__PURE__ */ e("div", { className: "text-center text-muted-foreground py-8", children: "Loading items…" }) : He.length === 0 ? /* @__PURE__ */ e(Ae, { children: /* @__PURE__ */ e(Me, { className: "py-12 text-center text-muted-foreground", children: T.length === 0 ? "No items in this release yet." : "No items match the current filters." }) }) : /* @__PURE__ */ e(Ae, { children: /* @__PURE__ */ e(Me, { className: "p-0", children: /* @__PURE__ */ n("table", { className: "w-full text-sm", children: [
|
|
1577
|
+
/* @__PURE__ */ e("thead", { children: /* @__PURE__ */ n("tr", { className: "border-b text-left text-muted-foreground", children: [
|
|
1578
|
+
/* @__PURE__ */ e("th", { className: "p-3 font-medium w-10", children: "Inc." }),
|
|
1579
|
+
/* @__PURE__ */ e("th", { className: "p-3 font-medium", children: "Type" }),
|
|
1580
|
+
/* @__PURE__ */ e("th", { className: "p-3 font-medium", children: "Name" }),
|
|
1581
|
+
/* @__PURE__ */ e("th", { className: "p-3 font-medium", children: "Status" }),
|
|
1582
|
+
/* @__PURE__ */ e("th", { className: "p-3 font-medium" })
|
|
1583
|
+
] }) }),
|
|
1584
|
+
/* @__PURE__ */ e("tbody", { children: He.map(({ node: o, renderChildren: v }) => {
|
|
1585
|
+
var nt;
|
|
1586
|
+
const u = o.item, I = v.length > 0, S = U.has(u.itemKey) || b !== "all", ie = U.has(u.itemKey), re = Cn(o), Xe = ((nt = u.diff) == null ? void 0 : nt.versions) ?? [], fe = u.itemType === "rule" && Xe.length > 0, Ze = Xe.some((K) => K.isPublished), It = fe ? pn(u) : [], et = fe && !Ze, tt = fe && Ze && It.length === 0, $e = et || tt, Rt = fe && !$e && u.selectedVersion == null;
|
|
1587
|
+
return /* @__PURE__ */ n(yt, { children: [
|
|
1588
|
+
o.synthetic ? /* @__PURE__ */ n(
|
|
1589
|
+
"tr",
|
|
1590
|
+
{
|
|
1591
|
+
className: "border-b last:border-0 cursor-pointer hover:bg-muted/50",
|
|
1592
|
+
onClick: () => Y(u.itemKey),
|
|
1593
|
+
children: [
|
|
1594
|
+
/* @__PURE__ */ e("td", { className: "p-3" }),
|
|
1595
|
+
/* @__PURE__ */ e("td", { className: "p-3", children: /* @__PURE__ */ e(xe, { type: u.itemType }) }),
|
|
1596
|
+
/* @__PURE__ */ e("td", { className: "p-3", children: /* @__PURE__ */ n("div", { className: "flex items-center gap-2", children: [
|
|
1597
|
+
/* @__PURE__ */ e(
|
|
1598
|
+
"button",
|
|
1599
|
+
{
|
|
1600
|
+
type: "button",
|
|
1601
|
+
className: "text-muted-foreground hover:text-foreground",
|
|
1602
|
+
onClick: (K) => {
|
|
1603
|
+
K.stopPropagation(), Y(u.itemKey);
|
|
1604
|
+
},
|
|
1605
|
+
"aria-label": ie ? "Collapse" : "Expand",
|
|
1606
|
+
children: ie ? /* @__PURE__ */ e(ue, { size: 14 }) : /* @__PURE__ */ e(he, { size: 14 })
|
|
1607
|
+
}
|
|
1608
|
+
),
|
|
1609
|
+
/* @__PURE__ */ e("span", { className: "font-medium", children: u.itemName }),
|
|
1610
|
+
/* @__PURE__ */ n("span", { className: `inline-flex items-center rounded px-1.5 py-0.5 text-xs ${re.included < re.total ? "bg-amber-100 text-amber-700 font-medium dark:bg-amber-500/15 dark:text-amber-300" : "bg-muted text-muted-foreground"}`, children: [
|
|
1611
|
+
re.included,
|
|
1612
|
+
"/",
|
|
1613
|
+
re.total,
|
|
1614
|
+
" changes included"
|
|
1615
|
+
] })
|
|
1616
|
+
] }) }),
|
|
1617
|
+
/* @__PURE__ */ e("td", { className: "p-3" }),
|
|
1618
|
+
/* @__PURE__ */ e("td", { className: "p-3" })
|
|
1619
|
+
]
|
|
1620
|
+
}
|
|
1621
|
+
) : /* @__PURE__ */ n(
|
|
1622
|
+
"tr",
|
|
1623
|
+
{
|
|
1624
|
+
className: `border-b last:border-0 cursor-pointer hover:bg-muted/50 ${(c == null ? void 0 : c.id) === u.id ? "bg-muted/50" : ""} ${$e ? "opacity-60" : ""}`,
|
|
1625
|
+
onClick: () => p(u),
|
|
1626
|
+
children: [
|
|
1627
|
+
/* @__PURE__ */ e("td", { className: "p-3", onClick: (K) => K.stopPropagation(), children: /* @__PURE__ */ e(
|
|
1628
|
+
lt,
|
|
1629
|
+
{
|
|
1630
|
+
checked: u.included,
|
|
1631
|
+
disabled: u.ignored || Ke.isPending || se || $e,
|
|
1632
|
+
onChange: (K) => Ke.mutate({ itemId: u.id, included: K })
|
|
1633
|
+
}
|
|
1634
|
+
) }),
|
|
1635
|
+
/* @__PURE__ */ e("td", { className: "p-3", children: /* @__PURE__ */ e(xe, { type: u.itemType }) }),
|
|
1636
|
+
/* @__PURE__ */ e("td", { className: "p-3", children: /* @__PURE__ */ n("div", { className: "flex items-center gap-2", children: [
|
|
1637
|
+
I ? /* @__PURE__ */ e(
|
|
1638
|
+
"button",
|
|
1639
|
+
{
|
|
1640
|
+
type: "button",
|
|
1641
|
+
className: "text-muted-foreground hover:text-foreground",
|
|
1642
|
+
onClick: (K) => {
|
|
1643
|
+
K.stopPropagation(), Y(u.itemKey);
|
|
1644
|
+
},
|
|
1645
|
+
"aria-label": ie ? "Collapse" : "Expand",
|
|
1646
|
+
children: ie ? /* @__PURE__ */ e(ue, { size: 14 }) : /* @__PURE__ */ e(he, { size: 14 })
|
|
1647
|
+
}
|
|
1648
|
+
) : null,
|
|
1649
|
+
/* @__PURE__ */ e("span", { className: "font-medium", children: u.itemName }),
|
|
1650
|
+
(() => {
|
|
1651
|
+
if (!u.included || u.ignored)
|
|
1652
|
+
return null;
|
|
1653
|
+
const K = Ie(u, ee, ne);
|
|
1654
|
+
return K.length === 0 ? null : /* @__PURE__ */ e("span", { title: `Depends on excluded: ${K.map((W) => W.itemName).join(", ")}`, children: /* @__PURE__ */ e(ye, { size: 14, className: "shrink-0 text-amber-600" }) });
|
|
1655
|
+
})(),
|
|
1656
|
+
/* @__PURE__ */ e(ct, { item: u }),
|
|
1657
|
+
I ? /* @__PURE__ */ n("span", { className: `inline-flex items-center rounded px-1.5 py-0.5 text-xs ${re.included < re.total ? "bg-amber-100 text-amber-700 font-medium dark:bg-amber-500/15 dark:text-amber-300" : "bg-muted text-muted-foreground"}`, children: [
|
|
1658
|
+
re.included,
|
|
1659
|
+
"/",
|
|
1660
|
+
re.total,
|
|
1661
|
+
" changes included"
|
|
1662
|
+
] }) : null,
|
|
1663
|
+
u.carriedOver ? /* @__PURE__ */ e(Zt, { originName: y(w.originConfigId) }) : null,
|
|
1664
|
+
u.ignored ? /* @__PURE__ */ e(en, {}) : null,
|
|
1665
|
+
fe && !$e ? /* @__PURE__ */ e("span", { onClick: (K) => K.stopPropagation(), children: /* @__PURE__ */ e(
|
|
1666
|
+
fn,
|
|
1667
|
+
{
|
|
1668
|
+
item: u,
|
|
1669
|
+
disabled: se || _e.isPending,
|
|
1670
|
+
onChange: (K) => _e.mutate({ itemId: u.id, selectedVersion: K })
|
|
1671
|
+
}
|
|
1672
|
+
) }) : null,
|
|
1673
|
+
et ? /* @__PURE__ */ e("span", { className: "text-xs text-muted-foreground", children: "Rules without a published version cannot be pushed" }) : null,
|
|
1674
|
+
tt ? /* @__PURE__ */ e("span", { className: "text-xs text-muted-foreground", children: "Nothing to push — all versions exist on target" }) : null,
|
|
1675
|
+
Rt ? /* @__PURE__ */ e("span", { className: "text-xs text-amber-600", children: "Pushable version not selected" }) : null
|
|
1676
|
+
] }) }),
|
|
1677
|
+
/* @__PURE__ */ e("td", { className: "p-3", children: /* @__PURE__ */ e(dt, { status: u.status }) }),
|
|
1678
|
+
/* @__PURE__ */ e("td", { className: "p-3 text-right", onClick: (K) => K.stopPropagation(), children: /* @__PURE__ */ n("div", { className: "flex items-center justify-end gap-2", children: [
|
|
1679
|
+
A ? /* @__PURE__ */ e(
|
|
1680
|
+
mt,
|
|
1681
|
+
{
|
|
1682
|
+
item: u,
|
|
1683
|
+
targetConfigIds: H,
|
|
1684
|
+
results: F,
|
|
1685
|
+
pushedDests: J,
|
|
1686
|
+
displayName: y
|
|
1687
|
+
}
|
|
1688
|
+
) : null,
|
|
1689
|
+
!u.ignored && !se && /* @__PURE__ */ e(
|
|
1690
|
+
tn,
|
|
1691
|
+
{
|
|
1692
|
+
createPayload: {
|
|
1693
|
+
originConfigId: w.originConfigId,
|
|
1694
|
+
itemKey: u.itemKey,
|
|
1695
|
+
itemType: u.itemType,
|
|
1696
|
+
itemName: u.itemName
|
|
1697
|
+
},
|
|
1698
|
+
onChange: () => {
|
|
1699
|
+
l.setQueryData(
|
|
1700
|
+
k,
|
|
1701
|
+
(K) => (K ?? []).map((W) => W.id === u.id ? { ...W, ignored: !0, included: !1 } : W)
|
|
1702
|
+
), Se.mutate();
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
)
|
|
1706
|
+
] }) })
|
|
1707
|
+
]
|
|
1708
|
+
}
|
|
1709
|
+
),
|
|
1710
|
+
I && S ? v.map((K) => /* @__PURE__ */ n(
|
|
1711
|
+
"tr",
|
|
1712
|
+
{
|
|
1713
|
+
className: `border-b last:border-0 cursor-pointer hover:bg-muted/50 ${(c == null ? void 0 : c.id) === K.id ? "bg-muted/50" : ""}`,
|
|
1714
|
+
onClick: () => p(K),
|
|
1715
|
+
children: [
|
|
1716
|
+
/* @__PURE__ */ e("td", { className: "p-3 pl-8", onClick: (W) => W.stopPropagation(), children: /* @__PURE__ */ e(
|
|
1717
|
+
lt,
|
|
1718
|
+
{
|
|
1719
|
+
checked: K.included,
|
|
1720
|
+
disabled: K.ignored || Ke.isPending || se,
|
|
1721
|
+
onChange: (W) => Ke.mutate({ itemId: K.id, included: W })
|
|
1722
|
+
}
|
|
1723
|
+
) }),
|
|
1724
|
+
/* @__PURE__ */ e("td", { className: "p-3 pl-8", children: /* @__PURE__ */ e(xe, { type: K.itemType }) }),
|
|
1725
|
+
/* @__PURE__ */ e("td", { className: "p-3", children: /* @__PURE__ */ n("div", { className: "flex items-center gap-2", children: [
|
|
1726
|
+
/* @__PURE__ */ e("span", { className: "font-medium", children: K.itemName }),
|
|
1727
|
+
(() => {
|
|
1728
|
+
if (!K.included || K.ignored)
|
|
1729
|
+
return null;
|
|
1730
|
+
const W = Ie(K, ee, ne);
|
|
1731
|
+
return W.length === 0 ? null : /* @__PURE__ */ e("span", { title: `Depends on excluded: ${W.map((At) => At.itemName).join(", ")}`, children: /* @__PURE__ */ e(ye, { size: 14, className: "shrink-0 text-amber-600" }) });
|
|
1732
|
+
})(),
|
|
1733
|
+
/* @__PURE__ */ e(ct, { item: K })
|
|
1734
|
+
] }) }),
|
|
1735
|
+
/* @__PURE__ */ e("td", { className: "p-3", children: /* @__PURE__ */ e(dt, { status: K.status }) }),
|
|
1736
|
+
/* @__PURE__ */ e("td", { className: "p-3 text-right", onClick: (W) => W.stopPropagation(), children: A ? /* @__PURE__ */ e(
|
|
1737
|
+
mt,
|
|
1738
|
+
{
|
|
1739
|
+
item: K,
|
|
1740
|
+
targetConfigIds: H,
|
|
1741
|
+
results: F,
|
|
1742
|
+
pushedDests: J,
|
|
1743
|
+
displayName: y
|
|
1744
|
+
}
|
|
1745
|
+
) : null })
|
|
1746
|
+
]
|
|
1747
|
+
},
|
|
1748
|
+
K.id
|
|
1749
|
+
)) : null
|
|
1750
|
+
] }, o.synthetic ? u.itemKey : u.id);
|
|
1751
|
+
}) })
|
|
1752
|
+
] }) }) }) }),
|
|
1753
|
+
c ? /* @__PURE__ */ e("div", { className: "w-[28rem] shrink-0 self-start sticky top-4 max-h-[calc(100vh-2rem)] overflow-auto", children: /* @__PURE__ */ e(
|
|
1754
|
+
sn,
|
|
1755
|
+
{
|
|
1756
|
+
item: N,
|
|
1757
|
+
targets: (w.targetConfigIds ?? []).map((o) => ({ id: o, name: y(o) })),
|
|
1758
|
+
onClose: () => p(null),
|
|
1759
|
+
unmetDependencyNames: N && N.included && !N.ignored ? Ie(N, ee, ne).map(pe) : [],
|
|
1760
|
+
tags: Array.isArray((We = (Ye = N == null ? void 0 : N.diff) == null ? void 0 : Ye.origin) == null ? void 0 : We.tags) ? ((Ge = N == null ? void 0 : N.diff) == null ? void 0 : Ge.origin).tags ?? [] : [],
|
|
1761
|
+
excludedTags: Z(N == null ? void 0 : N.excludedTags),
|
|
1762
|
+
metadataKeys: (() => {
|
|
1763
|
+
var v, u;
|
|
1764
|
+
const o = (u = (v = N == null ? void 0 : N.diff) == null ? void 0 : v.origin) == null ? void 0 : u.metadata;
|
|
1765
|
+
return o != null && typeof o == "object" && !Array.isArray(o) ? Object.keys(o) : [];
|
|
1766
|
+
})(),
|
|
1767
|
+
excludedMetadataKeys: Z(N == null ? void 0 : N.excludedMetadataKeys),
|
|
1768
|
+
i18nPaths: (() => {
|
|
1769
|
+
var u, I;
|
|
1770
|
+
const o = (I = (u = N == null ? void 0 : N.diff) == null ? void 0 : u.origin) == null ? void 0 : I.i18n;
|
|
1771
|
+
if (!Array.isArray(o))
|
|
1772
|
+
return [];
|
|
1773
|
+
const v = o.map((S) => S == null ? void 0 : S.path).filter((S) => typeof S == "string");
|
|
1774
|
+
return Array.from(new Set(v));
|
|
1775
|
+
})(),
|
|
1776
|
+
excludedI18nPaths: Z(N == null ? void 0 : N.excludedI18nPaths),
|
|
1777
|
+
permissionKeys: (() => {
|
|
1778
|
+
var u, I;
|
|
1779
|
+
if ((N == null ? void 0 : N.itemType) !== "role")
|
|
1780
|
+
return [];
|
|
1781
|
+
const o = (I = (u = N == null ? void 0 : N.diff) == null ? void 0 : u.origin) == null ? void 0 : I.permissions;
|
|
1782
|
+
if (!Array.isArray(o))
|
|
1783
|
+
return [];
|
|
1784
|
+
const v = o.map((S) => `${(S == null ? void 0 : S.module) ?? ""}/${(S == null ? void 0 : S.name) ?? (S == null ? void 0 : S.id) ?? ""}`).filter((S) => S !== "/");
|
|
1785
|
+
return Array.from(new Set(v));
|
|
1786
|
+
})(),
|
|
1787
|
+
excludedPermissions: Z(N == null ? void 0 : N.excludedPermissions),
|
|
1788
|
+
formatPermissionLabel: (o) => o.split(/([/.])/).map((v) => {
|
|
1789
|
+
var u, I;
|
|
1790
|
+
return ((I = (u = N == null ? void 0 : N.diff) == null ? void 0 : u.nameMap) == null ? void 0 : I[v]) ?? G.get(v) ?? v;
|
|
1791
|
+
}).join(""),
|
|
1792
|
+
replacementMaps: w.replacementMaps ?? void 0,
|
|
1793
|
+
editable: !se,
|
|
1794
|
+
onToggleTag: (o, v) => {
|
|
1795
|
+
if (!N)
|
|
1796
|
+
return;
|
|
1797
|
+
const u = Z(N.excludedTags), I = v ? u.filter((S) => S !== o) : Array.from(/* @__PURE__ */ new Set([...u, o]));
|
|
1798
|
+
Kt.mutate({ itemId: N.id, value: I });
|
|
1799
|
+
},
|
|
1800
|
+
onToggleMetadataKey: (o, v) => {
|
|
1801
|
+
if (!N)
|
|
1802
|
+
return;
|
|
1803
|
+
const u = Z(N.excludedMetadataKeys), I = v ? u.filter((S) => S !== o) : Array.from(/* @__PURE__ */ new Set([...u, o]));
|
|
1804
|
+
Et.mutate({ itemId: N.id, value: I });
|
|
1805
|
+
},
|
|
1806
|
+
onToggleI18nPath: (o, v) => {
|
|
1807
|
+
if (!N)
|
|
1808
|
+
return;
|
|
1809
|
+
const u = Z(N.excludedI18nPaths), I = v ? u.filter((S) => S !== o) : Array.from(/* @__PURE__ */ new Set([...u, o]));
|
|
1810
|
+
$t.mutate({ itemId: N.id, value: I });
|
|
1811
|
+
},
|
|
1812
|
+
onTogglePermission: (o, v) => {
|
|
1813
|
+
if (!N)
|
|
1814
|
+
return;
|
|
1815
|
+
const u = Z(N.excludedPermissions), I = v ? u.filter((S) => S !== o) : Array.from(/* @__PURE__ */ new Set([...u, o]));
|
|
1816
|
+
Ot.mutate({ itemId: N.id, value: I });
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
) }) : null
|
|
1820
|
+
] }),
|
|
1821
|
+
/* @__PURE__ */ e(
|
|
1822
|
+
mn,
|
|
1823
|
+
{
|
|
1824
|
+
open: P,
|
|
1825
|
+
onOpenChange: M,
|
|
1826
|
+
releaseId: t,
|
|
1827
|
+
apiPath: i,
|
|
1828
|
+
targetConfigIds: H,
|
|
1829
|
+
targetNames: Object.fromEntries(
|
|
1830
|
+
(w.targetConfigIds ?? []).map((o) => [o, y(o)])
|
|
1831
|
+
),
|
|
1832
|
+
dependencyWarnings: me
|
|
1833
|
+
}
|
|
1834
|
+
),
|
|
1835
|
+
/* @__PURE__ */ e(
|
|
1836
|
+
hn,
|
|
1837
|
+
{
|
|
1838
|
+
open: D,
|
|
1839
|
+
onOpenChange: Q,
|
|
1840
|
+
releaseId: t,
|
|
1841
|
+
apiPath: i,
|
|
1842
|
+
targetConfigIds: H,
|
|
1843
|
+
targetNames: Object.fromEntries(
|
|
1844
|
+
(w.targetConfigIds ?? []).map((o) => [o, y(o)])
|
|
1845
|
+
)
|
|
1846
|
+
}
|
|
1847
|
+
)
|
|
1848
|
+
] }) : /* @__PURE__ */ n("div", { className: "space-y-4", children: [
|
|
1849
|
+
/* @__PURE__ */ n(E, { variant: "ghost", size: "sm", onClick: s, children: [
|
|
1850
|
+
/* @__PURE__ */ e(Le, {}),
|
|
1851
|
+
"Back"
|
|
1852
|
+
] }),
|
|
1853
|
+
/* @__PURE__ */ e("p", { className: "text-muted-foreground", children: "Release not found." })
|
|
1854
|
+
] });
|
|
1855
|
+
}
|
|
1856
|
+
function ut({ value: t, onChange: s, configs: i, label: a }) {
|
|
1857
|
+
const r = `cluster-select-${a.toLowerCase().replace(/\s+/g, "-")}`;
|
|
1858
|
+
return /* @__PURE__ */ n("div", { className: "space-y-2", children: [
|
|
1859
|
+
/* @__PURE__ */ e(le, { htmlFor: r, children: a }),
|
|
1860
|
+
/* @__PURE__ */ n(
|
|
1861
|
+
"select",
|
|
1862
|
+
{
|
|
1863
|
+
id: r,
|
|
1864
|
+
value: t,
|
|
1865
|
+
onChange: (d) => s(d.target.value),
|
|
1866
|
+
className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm",
|
|
1867
|
+
children: [
|
|
1868
|
+
/* @__PURE__ */ e("option", { value: "", children: "Select cluster…" }),
|
|
1869
|
+
i.map((d) => /* @__PURE__ */ e("option", { value: d.id, children: d.displayName }, d.id))
|
|
1870
|
+
]
|
|
1871
|
+
}
|
|
1872
|
+
)
|
|
1873
|
+
] });
|
|
1874
|
+
}
|
|
1875
|
+
const ht = {
|
|
1876
|
+
match: { symbol: "✓", className: "text-muted-foreground", label: "Match" },
|
|
1877
|
+
diff: { symbol: "≠", className: "text-red-500 dark:text-red-400 font-semibold", label: "Diff" },
|
|
1878
|
+
translated: { symbol: "≈", className: "text-blue-600 dark:text-blue-400 font-semibold", label: "Translated" },
|
|
1879
|
+
missing: { symbol: "✗", className: "text-red-500 dark:text-red-400 font-semibold", label: "Missing" },
|
|
1880
|
+
extra: { symbol: "+", className: "text-amber-600 font-semibold", label: "Extra" },
|
|
1881
|
+
skip: { symbol: "—", className: "text-muted-foreground/50", label: "Ignored" }
|
|
1882
|
+
};
|
|
1883
|
+
function pt({
|
|
1884
|
+
state: t,
|
|
1885
|
+
onClick: s,
|
|
1886
|
+
active: i
|
|
1887
|
+
}) {
|
|
1888
|
+
const a = ht[t] ?? ht.match, r = t !== "match" && t !== "skip" && !!s;
|
|
1889
|
+
return /* @__PURE__ */ e(
|
|
1890
|
+
"button",
|
|
1891
|
+
{
|
|
1892
|
+
type: "button",
|
|
1893
|
+
onClick: r ? s : void 0,
|
|
1894
|
+
disabled: !r,
|
|
1895
|
+
title: a.label,
|
|
1896
|
+
className: ce(
|
|
1897
|
+
"w-full text-center text-sm py-1 rounded",
|
|
1898
|
+
a.className,
|
|
1899
|
+
r && "hover:bg-muted cursor-pointer",
|
|
1900
|
+
!r && "cursor-default",
|
|
1901
|
+
i && "bg-muted ring-1 ring-ring"
|
|
1902
|
+
),
|
|
1903
|
+
children: a.symbol
|
|
1904
|
+
}
|
|
1905
|
+
);
|
|
1906
|
+
}
|
|
1907
|
+
function $n({ stats: t, destConfigIds: s }) {
|
|
1908
|
+
return /* @__PURE__ */ e("div", { className: "flex gap-6 text-xs text-muted-foreground py-2 px-1", children: s.map((i) => {
|
|
1909
|
+
const a = t[i];
|
|
1910
|
+
if (!a)
|
|
1911
|
+
return null;
|
|
1912
|
+
const r = a.match + a.diff + a.missing + a.extra;
|
|
1913
|
+
return /* @__PURE__ */ n("span", { children: [
|
|
1914
|
+
/* @__PURE__ */ n("span", { className: "font-mono font-medium", children: [
|
|
1915
|
+
a.match,
|
|
1916
|
+
"/",
|
|
1917
|
+
r
|
|
1918
|
+
] }),
|
|
1919
|
+
" match",
|
|
1920
|
+
a.diff > 0 && /* @__PURE__ */ n("span", { className: "text-destructive ml-2", children: [
|
|
1921
|
+
a.diff,
|
|
1922
|
+
" diff"
|
|
1923
|
+
] }),
|
|
1924
|
+
a.missing > 0 && /* @__PURE__ */ n("span", { className: "text-destructive ml-2", children: [
|
|
1925
|
+
a.missing,
|
|
1926
|
+
" missing"
|
|
1927
|
+
] }),
|
|
1928
|
+
a.extra > 0 && /* @__PURE__ */ n("span", { className: "text-amber-600 ml-2", children: [
|
|
1929
|
+
a.extra,
|
|
1930
|
+
" extra"
|
|
1931
|
+
] })
|
|
1932
|
+
] }, i);
|
|
1933
|
+
}) });
|
|
1934
|
+
}
|
|
1935
|
+
function ft(t) {
|
|
1936
|
+
return Object.values(t.cells).some((s) => s === "diff" || s === "missing" || s === "extra");
|
|
1937
|
+
}
|
|
1938
|
+
function On({
|
|
1939
|
+
originConfigId: t,
|
|
1940
|
+
destConfigIds: s,
|
|
1941
|
+
apiPath: i = "/release-status"
|
|
1942
|
+
}) {
|
|
1943
|
+
const { toast: a } = oe(), { fetchJson: r } = te(), { configs: d } = be(), l = de(), [m, h] = R("issues"), [b, x] = R(!1), [c, p] = R(null), [P, M] = R(/* @__PURE__ */ new Set()), [D, Q] = R(() => /* @__PURE__ */ new Set()), U = (y) => Q((O) => {
|
|
1944
|
+
const T = new Set(O);
|
|
1945
|
+
return T.has(y) ? T.delete(y) : T.add(y), T;
|
|
1946
|
+
}), j = q(() => {
|
|
1947
|
+
const y = /* @__PURE__ */ new Map();
|
|
1948
|
+
return d.forEach((O) => y.set(O.id, O.displayName)), y;
|
|
1949
|
+
}, [d]), Y = (y) => j.get(y) ?? y, B = s.filter((y) => !P.has(y)), k = new URLSearchParams();
|
|
1950
|
+
k.set("originConfigId", t), B.forEach((y) => k.append("destConfigIds[]", y));
|
|
1951
|
+
const C = ["imaginarium", "release-status", t, B], { data: $, isLoading: g, isError: w } = ae({
|
|
1952
|
+
queryKey: C,
|
|
1953
|
+
queryFn: () => r(`${i}?${k.toString()}`),
|
|
1954
|
+
enabled: B.length > 0
|
|
1955
|
+
}), V = _({
|
|
1956
|
+
mutationFn: () => r(`${i}/refresh`, {
|
|
1957
|
+
method: "POST",
|
|
1958
|
+
body: JSON.stringify({ originConfigId: t, destConfigIds: B })
|
|
1959
|
+
}),
|
|
1960
|
+
onSuccess: () => {
|
|
1961
|
+
l.invalidateQueries({ queryKey: C }), a({ title: "Cache cleared", description: "Refreshing comparison data…" });
|
|
1962
|
+
},
|
|
1963
|
+
onError: (y) => {
|
|
1964
|
+
a({ title: "Error", description: y.message, variant: "destructive" });
|
|
1965
|
+
}
|
|
1966
|
+
}), {
|
|
1967
|
+
data: L,
|
|
1968
|
+
isLoading: X,
|
|
1969
|
+
isError: f
|
|
1970
|
+
} = ae({
|
|
1971
|
+
queryKey: ["imaginarium", "release-status-diff", t, c == null ? void 0 : c.destConfigId, c == null ? void 0 : c.itemKey],
|
|
1972
|
+
queryFn: () => r(
|
|
1973
|
+
`${i}/diff?originConfigId=${encodeURIComponent(t)}&destConfigId=${encodeURIComponent(c.destConfigId)}&itemKey=${encodeURIComponent(c.itemKey)}`
|
|
1974
|
+
),
|
|
1975
|
+
enabled: !!c
|
|
1976
|
+
}), F = (y) => {
|
|
1977
|
+
M((O) => {
|
|
1978
|
+
const T = new Set(O);
|
|
1979
|
+
return T.has(y) ? T.delete(y) : T.add(y), T;
|
|
1980
|
+
});
|
|
1981
|
+
}, J = (y, O) => {
|
|
1982
|
+
p(
|
|
1983
|
+
(T) => (T == null ? void 0 : T.itemKey) === y && T.destConfigId === O ? null : { itemKey: y, destConfigId: O }
|
|
1984
|
+
);
|
|
1985
|
+
}, A = ($ == null ? void 0 : $.rows) ?? [], H = ($ == null ? void 0 : $.stats) ?? {}, z = q(() => kn(A).map((O) => {
|
|
1986
|
+
const T = m === "issues" ? O.children.filter(ft) : O.children;
|
|
1987
|
+
return { node: O, renderChildren: T };
|
|
1988
|
+
}).filter(
|
|
1989
|
+
({ node: O, renderChildren: T }) => m === "all" || ft(O.row) || T.length > 0
|
|
1990
|
+
).sort((O, T) => {
|
|
1991
|
+
const ee = Je(O.node.row.itemType, T.node.row.itemType);
|
|
1992
|
+
return ee !== 0 ? ee : O.node.row.itemName.localeCompare(T.node.row.itemName);
|
|
1993
|
+
}), [A, m]);
|
|
1994
|
+
return /* @__PURE__ */ n("div", { className: "space-y-3", children: [
|
|
1995
|
+
/* @__PURE__ */ n("div", { className: "flex items-center gap-2 flex-wrap", children: [
|
|
1996
|
+
/* @__PURE__ */ n("div", { className: "flex rounded-md border text-sm overflow-hidden", children: [
|
|
1997
|
+
/* @__PURE__ */ e(
|
|
1998
|
+
"button",
|
|
1999
|
+
{
|
|
2000
|
+
className: ce("px-3 py-1.5", m === "issues" ? "bg-muted font-medium" : "hover:bg-muted/50"),
|
|
2001
|
+
onClick: () => h("issues"),
|
|
2002
|
+
children: "Issues only"
|
|
2003
|
+
}
|
|
2004
|
+
),
|
|
2005
|
+
/* @__PURE__ */ e(
|
|
2006
|
+
"button",
|
|
2007
|
+
{
|
|
2008
|
+
className: ce("px-3 py-1.5 border-l", m === "all" ? "bg-muted font-medium" : "hover:bg-muted/50"),
|
|
2009
|
+
onClick: () => h("all"),
|
|
2010
|
+
children: "All"
|
|
2011
|
+
}
|
|
2012
|
+
)
|
|
2013
|
+
] }),
|
|
2014
|
+
/* @__PURE__ */ n(E, { variant: "ghost", size: "sm", onClick: () => x((y) => !y), children: [
|
|
2015
|
+
/* @__PURE__ */ e(Jt, {}),
|
|
2016
|
+
"Stats"
|
|
2017
|
+
] }),
|
|
2018
|
+
/* @__PURE__ */ n(
|
|
2019
|
+
E,
|
|
2020
|
+
{
|
|
2021
|
+
variant: "ghost",
|
|
2022
|
+
size: "sm",
|
|
2023
|
+
onClick: () => V.mutate(),
|
|
2024
|
+
disabled: V.isPending,
|
|
2025
|
+
children: [
|
|
2026
|
+
/* @__PURE__ */ e(vt, { className: ce(V.isPending && "animate-spin") }),
|
|
2027
|
+
"Refresh"
|
|
2028
|
+
]
|
|
2029
|
+
}
|
|
2030
|
+
),
|
|
2031
|
+
[...P].map((y) => /* @__PURE__ */ n(
|
|
2032
|
+
"button",
|
|
2033
|
+
{
|
|
2034
|
+
onClick: () => F(y),
|
|
2035
|
+
className: "text-xs border rounded px-2 py-1 text-muted-foreground hover:bg-muted",
|
|
2036
|
+
children: [
|
|
2037
|
+
"+ ",
|
|
2038
|
+
Y(y)
|
|
2039
|
+
]
|
|
2040
|
+
},
|
|
2041
|
+
y
|
|
2042
|
+
))
|
|
2043
|
+
] }),
|
|
2044
|
+
b && $ && /* @__PURE__ */ e($n, { stats: H, destConfigIds: B }),
|
|
2045
|
+
g && /* @__PURE__ */ e("div", { className: "text-center text-muted-foreground py-8", children: "Loading…" }),
|
|
2046
|
+
w && /* @__PURE__ */ e("div", { className: "text-center text-destructive py-8", children: "Failed to load comparison data." }),
|
|
2047
|
+
!g && !w && /* @__PURE__ */ n("div", { className: "flex gap-4", children: [
|
|
2048
|
+
/* @__PURE__ */ e("div", { className: "min-w-0 flex-1 rounded-md border overflow-auto max-h-[70vh]", children: /* @__PURE__ */ n("table", { className: "w-full text-sm", children: [
|
|
2049
|
+
/* @__PURE__ */ e("thead", { children: /* @__PURE__ */ n("tr", { className: "border-b bg-muted/50", children: [
|
|
2050
|
+
/* @__PURE__ */ e("th", { className: "sticky top-0 z-10 bg-muted px-4 py-2 text-left font-medium min-w-[200px]", children: "Item" }),
|
|
2051
|
+
B.map((y) => /* @__PURE__ */ e("th", { className: "sticky top-0 z-10 bg-muted px-2 py-2 text-center font-medium min-w-[80px]", children: /* @__PURE__ */ n("div", { className: "flex items-center justify-center gap-1", children: [
|
|
2052
|
+
/* @__PURE__ */ e("span", { className: "truncate max-w-[120px]", title: Y(y), children: Y(y) }),
|
|
2053
|
+
/* @__PURE__ */ e(
|
|
2054
|
+
"button",
|
|
2055
|
+
{
|
|
2056
|
+
className: "text-muted-foreground hover:text-foreground",
|
|
2057
|
+
onClick: () => F(y),
|
|
2058
|
+
title: "Hide column",
|
|
2059
|
+
children: "×"
|
|
2060
|
+
}
|
|
2061
|
+
)
|
|
2062
|
+
] }) }, y))
|
|
2063
|
+
] }) }),
|
|
2064
|
+
/* @__PURE__ */ e("tbody", { children: z.length === 0 ? /* @__PURE__ */ e("tr", { children: /* @__PURE__ */ e("td", { colSpan: B.length + 1, className: "text-center text-muted-foreground py-8", children: m === "issues" ? "No issues found — all clusters in sync." : "No items." }) }) : z.map(({ node: y, renderChildren: O }) => {
|
|
2065
|
+
const T = y.row, ee = O.length > 0, ne = D.has(T.itemKey) || m === "issues", pe = D.has(T.itemKey);
|
|
2066
|
+
return /* @__PURE__ */ n(yt, { children: [
|
|
2067
|
+
/* @__PURE__ */ n("tr", { className: "border-b last:border-0 hover:bg-muted/25", children: [
|
|
2068
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-1.5", children: /* @__PURE__ */ n("div", { className: "flex items-center gap-2", children: [
|
|
2069
|
+
ee ? /* @__PURE__ */ e(
|
|
2070
|
+
"button",
|
|
2071
|
+
{
|
|
2072
|
+
type: "button",
|
|
2073
|
+
className: "text-muted-foreground hover:text-foreground",
|
|
2074
|
+
onClick: () => U(T.itemKey),
|
|
2075
|
+
"aria-label": pe ? "Collapse" : "Expand",
|
|
2076
|
+
children: pe ? /* @__PURE__ */ e(ue, { size: 14 }) : /* @__PURE__ */ e(he, { size: 14 })
|
|
2077
|
+
}
|
|
2078
|
+
) : null,
|
|
2079
|
+
/* @__PURE__ */ e("span", { className: "inline-flex align-middle", children: /* @__PURE__ */ e(xe, { type: T.itemType }) }),
|
|
2080
|
+
/* @__PURE__ */ e("span", { className: "font-medium", children: T.itemName })
|
|
2081
|
+
] }) }),
|
|
2082
|
+
B.map((G) => /* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e(
|
|
2083
|
+
pt,
|
|
2084
|
+
{
|
|
2085
|
+
state: T.cells[G] ?? "match",
|
|
2086
|
+
active: (c == null ? void 0 : c.itemKey) === T.itemKey && c.destConfigId === G,
|
|
2087
|
+
onClick: () => J(T.itemKey, G)
|
|
2088
|
+
}
|
|
2089
|
+
) }, G))
|
|
2090
|
+
] }),
|
|
2091
|
+
ee && ne ? O.map((G) => /* @__PURE__ */ n("tr", { className: "border-b last:border-0 hover:bg-muted/25", children: [
|
|
2092
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-1.5 pl-8", children: /* @__PURE__ */ n("div", { className: "flex items-center gap-2", children: [
|
|
2093
|
+
/* @__PURE__ */ e("span", { className: "inline-flex align-middle", children: /* @__PURE__ */ e(xe, { type: G.itemType }) }),
|
|
2094
|
+
/* @__PURE__ */ e("span", { className: "font-medium", children: G.itemName })
|
|
2095
|
+
] }) }),
|
|
2096
|
+
B.map((me) => /* @__PURE__ */ e("td", { className: "px-2 py-1", children: /* @__PURE__ */ e(
|
|
2097
|
+
pt,
|
|
2098
|
+
{
|
|
2099
|
+
state: G.cells[me] ?? "match",
|
|
2100
|
+
active: (c == null ? void 0 : c.itemKey) === G.itemKey && c.destConfigId === me,
|
|
2101
|
+
onClick: () => J(G.itemKey, me)
|
|
2102
|
+
}
|
|
2103
|
+
) }, me))
|
|
2104
|
+
] }, G.itemKey)) : null
|
|
2105
|
+
] }, T.itemKey);
|
|
2106
|
+
}) })
|
|
2107
|
+
] }) }),
|
|
2108
|
+
c ? /* @__PURE__ */ e("div", { className: "w-[28rem] shrink-0 self-start sticky top-4 max-h-[calc(100vh-2rem)] overflow-auto", children: X ? /* @__PURE__ */ e("div", { className: "flex h-full items-center justify-center rounded-md border bg-background p-4 text-sm text-muted-foreground", children: "Loading diff…" }) : f || !L ? /* @__PURE__ */ e("div", { className: "flex h-full items-center justify-center rounded-md border bg-background p-4 text-sm text-muted-foreground", children: "No diff available." }) : /* @__PURE__ */ e(
|
|
2109
|
+
Pt,
|
|
2110
|
+
{
|
|
2111
|
+
item: {
|
|
2112
|
+
itemName: L.itemName,
|
|
2113
|
+
itemType: L.itemType,
|
|
2114
|
+
diff: { origin: L.origin, target: L.target }
|
|
2115
|
+
},
|
|
2116
|
+
onClose: () => p(null)
|
|
2117
|
+
}
|
|
2118
|
+
) }) : null
|
|
2119
|
+
] })
|
|
2120
|
+
] });
|
|
2121
|
+
}
|
|
2122
|
+
const gt = (t) => ({
|
|
2123
|
+
name: "",
|
|
2124
|
+
description: "",
|
|
2125
|
+
values: Object.fromEntries(t.map((s) => [s, ""]))
|
|
2126
|
+
});
|
|
2127
|
+
function In({
|
|
2128
|
+
configIds: t,
|
|
2129
|
+
clusterNames: s = {},
|
|
2130
|
+
apiPath: i = "/release-translations"
|
|
2131
|
+
}) {
|
|
2132
|
+
const { toast: a } = oe(), { fetchJson: r } = te(), d = de(), [l, m] = R(!1), [h, b] = R(null), [x, c] = R(gt(t)), [p, P] = R(() => /* @__PURE__ */ new Set()), M = (f) => {
|
|
2133
|
+
P((F) => {
|
|
2134
|
+
const J = new Set(F);
|
|
2135
|
+
return J.has(f) ? J.delete(f) : J.add(f), J;
|
|
2136
|
+
});
|
|
2137
|
+
}, D = ["imaginarium", "release-translations"], { data: Q, isLoading: U } = ae({
|
|
2138
|
+
queryKey: D,
|
|
2139
|
+
queryFn: async () => {
|
|
2140
|
+
const f = await r(i);
|
|
2141
|
+
return (f == null ? void 0 : f.items) ?? [];
|
|
2142
|
+
}
|
|
2143
|
+
}), j = _({
|
|
2144
|
+
mutationFn: async (f) => {
|
|
2145
|
+
const F = await r(i, {
|
|
2146
|
+
method: "POST",
|
|
2147
|
+
body: JSON.stringify({ name: f.name.trim(), description: f.description.trim() || null })
|
|
2148
|
+
});
|
|
2149
|
+
await k(F.id, f.values);
|
|
2150
|
+
},
|
|
2151
|
+
onSuccess: () => {
|
|
2152
|
+
d.invalidateQueries({ queryKey: D }), a({ title: "Translation created" }), g();
|
|
2153
|
+
},
|
|
2154
|
+
onError: (f) => a({ title: "Error", description: f.message, variant: "destructive" })
|
|
2155
|
+
}), Y = _({
|
|
2156
|
+
mutationFn: async (f) => {
|
|
2157
|
+
await r(`${i}/${h.id}`, {
|
|
2158
|
+
method: "PATCH",
|
|
2159
|
+
body: JSON.stringify({ name: f.name.trim(), description: f.description.trim() || null })
|
|
2160
|
+
}), await k(h.id, f.values);
|
|
2161
|
+
},
|
|
2162
|
+
onSuccess: () => {
|
|
2163
|
+
d.invalidateQueries({ queryKey: D }), a({ title: "Translation updated" }), g();
|
|
2164
|
+
},
|
|
2165
|
+
onError: (f) => a({ title: "Error", description: f.message, variant: "destructive" })
|
|
2166
|
+
}), B = _({
|
|
2167
|
+
mutationFn: (f) => r(`${i}/${f}`, { method: "DELETE" }),
|
|
2168
|
+
onSuccess: () => {
|
|
2169
|
+
d.invalidateQueries({ queryKey: D }), a({ title: "Translation deleted" });
|
|
2170
|
+
},
|
|
2171
|
+
onError: (f) => a({ title: "Error", description: f.message, variant: "destructive" })
|
|
2172
|
+
});
|
|
2173
|
+
async function k(f, F) {
|
|
2174
|
+
var A;
|
|
2175
|
+
const J = (h == null ? void 0 : h.values) ?? [];
|
|
2176
|
+
for (const H of t) {
|
|
2177
|
+
const z = (A = F[H]) == null ? void 0 : A.trim(), y = J.find((T) => T.configId === H), O = `${i}/${f}/values`;
|
|
2178
|
+
y && z ? await r(`${O}/${y.id}`, {
|
|
2179
|
+
method: "PATCH",
|
|
2180
|
+
body: JSON.stringify({ value: z })
|
|
2181
|
+
}) : y && !z ? await r(`${O}/${y.id}`, { method: "DELETE" }) : !y && z && await r(O, {
|
|
2182
|
+
method: "POST",
|
|
2183
|
+
body: JSON.stringify({ translationId: f, configId: H, value: z })
|
|
2184
|
+
});
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
const C = () => {
|
|
2188
|
+
b(null), c(gt(t)), m(!0);
|
|
2189
|
+
}, $ = (f) => {
|
|
2190
|
+
b(f);
|
|
2191
|
+
const F = f.values ?? [], J = Object.fromEntries(
|
|
2192
|
+
t.map((A) => {
|
|
2193
|
+
var H;
|
|
2194
|
+
return [A, ((H = F.find((z) => z.configId === A)) == null ? void 0 : H.value) ?? ""];
|
|
2195
|
+
})
|
|
2196
|
+
);
|
|
2197
|
+
c({ name: f.name, description: f.description ?? "", values: J }), m(!0);
|
|
2198
|
+
}, g = () => {
|
|
2199
|
+
m(!1), b(null);
|
|
2200
|
+
}, w = () => {
|
|
2201
|
+
h ? Y.mutate(x) : j.mutate(x);
|
|
2202
|
+
}, V = j.isPending || Y.isPending, L = !!x.name.trim();
|
|
2203
|
+
if (U)
|
|
2204
|
+
return /* @__PURE__ */ e("div", { className: "text-center text-muted-foreground py-8", children: "Loading…" });
|
|
2205
|
+
const X = [...Q ?? []].sort(
|
|
2206
|
+
(f, F) => f.name.localeCompare(F.name, void 0, { sensitivity: "base" })
|
|
2207
|
+
);
|
|
2208
|
+
return /* @__PURE__ */ n("div", { className: "space-y-4", children: [
|
|
2209
|
+
/* @__PURE__ */ n("div", { className: "flex items-center justify-between", children: [
|
|
2210
|
+
/* @__PURE__ */ e("p", { className: "text-sm text-muted-foreground", children: X.length === 0 ? "No translation rules yet." : `${X.length} translation rule${X.length === 1 ? "" : "s"}.` }),
|
|
2211
|
+
/* @__PURE__ */ n(E, { size: "sm", onClick: C, children: [
|
|
2212
|
+
/* @__PURE__ */ e(je, {}),
|
|
2213
|
+
"Add translation"
|
|
2214
|
+
] })
|
|
2215
|
+
] }),
|
|
2216
|
+
X.length > 0 && /* @__PURE__ */ e("div", { className: "rounded-md border divide-y text-sm", children: X.map((f) => {
|
|
2217
|
+
const F = p.has(f.id), J = f.values ?? [], A = (z) => {
|
|
2218
|
+
var y;
|
|
2219
|
+
return ((y = J.find((O) => O.configId === z)) == null ? void 0 : y.value) ?? "";
|
|
2220
|
+
}, H = t.filter((z) => A(z)).length;
|
|
2221
|
+
return /* @__PURE__ */ n("div", { children: [
|
|
2222
|
+
/* @__PURE__ */ n("div", { className: "flex items-center gap-3 px-4 py-2 hover:bg-muted/25", children: [
|
|
2223
|
+
/* @__PURE__ */ n(
|
|
2224
|
+
"button",
|
|
2225
|
+
{
|
|
2226
|
+
type: "button",
|
|
2227
|
+
onClick: () => M(f.id),
|
|
2228
|
+
"aria-expanded": F,
|
|
2229
|
+
className: "flex flex-1 min-w-0 items-center gap-3 text-left",
|
|
2230
|
+
children: [
|
|
2231
|
+
F ? /* @__PURE__ */ e(ue, { className: "size-4 shrink-0 text-muted-foreground" }) : /* @__PURE__ */ e(he, { className: "size-4 shrink-0 text-muted-foreground" }),
|
|
2232
|
+
/* @__PURE__ */ n("div", { className: "min-w-0 flex-1", children: [
|
|
2233
|
+
/* @__PURE__ */ e("div", { className: "font-medium", children: f.name }),
|
|
2234
|
+
f.description && /* @__PURE__ */ e("div", { className: "truncate text-xs text-muted-foreground", children: f.description })
|
|
2235
|
+
] }),
|
|
2236
|
+
/* @__PURE__ */ n("div", { className: "shrink-0 whitespace-nowrap text-xs text-muted-foreground", children: [
|
|
2237
|
+
H,
|
|
2238
|
+
" of ",
|
|
2239
|
+
t.length,
|
|
2240
|
+
" set"
|
|
2241
|
+
] })
|
|
2242
|
+
]
|
|
2243
|
+
}
|
|
2244
|
+
),
|
|
2245
|
+
/* @__PURE__ */ n("div", { className: "flex shrink-0 gap-1", children: [
|
|
2246
|
+
/* @__PURE__ */ e(E, { variant: "ghost", size: "icon", onClick: () => $(f), children: /* @__PURE__ */ e(Qt, {}) }),
|
|
2247
|
+
/* @__PURE__ */ e(
|
|
2248
|
+
E,
|
|
2249
|
+
{
|
|
2250
|
+
variant: "ghost",
|
|
2251
|
+
size: "icon",
|
|
2252
|
+
onClick: () => {
|
|
2253
|
+
window.confirm(`Delete translation "${f.name}"?`) && B.mutate(f.id);
|
|
2254
|
+
},
|
|
2255
|
+
children: /* @__PURE__ */ e(wt, {})
|
|
2256
|
+
}
|
|
2257
|
+
)
|
|
2258
|
+
] })
|
|
2259
|
+
] }),
|
|
2260
|
+
F && /* @__PURE__ */ e("div", { className: "space-y-1 px-4 pb-3 pl-11", children: t.map((z) => /* @__PURE__ */ n("div", { className: "grid grid-cols-[10rem_1fr] gap-2 text-xs", children: [
|
|
2261
|
+
/* @__PURE__ */ e("span", { className: "text-muted-foreground", children: s[z] ?? z }),
|
|
2262
|
+
/* @__PURE__ */ e("span", { className: "break-all font-mono", children: A(z) || /* @__PURE__ */ e("span", { className: "text-muted-foreground", children: "—" }) })
|
|
2263
|
+
] }, z)) })
|
|
2264
|
+
] }, f.id);
|
|
2265
|
+
}) }),
|
|
2266
|
+
/* @__PURE__ */ e(ve, { open: l, onOpenChange: m, children: /* @__PURE__ */ n(we, { className: "max-w-lg", children: [
|
|
2267
|
+
/* @__PURE__ */ n(ke, { children: [
|
|
2268
|
+
/* @__PURE__ */ e(Ce, { children: h ? `Edit ${h.name}` : "New Translation Rule" }),
|
|
2269
|
+
/* @__PURE__ */ e(Te, { children: "Set the equivalent values for each cluster. Rules with values on only one side of a pair are silently skipped for that comparison." })
|
|
2270
|
+
] }),
|
|
2271
|
+
/* @__PURE__ */ n("div", { className: "space-y-4 py-2", children: [
|
|
2272
|
+
/* @__PURE__ */ n("div", { className: "space-y-2", children: [
|
|
2273
|
+
/* @__PURE__ */ e(le, { htmlFor: "tr-name", children: "Name" }),
|
|
2274
|
+
/* @__PURE__ */ e(
|
|
2275
|
+
ge,
|
|
2276
|
+
{
|
|
2277
|
+
id: "tr-name",
|
|
2278
|
+
value: x.name,
|
|
2279
|
+
onChange: (f) => c({ ...x, name: f.target.value }),
|
|
2280
|
+
placeholder: "key (ex. molten-url)"
|
|
2281
|
+
}
|
|
2282
|
+
)
|
|
2283
|
+
] }),
|
|
2284
|
+
/* @__PURE__ */ n("div", { className: "space-y-2", children: [
|
|
2285
|
+
/* @__PURE__ */ e(le, { htmlFor: "tr-desc", children: "Description (optional)" }),
|
|
2286
|
+
/* @__PURE__ */ e(
|
|
2287
|
+
ge,
|
|
2288
|
+
{
|
|
2289
|
+
id: "tr-desc",
|
|
2290
|
+
value: x.description,
|
|
2291
|
+
onChange: (f) => c({ ...x, description: f.target.value }),
|
|
2292
|
+
placeholder: "Explain what this value represents"
|
|
2293
|
+
}
|
|
2294
|
+
)
|
|
2295
|
+
] }),
|
|
2296
|
+
/* @__PURE__ */ n("div", { className: "space-y-3 pt-1", children: [
|
|
2297
|
+
/* @__PURE__ */ e("p", { className: "text-sm font-medium", children: "Values per cluster" }),
|
|
2298
|
+
t.map((f) => /* @__PURE__ */ n("div", { className: "space-y-1", children: [
|
|
2299
|
+
/* @__PURE__ */ e(le, { htmlFor: `tr-val-${f}`, className: "text-xs text-muted-foreground", children: s[f] ?? f }),
|
|
2300
|
+
/* @__PURE__ */ e(
|
|
2301
|
+
ge,
|
|
2302
|
+
{
|
|
2303
|
+
id: `tr-val-${f}`,
|
|
2304
|
+
value: x.values[f] ?? "",
|
|
2305
|
+
onChange: (F) => c({
|
|
2306
|
+
...x,
|
|
2307
|
+
values: { ...x.values, [f]: F.target.value }
|
|
2308
|
+
}),
|
|
2309
|
+
placeholder: "Leave blank to remove",
|
|
2310
|
+
className: "font-mono text-xs"
|
|
2311
|
+
}
|
|
2312
|
+
)
|
|
2313
|
+
] }, f))
|
|
2314
|
+
] })
|
|
2315
|
+
] }),
|
|
2316
|
+
/* @__PURE__ */ n(Pe, { children: [
|
|
2317
|
+
/* @__PURE__ */ n(E, { variant: "outline", onClick: g, children: [
|
|
2318
|
+
/* @__PURE__ */ e(Ne, {}),
|
|
2319
|
+
"Cancel"
|
|
2320
|
+
] }),
|
|
2321
|
+
/* @__PURE__ */ n(E, { onClick: w, disabled: !L || V, children: [
|
|
2322
|
+
/* @__PURE__ */ e(bt, {}),
|
|
2323
|
+
V ? "Saving…" : "Save"
|
|
2324
|
+
] })
|
|
2325
|
+
] })
|
|
2326
|
+
] }) })
|
|
2327
|
+
] });
|
|
2328
|
+
}
|
|
2329
|
+
function Rn({
|
|
2330
|
+
originConfigId: t,
|
|
2331
|
+
apiPath: s = "/release-ignores"
|
|
2332
|
+
}) {
|
|
2333
|
+
const { toast: i } = oe(), { fetchJson: a } = te(), r = de(), d = ["imaginarium", "release-ignores", t], { data: l, isLoading: m } = ae({
|
|
2334
|
+
queryKey: d,
|
|
2335
|
+
queryFn: async () => {
|
|
2336
|
+
const p = await a(
|
|
2337
|
+
`${s}?where[originConfigId]=${encodeURIComponent(t)}`
|
|
2338
|
+
);
|
|
2339
|
+
return (p == null ? void 0 : p.items) ?? [];
|
|
2340
|
+
}
|
|
2341
|
+
}), h = _({
|
|
2342
|
+
mutationFn: (p) => a(`${s}/${p}`, { method: "DELETE" }),
|
|
2343
|
+
onSuccess: () => {
|
|
2344
|
+
r.invalidateQueries({ queryKey: d }), i({ title: "Item removed from ignore list" });
|
|
2345
|
+
},
|
|
2346
|
+
onError: (p) => {
|
|
2347
|
+
i({ title: "Error", description: p.message, variant: "destructive" });
|
|
2348
|
+
}
|
|
2349
|
+
}), b = _({
|
|
2350
|
+
mutationFn: () => a(`${s}?originConfigId=${encodeURIComponent(t)}`, {
|
|
2351
|
+
method: "DELETE"
|
|
2352
|
+
}),
|
|
2353
|
+
onSuccess: () => {
|
|
2354
|
+
r.invalidateQueries({ queryKey: d }), i({ title: "All ignore rules cleared" });
|
|
2355
|
+
},
|
|
2356
|
+
onError: (p) => {
|
|
2357
|
+
i({ title: "Error", description: p.message, variant: "destructive" });
|
|
2358
|
+
}
|
|
2359
|
+
}), x = () => {
|
|
2360
|
+
window.confirm("Remove all ignore rules for this cluster? Items will appear normally in future snapshots.") && b.mutate();
|
|
2361
|
+
};
|
|
2362
|
+
if (m)
|
|
2363
|
+
return /* @__PURE__ */ e("div", { className: "text-center text-muted-foreground py-8", children: "Loading…" });
|
|
2364
|
+
const c = l ?? [];
|
|
2365
|
+
return /* @__PURE__ */ n("div", { className: "space-y-4", children: [
|
|
2366
|
+
/* @__PURE__ */ n("div", { className: "flex items-center justify-between", children: [
|
|
2367
|
+
/* @__PURE__ */ e("p", { className: "text-sm text-muted-foreground", children: c.length === 0 ? "No items are permanently ignored." : `${c.length} item${c.length === 1 ? "" : "s"} permanently ignored for this cluster.` }),
|
|
2368
|
+
c.length > 0 && /* @__PURE__ */ n(
|
|
2369
|
+
E,
|
|
2370
|
+
{
|
|
2371
|
+
variant: "outline",
|
|
2372
|
+
size: "sm",
|
|
2373
|
+
onClick: x,
|
|
2374
|
+
disabled: b.isPending,
|
|
2375
|
+
children: [
|
|
2376
|
+
/* @__PURE__ */ e(Be, {}),
|
|
2377
|
+
b.isPending ? "Clearing…" : "Clear all"
|
|
2378
|
+
]
|
|
2379
|
+
}
|
|
2380
|
+
)
|
|
2381
|
+
] }),
|
|
2382
|
+
c.length > 0 && /* @__PURE__ */ e("div", { className: "rounded-md border", children: /* @__PURE__ */ n("table", { className: "w-full text-sm", children: [
|
|
2383
|
+
/* @__PURE__ */ e("thead", { children: /* @__PURE__ */ n("tr", { className: "border-b bg-muted/50", children: [
|
|
2384
|
+
/* @__PURE__ */ e("th", { className: "px-4 py-2 text-left font-medium", children: "Type" }),
|
|
2385
|
+
/* @__PURE__ */ e("th", { className: "px-4 py-2 text-left font-medium", children: "Name" }),
|
|
2386
|
+
/* @__PURE__ */ e("th", { className: "px-4 py-2 text-left font-medium", children: "Reason" }),
|
|
2387
|
+
/* @__PURE__ */ e("th", { className: "px-4 py-2 text-right font-medium" })
|
|
2388
|
+
] }) }),
|
|
2389
|
+
/* @__PURE__ */ e("tbody", { children: c.map((p) => /* @__PURE__ */ n("tr", { className: "border-b last:border-0 hover:bg-muted/25", children: [
|
|
2390
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-muted-foreground font-mono text-xs", children: p.itemType }),
|
|
2391
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-2 font-medium", children: p.itemName }),
|
|
2392
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-muted-foreground", children: p.reason ?? /* @__PURE__ */ e("span", { className: "italic text-xs", children: "—" }) }),
|
|
2393
|
+
/* @__PURE__ */ e("td", { className: "px-4 py-2 text-right", children: /* @__PURE__ */ e(
|
|
2394
|
+
E,
|
|
2395
|
+
{
|
|
2396
|
+
variant: "ghost",
|
|
2397
|
+
size: "icon",
|
|
2398
|
+
title: "Remove from ignore list",
|
|
2399
|
+
onClick: () => h.mutate(p.id),
|
|
2400
|
+
disabled: h.isPending,
|
|
2401
|
+
children: /* @__PURE__ */ e(wt, {})
|
|
2402
|
+
}
|
|
2403
|
+
) })
|
|
2404
|
+
] }, p.id)) })
|
|
2405
|
+
] }) })
|
|
2406
|
+
] });
|
|
2407
|
+
}
|
|
2408
|
+
function An(t, s) {
|
|
2409
|
+
return [...t].sort(
|
|
2410
|
+
(i, a) => (s[i] ?? i).localeCompare(s[a] ?? a, void 0, { sensitivity: "base" })
|
|
2411
|
+
);
|
|
2412
|
+
}
|
|
2413
|
+
const xt = ["dev", "stg", "prd"];
|
|
2414
|
+
function Mn(t) {
|
|
2415
|
+
const s = (t.tags ?? []).map((a) => a.toLowerCase()), i = xt.findIndex((a) => s.includes(a));
|
|
2416
|
+
return i === -1 ? xt.length : i;
|
|
2417
|
+
}
|
|
2418
|
+
function Dn(t) {
|
|
2419
|
+
const s = Object.fromEntries(t.map((r) => [r.id, r.displayName])), i = /* @__PURE__ */ new Map();
|
|
2420
|
+
for (const r of t) {
|
|
2421
|
+
const d = Mn(r);
|
|
2422
|
+
i.has(d) || i.set(d, []), i.get(d).push(r.id);
|
|
2423
|
+
}
|
|
2424
|
+
return [...i.keys()].sort((r, d) => r - d).flatMap((r) => An(i.get(r), s));
|
|
2425
|
+
}
|
|
2426
|
+
const Fn = [
|
|
2427
|
+
{ id: "releases", label: "Releases" },
|
|
2428
|
+
{ id: "status", label: "Status" },
|
|
2429
|
+
{ id: "translations", label: "Translations" },
|
|
2430
|
+
{ id: "ignored", label: "Ignored" }
|
|
2431
|
+
];
|
|
2432
|
+
function qn() {
|
|
2433
|
+
var c;
|
|
2434
|
+
const [t, s] = R("releases"), [i, a] = R(null), { configs: r } = be(), [d, l] = R("");
|
|
2435
|
+
Qe(() => {
|
|
2436
|
+
!d && r.length > 0 && l(r[0].id);
|
|
2437
|
+
}, [d, r]);
|
|
2438
|
+
const m = q(() => {
|
|
2439
|
+
const p = {};
|
|
2440
|
+
return r.forEach((P) => {
|
|
2441
|
+
p[P.id] = P.displayName;
|
|
2442
|
+
}), p;
|
|
2443
|
+
}, [r]), h = d || ((c = r[0]) == null ? void 0 : c.id) || "", b = q(() => Dn(r), [r]), x = b.filter((p) => p !== h);
|
|
2444
|
+
return /* @__PURE__ */ n("div", { className: "space-y-6", children: [
|
|
2445
|
+
/* @__PURE__ */ n("div", { children: [
|
|
2446
|
+
/* @__PURE__ */ e("h2", { className: "text-2xl font-semibold", children: "imp" }),
|
|
2447
|
+
/* @__PURE__ */ e("p", { className: "text-sm text-muted-foreground", children: "Manage releases across clusters" })
|
|
2448
|
+
] }),
|
|
2449
|
+
/* @__PURE__ */ e("div", { className: "flex items-center gap-1 border-b pb-2", children: Fn.map(({ id: p, label: P }) => /* @__PURE__ */ e(
|
|
2450
|
+
E,
|
|
2451
|
+
{
|
|
2452
|
+
variant: t === p ? "secondary" : "ghost",
|
|
2453
|
+
size: "sm",
|
|
2454
|
+
onClick: () => s(p),
|
|
2455
|
+
children: P
|
|
2456
|
+
},
|
|
2457
|
+
p
|
|
2458
|
+
)) }),
|
|
2459
|
+
t === "releases" && (i == null ? /* @__PURE__ */ e(Xt, { onOpen: a }) : /* @__PURE__ */ e(En, { releaseId: i, onBack: () => a(null) })),
|
|
2460
|
+
t === "status" && (r.length === 0 ? /* @__PURE__ */ e("div", { className: "text-muted-foreground", children: "No clusters configured." }) : /* @__PURE__ */ n("div", { className: "space-y-4", children: [
|
|
2461
|
+
/* @__PURE__ */ e("div", { className: "max-w-xs", children: /* @__PURE__ */ e(
|
|
2462
|
+
ut,
|
|
2463
|
+
{
|
|
2464
|
+
label: "Reference",
|
|
2465
|
+
value: h,
|
|
2466
|
+
onChange: l,
|
|
2467
|
+
configs: r
|
|
2468
|
+
}
|
|
2469
|
+
) }),
|
|
2470
|
+
h ? /* @__PURE__ */ e(On, { originConfigId: h, destConfigIds: x }) : /* @__PURE__ */ e("div", { className: "text-muted-foreground", children: "Select a reference cluster." })
|
|
2471
|
+
] })),
|
|
2472
|
+
t === "translations" && (r.length === 0 ? /* @__PURE__ */ e("div", { className: "text-muted-foreground", children: "No clusters configured." }) : /* @__PURE__ */ e(In, { configIds: b, clusterNames: m })),
|
|
2473
|
+
t === "ignored" && (r.length === 0 ? /* @__PURE__ */ e("div", { className: "text-muted-foreground", children: "No clusters configured." }) : /* @__PURE__ */ n("div", { className: "space-y-4", children: [
|
|
2474
|
+
/* @__PURE__ */ e("div", { className: "max-w-xs", children: /* @__PURE__ */ e(
|
|
2475
|
+
ut,
|
|
2476
|
+
{
|
|
2477
|
+
label: "Cluster",
|
|
2478
|
+
value: h,
|
|
2479
|
+
onChange: l,
|
|
2480
|
+
configs: r
|
|
2481
|
+
}
|
|
2482
|
+
) }),
|
|
2483
|
+
h ? /* @__PURE__ */ e(Rn, { originConfigId: h }) : /* @__PURE__ */ e("div", { className: "text-muted-foreground", children: "Select a cluster." })
|
|
2484
|
+
] }))
|
|
2485
|
+
] });
|
|
2486
|
+
}
|
|
2487
|
+
const zn = {
|
|
2488
|
+
id: "imaginarium.ui.ImpPage",
|
|
2489
|
+
path: "/imp",
|
|
2490
|
+
element: qn
|
|
2491
|
+
}, jn = {
|
|
2492
|
+
id: "imaginarium.ui.ImpNavItem",
|
|
2493
|
+
path: "/imp",
|
|
2494
|
+
label: "imp",
|
|
2495
|
+
icon: Vt,
|
|
2496
|
+
sort: 150
|
|
2497
|
+
}, Xn = {
|
|
2498
|
+
install(t) {
|
|
2499
|
+
t.addPlugin(Mt, zn), t.addPlugin(Dt, jn), qt.register(t, Wt);
|
|
2500
|
+
}
|
|
2501
|
+
};
|
|
2502
|
+
export {
|
|
2503
|
+
ut as C,
|
|
2504
|
+
Pt as D,
|
|
2505
|
+
xe as E,
|
|
2506
|
+
tn as I,
|
|
2507
|
+
Zt as P,
|
|
2508
|
+
En as R,
|
|
2509
|
+
On as S,
|
|
2510
|
+
lt as T,
|
|
2511
|
+
Gt as a,
|
|
2512
|
+
en as b,
|
|
2513
|
+
Rn as c,
|
|
2514
|
+
mn as d,
|
|
2515
|
+
sn as e,
|
|
2516
|
+
Xt as f,
|
|
2517
|
+
Xn as g,
|
|
2518
|
+
kt as h,
|
|
2519
|
+
qn as i,
|
|
2520
|
+
nn as j,
|
|
2521
|
+
In as k,
|
|
2522
|
+
vn as l,
|
|
2523
|
+
xn as m,
|
|
2524
|
+
Tn as n,
|
|
2525
|
+
Gn as o,
|
|
2526
|
+
kn as p,
|
|
2527
|
+
Cn as q,
|
|
2528
|
+
yn as r,
|
|
2529
|
+
bn as t,
|
|
2530
|
+
Ie as u
|
|
2531
|
+
};
|
|
2532
|
+
//# sourceMappingURL=PluginSetup-CBFwSR1s.js.map
|