@burdenoff/microfe-vibecontrols 2026.531.14 → 2026.531.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/docs/DocsTabPanel.js +146 -125
- package/dist/components/docs/DocsTabPanel.js.map +1 -1
- package/dist/components/notes/NotesTabPanel.js +1 -1
- package/dist/components/notes/NotesTabPanel.js.map +1 -1
- package/dist/components/shared/PluginGate.js +1 -1
- package/dist/components/shared/PluginGate.js.map +1 -1
- package/dist/components/tunnels/TunnelCreateWizard.js +1 -1
- package/dist/components/tunnels/TunnelCreateWizard.js.map +1 -1
- package/dist/pages/ActionsPage.js +1 -1
- package/dist/pages/ActionsPage.js.map +1 -1
- package/dist/pages/AgentDetailsPage.js +38 -37
- package/dist/pages/AgentDetailsPage.js.map +1 -1
- package/dist/pages/AgentsPage.js +1 -1
- package/dist/pages/AgentsPage.js.map +1 -1
- package/dist/pages/CatalogPage.js +1 -1
- package/dist/pages/CatalogPage.js.map +1 -1
- package/dist/pages/ComponentDetailPage.js +1 -1
- package/dist/pages/ComponentDetailPage.js.map +1 -1
- package/dist/pages/ComponentsPage.js +1 -1
- package/dist/pages/ComponentsPage.js.map +1 -1
- package/dist/pages/SessionDetailsPage.js +1 -1
- package/dist/pages/SessionDetailsPage.js.map +1 -1
- package/dist/pages/SessionsPage.js +1 -1
- package/dist/pages/SessionsPage.js.map +1 -1
- package/dist/pages/TargetsPage.js +1 -1
- package/dist/pages/TargetsPage.js.map +1 -1
- package/dist/pages/TemplateDetailPage.js +1 -1
- package/dist/pages/TemplateDetailPage.js.map +1 -1
- package/dist/pages/VibeDeckPage.js +1 -1
- package/dist/pages/VibeDeckPage.js.map +1 -1
- package/dist/pages/VibesPage.js +1 -1
- package/dist/pages/VibesPage.js.map +1 -1
- package/dist/pages/tunnels/TunnelsTab.js +1 -1
- package/dist/pages/tunnels/TunnelsTab.js.map +1 -1
- package/dist/providers/QuotaExhaustedProvider.js +1 -1
- package/dist/providers/QuotaExhaustedProvider.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import { useCompileDocsSiteMutation as e, useCreateDocsPageMutation as t, useCreateDocsSiteMutation as n, useDeleteDocsPageMutation as r, useDeleteDocsSiteMutation as
|
|
2
|
-
import { useTr as
|
|
3
|
-
import { QuotaExhaustedDialog as
|
|
4
|
-
import { isQuotaExhaustedError as
|
|
5
|
-
import { useVibeNavigate as
|
|
6
|
-
import { LoadingState as
|
|
7
|
-
import { ErrorState as
|
|
1
|
+
import { useCompileDocsSiteMutation as e, useCreateDocsPageMutation as t, useCreateDocsSiteMutation as n, useDeleteDocsPageMutation as r, useDeleteDocsSiteMutation as ee, useDocsContentQuery as te, useGenerateDocsSignedUrlMutation as ne, useGetDocsRevisionLazyQuery as i, useGetDocsSiteQuery as a, useRollbackDocsRevisionMutation as re, useUpdateDocsPageMutation as ie, useUpdateDocsSiteMutation as ae, useUpdateDocsSiteVisibilityMutation as oe } from "../../generated/wspace-operations.js";
|
|
2
|
+
import { useTr as se } from "../../shared/hooks/useTr.js";
|
|
3
|
+
import { QuotaExhaustedDialog as o } from "../shared/QuotaExhaustedDialog.js";
|
|
4
|
+
import { getQuotaDialogContent as s, isQuotaExhaustedError as c, markQuotaHandledLocally as l } from "../../utils/quotaUtils.js";
|
|
5
|
+
import { useVibeNavigate as u } from "../../providers/VibeControlsProvider.js";
|
|
6
|
+
import { LoadingState as d } from "../shared/LoadingState.js";
|
|
7
|
+
import { ErrorState as f } from "../shared/ErrorState.js";
|
|
8
8
|
import "../shared/index.js";
|
|
9
|
-
import { DocsEmptyState as
|
|
10
|
-
import { DocsPreviewPanel as
|
|
11
|
-
import { DocsEditPanel as
|
|
12
|
-
import { useEffect as
|
|
13
|
-
import { AlertCircle as
|
|
9
|
+
import { DocsEmptyState as p } from "./DocsEmptyState.js";
|
|
10
|
+
import { DocsPreviewPanel as m } from "./DocsPreviewPanel.js";
|
|
11
|
+
import { DocsEditPanel as h } from "./DocsEditPanel.js";
|
|
12
|
+
import { useEffect as g, useRef as _, useState as v } from "react";
|
|
13
|
+
import { AlertCircle as y, X as b } from "lucide-react";
|
|
14
14
|
import { Fragment as x, jsx as S, jsxs as C } from "react/jsx-runtime";
|
|
15
|
-
import { resolveGatewayUrls as
|
|
15
|
+
import { resolveGatewayUrls as ce } from "@burdenoff/fe-libs/shared/config";
|
|
16
16
|
//#region src/components/docs/DocsTabPanel.tsx
|
|
17
|
-
function w({ vibeId: w, ownerType:
|
|
18
|
-
let T =
|
|
17
|
+
function w({ vibeId: w, ownerType: le, ownerId: ue }) {
|
|
18
|
+
let T = se(), E = le || "VIBE", D = ue || w || "", [de, O] = v("preview"), [k, A] = v(null), [j, M] = v(!1), [N, P] = v(null), [F, I] = v(""), [L, R] = v(null), z = u(), [B, V] = v(!1), [H, U] = v(!1), { data: fe, loading: pe, error: W, refetch: G } = a({
|
|
19
19
|
variables: {
|
|
20
20
|
ownerType: E,
|
|
21
21
|
ownerId: D
|
|
22
22
|
},
|
|
23
23
|
skip: !D,
|
|
24
24
|
fetchPolicy: "cache-and-network"
|
|
25
|
-
}),
|
|
25
|
+
}), K = fe?.vibecontrolsDocsSiteByOwner ?? null, q = K?.pages || [], { data: me, loading: he, refetch: ge } = te({
|
|
26
26
|
variables: {
|
|
27
|
-
siteId:
|
|
28
|
-
path:
|
|
27
|
+
siteId: K?.id || "",
|
|
28
|
+
path: F
|
|
29
29
|
},
|
|
30
|
-
skip: !
|
|
30
|
+
skip: !K?.id || !K.currentRevisionId,
|
|
31
31
|
fetchPolicy: "network-only"
|
|
32
|
-
}),
|
|
33
|
-
|
|
34
|
-
let e =
|
|
35
|
-
if (
|
|
36
|
-
|
|
32
|
+
}), _e = me?.docsContent?.html ?? null, J = _(void 0);
|
|
33
|
+
g(() => {
|
|
34
|
+
let e = K?.currentRevisionId ?? null;
|
|
35
|
+
if (J.current === void 0) {
|
|
36
|
+
J.current = e;
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
|
-
e && e !==
|
|
40
|
-
}, [
|
|
41
|
-
let
|
|
39
|
+
e && e !== J.current && (J.current = e, ge());
|
|
40
|
+
}, [K?.currentRevisionId]);
|
|
41
|
+
let ve = ce(), ye = K?.workspaceId ? `${ve.workspaceBaseUrl}/workspaces/static/${K.workspaceId}/docs/${D}/` : null, [be, { loading: xe }] = n(), [Se] = ae(), [Ce] = oe(), [we, { loading: Te }] = t(), [Ee] = ie(), [De] = r(), [Oe] = e(), [ke] = ne(), [Ae] = re(), [je] = ee(), [Y] = i({ fetchPolicy: "network-only" }), Me = async (e = "DOCUSAURUS") => {
|
|
42
42
|
try {
|
|
43
|
-
await
|
|
43
|
+
await be({
|
|
44
44
|
variables: { input: {
|
|
45
45
|
ownerType: E,
|
|
46
46
|
ownerId: D,
|
|
@@ -49,24 +49,24 @@ function w({ vibeId: w, ownerType: ce, ownerId: le }) {
|
|
|
49
49
|
} },
|
|
50
50
|
refetchQueries: ["GetDocsSite"],
|
|
51
51
|
awaitRefetchQueries: !0
|
|
52
|
-
}),
|
|
52
|
+
}), O("edit");
|
|
53
53
|
} catch (e) {
|
|
54
|
-
if (
|
|
55
|
-
|
|
54
|
+
if (c(e)) {
|
|
55
|
+
l(), V(!0);
|
|
56
56
|
return;
|
|
57
57
|
}
|
|
58
58
|
throw e;
|
|
59
59
|
}
|
|
60
|
-
},
|
|
61
|
-
await
|
|
60
|
+
}, Ne = async (e, t) => {
|
|
61
|
+
await Ee({ variables: {
|
|
62
62
|
id: e,
|
|
63
63
|
input: t
|
|
64
64
|
} });
|
|
65
|
-
},
|
|
66
|
-
if (!
|
|
67
|
-
let n =
|
|
68
|
-
await
|
|
69
|
-
siteId:
|
|
65
|
+
}, Pe = async (e, t) => {
|
|
66
|
+
if (!K) return;
|
|
67
|
+
let n = q.length, r = `page-${n + 1}`;
|
|
68
|
+
await we({ variables: { input: {
|
|
69
|
+
siteId: K.id,
|
|
70
70
|
parentId: e || null,
|
|
71
71
|
slug: r,
|
|
72
72
|
title: `New Page ${n + 1}`,
|
|
@@ -74,33 +74,41 @@ function w({ vibeId: w, ownerType: ce, ownerId: le }) {
|
|
|
74
74
|
status: "DRAFT",
|
|
75
75
|
sidebarPosition: n,
|
|
76
76
|
category: t || null
|
|
77
|
-
} } }), await
|
|
78
|
-
},
|
|
79
|
-
confirm("Delete this page?") && (await
|
|
80
|
-
},
|
|
81
|
-
if (
|
|
82
|
-
|
|
77
|
+
} } }), await G();
|
|
78
|
+
}, Fe = async (e) => {
|
|
79
|
+
confirm("Delete this page?") && (await De({ variables: { id: e } }), await G());
|
|
80
|
+
}, X = async () => {
|
|
81
|
+
if (K) {
|
|
82
|
+
M(!0), P(null);
|
|
83
83
|
try {
|
|
84
|
-
let
|
|
85
|
-
siteId:
|
|
84
|
+
let e = await Oe({ variables: {
|
|
85
|
+
siteId: K.id,
|
|
86
86
|
publish: !0
|
|
87
87
|
} });
|
|
88
|
-
|
|
88
|
+
if (e.error && c(e.error)) {
|
|
89
|
+
l(), M(!1), U(!0);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
e.data?.compileDocsSite ? A(e.data.compileDocsSite) : (M(!1), P("Build could not be started — the server returned an empty response. Please try again."));
|
|
89
93
|
} catch (e) {
|
|
90
|
-
|
|
94
|
+
if (M(!1), c(e)) {
|
|
95
|
+
l(), U(!0);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
P(e instanceof Error ? e.message : "Failed to start the build. Please try again.");
|
|
91
99
|
}
|
|
92
100
|
}
|
|
93
|
-
},
|
|
94
|
-
let { data: t } = await
|
|
95
|
-
return n && (
|
|
101
|
+
}, Z = async (e) => {
|
|
102
|
+
let { data: t } = await Y({ variables: { id: e } }), n = t?.docsRevision;
|
|
103
|
+
return n && (A(n), [
|
|
96
104
|
"SUCCEEDED",
|
|
97
105
|
"PUBLISHED",
|
|
98
106
|
"FAILED"
|
|
99
|
-
].includes(n.status) && (
|
|
100
|
-
},
|
|
101
|
-
if (!
|
|
102
|
-
e.visibility && e.visibility !==
|
|
103
|
-
id:
|
|
107
|
+
].includes(n.status) && (M(!1), (n.status === "PUBLISHED" || n.status === "SUCCEEDED") && (I(""), await G()))), n;
|
|
108
|
+
}, Ie = async (e) => {
|
|
109
|
+
if (!K) return;
|
|
110
|
+
e.visibility && e.visibility !== K.visibility && await Ce({ variables: {
|
|
111
|
+
id: K.id,
|
|
104
112
|
visibility: e.visibility
|
|
105
113
|
} });
|
|
106
114
|
let t = {
|
|
@@ -108,113 +116,126 @@ function w({ vibeId: w, ownerType: ce, ownerId: le }) {
|
|
|
108
116
|
provider: e.provider,
|
|
109
117
|
providerConfig: e.providerConfig
|
|
110
118
|
};
|
|
111
|
-
Object.keys(t).length > 0 && await
|
|
112
|
-
id:
|
|
119
|
+
Object.keys(t).length > 0 && await Se({ variables: {
|
|
120
|
+
id: K.id,
|
|
113
121
|
input: t
|
|
114
|
-
} }), await
|
|
115
|
-
},
|
|
116
|
-
if (!
|
|
122
|
+
} }), await G();
|
|
123
|
+
}, Le = async () => {
|
|
124
|
+
if (!K?.currentRevisionId) return null;
|
|
117
125
|
try {
|
|
118
|
-
let { data: e } = await
|
|
126
|
+
let { data: e } = await ke({ variables: { siteId: K.id } });
|
|
119
127
|
return e?.generateDocsSignedUrl?.url ?? null;
|
|
120
128
|
} catch {
|
|
121
129
|
return null;
|
|
122
130
|
}
|
|
123
|
-
},
|
|
124
|
-
if (
|
|
125
|
-
|
|
131
|
+
}, Re = async (e) => {
|
|
132
|
+
if (K && confirm("Roll back to this revision? The current published docs will be replaced.")) {
|
|
133
|
+
R(e);
|
|
126
134
|
try {
|
|
127
|
-
await
|
|
128
|
-
siteId:
|
|
135
|
+
await Ae({ variables: {
|
|
136
|
+
siteId: K.id,
|
|
129
137
|
revisionId: e
|
|
130
|
-
} }), await
|
|
138
|
+
} }), await G();
|
|
131
139
|
} finally {
|
|
132
|
-
|
|
140
|
+
R(null);
|
|
133
141
|
}
|
|
134
142
|
}
|
|
135
|
-
},
|
|
136
|
-
|
|
143
|
+
}, ze = async () => {
|
|
144
|
+
K && confirm("Delete this docs site and all its pages and revisions? This cannot be undone.") && (await je({ variables: { id: K.id } }), await G());
|
|
137
145
|
};
|
|
138
|
-
if (
|
|
139
|
-
if (
|
|
146
|
+
if (pe && !K) return /* @__PURE__ */ S(d, { message: T("vibecontrols.docs.tab.loading", "Loading documentation...") });
|
|
147
|
+
if (W && !K) return /* @__PURE__ */ S(f, {
|
|
140
148
|
title: T("vibecontrols.docs.tab.loadFailed", "Failed to load docs"),
|
|
141
|
-
message:
|
|
142
|
-
onRetry: () =>
|
|
149
|
+
message: W.message,
|
|
150
|
+
onRetry: () => G()
|
|
143
151
|
});
|
|
144
|
-
if (!
|
|
145
|
-
onCreate:
|
|
146
|
-
loading:
|
|
147
|
-
}), /* @__PURE__ */ S(
|
|
148
|
-
isOpen:
|
|
149
|
-
onClose: () =>
|
|
152
|
+
if (!K) return /* @__PURE__ */ C(x, { children: [/* @__PURE__ */ S(p, {
|
|
153
|
+
onCreate: Me,
|
|
154
|
+
loading: xe
|
|
155
|
+
}), /* @__PURE__ */ S(o, {
|
|
156
|
+
isOpen: B,
|
|
157
|
+
onClose: () => V(!1),
|
|
150
158
|
onConfirm: () => {
|
|
151
|
-
|
|
159
|
+
V(!1), z("/billing/plans");
|
|
152
160
|
},
|
|
153
161
|
title: "Docs Site Quota Reached",
|
|
154
162
|
message: "You have reached the documentation site limit for your current plan. Upgrade to create more docs sites."
|
|
155
163
|
})] });
|
|
156
|
-
let
|
|
164
|
+
let Q = N ? /* @__PURE__ */ C("div", {
|
|
157
165
|
className: "flex items-center gap-2 px-4 py-2 mb-2 bg-status-error-bg text-status-error-text text-sm rounded-md",
|
|
158
166
|
children: [
|
|
159
|
-
/* @__PURE__ */ S(
|
|
167
|
+
/* @__PURE__ */ S(y, { className: "size-4 shrink-0" }),
|
|
160
168
|
/* @__PURE__ */ S("span", {
|
|
161
169
|
className: "flex-1",
|
|
162
|
-
children:
|
|
170
|
+
children: N
|
|
163
171
|
}),
|
|
164
172
|
/* @__PURE__ */ S("button", {
|
|
165
173
|
type: "button",
|
|
166
|
-
onClick: () =>
|
|
174
|
+
onClick: () => P(null),
|
|
167
175
|
className: "p-0.5 hover:opacity-70",
|
|
168
|
-
children: /* @__PURE__ */ S(
|
|
176
|
+
children: /* @__PURE__ */ S(b, { className: "size-3.5" })
|
|
169
177
|
})
|
|
170
178
|
]
|
|
171
|
-
}) : null
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
179
|
+
}) : null, $ = /* @__PURE__ */ S(o, {
|
|
180
|
+
isOpen: H,
|
|
181
|
+
onClose: () => U(!1),
|
|
182
|
+
onConfirm: () => {
|
|
183
|
+
U(!1), z("/billing/plans");
|
|
184
|
+
},
|
|
185
|
+
title: s("docs-compilation").title,
|
|
186
|
+
message: s("docs-compilation").message
|
|
187
|
+
});
|
|
188
|
+
return de === "edit" ? /* @__PURE__ */ C(x, { children: [
|
|
189
|
+
Q,
|
|
190
|
+
$,
|
|
191
|
+
/* @__PURE__ */ S(h, {
|
|
192
|
+
site: K,
|
|
193
|
+
pages: q,
|
|
194
|
+
onBack: () => O("preview"),
|
|
195
|
+
onSavePage: Ne,
|
|
196
|
+
onAddPage: Pe,
|
|
197
|
+
pageAdding: Te,
|
|
198
|
+
onDeletePage: Fe,
|
|
199
|
+
onCompile: X,
|
|
200
|
+
onSaveSettings: Ie,
|
|
201
|
+
onRollback: Re,
|
|
202
|
+
onDeleteSite: ze,
|
|
203
|
+
rollingBack: L,
|
|
204
|
+
compileRevision: k,
|
|
205
|
+
onPollRevision: Z,
|
|
206
|
+
compiling: j
|
|
207
|
+
})
|
|
208
|
+
] }) : /* @__PURE__ */ C(x, { children: [
|
|
209
|
+
Q,
|
|
189
210
|
$,
|
|
190
|
-
/* @__PURE__ */ S(
|
|
191
|
-
site:
|
|
192
|
-
pages:
|
|
193
|
-
selectedPageSlug:
|
|
194
|
-
onSelectPage:
|
|
195
|
-
docsBaseUrl:
|
|
196
|
-
docsHtml:
|
|
197
|
-
docsContentLoading:
|
|
198
|
-
onEdit: () =>
|
|
199
|
-
onCompile:
|
|
200
|
-
onSettings: () =>
|
|
201
|
-
onGetShareUrl:
|
|
211
|
+
/* @__PURE__ */ S(m, {
|
|
212
|
+
site: K,
|
|
213
|
+
pages: q,
|
|
214
|
+
selectedPageSlug: F,
|
|
215
|
+
onSelectPage: I,
|
|
216
|
+
docsBaseUrl: K.currentRevisionId ? ye ?? null : null,
|
|
217
|
+
docsHtml: K.currentRevisionId ? _e : null,
|
|
218
|
+
docsContentLoading: he,
|
|
219
|
+
onEdit: () => O("edit"),
|
|
220
|
+
onCompile: X,
|
|
221
|
+
onSettings: () => O("edit"),
|
|
222
|
+
onGetShareUrl: Le,
|
|
202
223
|
onOpenFullScreen: () => {
|
|
203
|
-
|
|
224
|
+
z(`/${{
|
|
204
225
|
VIBE: "vibes",
|
|
205
226
|
CATALOG: "catalogs",
|
|
206
227
|
COMPONENT: "components"
|
|
207
228
|
}[E] || "vibes"}/${D}/docs`);
|
|
208
229
|
},
|
|
209
|
-
compileRevision:
|
|
210
|
-
onPollRevision:
|
|
211
|
-
compiling:
|
|
230
|
+
compileRevision: k,
|
|
231
|
+
onPollRevision: Z,
|
|
232
|
+
compiling: j
|
|
212
233
|
}),
|
|
213
|
-
/* @__PURE__ */ S(
|
|
214
|
-
isOpen:
|
|
215
|
-
onClose: () =>
|
|
234
|
+
/* @__PURE__ */ S(o, {
|
|
235
|
+
isOpen: B,
|
|
236
|
+
onClose: () => V(!1),
|
|
216
237
|
onConfirm: () => {
|
|
217
|
-
|
|
238
|
+
V(!1), z("/billing/plans");
|
|
218
239
|
},
|
|
219
240
|
title: "Docs Site Quota Reached",
|
|
220
241
|
message: "You have reached the documentation site limit for your current plan. Upgrade to create more docs sites."
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocsTabPanel.js","names":[],"sources":["../../../src/components/docs/DocsTabPanel.tsx"],"sourcesContent":["import { useState, useEffect, useRef } from 'react';\nimport { AlertCircle, X } from 'lucide-react';\nimport { LoadingState, ErrorState, QuotaExhaustedDialog } from '@/components/shared';\nimport { useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { resolveGatewayUrls } from '@burdenoff/fe-libs/shared/config';\nimport { DocsEmptyState } from './DocsEmptyState';\nimport { DocsPreviewPanel } from './DocsPreviewPanel';\nimport { DocsEditPanel } from './DocsEditPanel';\nimport type { DocsSite, DocsRevision } from './types';\nimport { isQuotaExhaustedError, markQuotaHandledLocally } from '@/utils/quotaUtils';\nimport { useTr } from '../../shared/hooks/useTr';\nimport {\n useGetDocsSiteQuery,\n useCreateDocsSiteMutation,\n useUpdateDocsSiteMutation,\n useUpdateDocsSiteVisibilityMutation,\n useCreateDocsPageMutation,\n useUpdateDocsPageMutation,\n useDeleteDocsPageMutation,\n useCompileDocsSiteMutation,\n useDocsContentQuery,\n useGetDocsRevisionLazyQuery,\n useGenerateDocsSignedUrlMutation,\n useRollbackDocsRevisionMutation,\n useDeleteDocsSiteMutation,\n} from '@/generated/wspace-operations';\n\ninterface DocsTabPanelProps {\n vibeId?: string;\n ownerType?: string;\n ownerId?: string;\n}\n\nexport function DocsTabPanel({ vibeId, ownerType, ownerId }: DocsTabPanelProps) {\n const tr = useTr();\n const effectiveOwnerType = ownerType || 'VIBE';\n const effectiveOwnerId = ownerId || vibeId || '';\n const [mode, setMode] = useState<'preview' | 'edit'>('preview');\n const [compileRevision, setCompileRevision] = useState<DocsRevision | null>(null);\n const [compiling, setCompiling] = useState(false);\n const [compileError, setCompileError] = useState<string | null>(null);\n const [selectedPageSlug, setSelectedPageSlug] = useState('');\n const [rollingBack, setRollingBack] = useState<string | null>(null);\n const navigate = useVibeNavigate();\n const [showQuotaExhausted, setShowQuotaExhausted] = useState(false);\n\n // Queries\n const { data, loading, error, refetch } = useGetDocsSiteQuery({\n variables: { ownerType: effectiveOwnerType as any, ownerId: effectiveOwnerId },\n skip: !effectiveOwnerId,\n fetchPolicy: 'cache-and-network',\n });\n\n const site = (data?.vibecontrolsDocsSiteByOwner ?? null) as DocsSite | null;\n const pages = site?.pages || [];\n\n const {\n data: docsContentData,\n loading: docsContentLoading,\n refetch: refetchDocsContent,\n } = useDocsContentQuery({\n variables: { siteId: site?.id || '', path: selectedPageSlug },\n skip: !site?.id || !site.currentRevisionId,\n fetchPolicy: 'network-only',\n });\n const docsHtml = docsContentData?.docsContent?.html ?? null;\n\n // Re-fetch docs content whenever currentRevisionId changes (compile finished or first publish).\n // This runs post-render so skip:false is guaranteed — imperative calls during async handlers\n // are no-ops when skip is still true in the closure.\n const prevRevisionIdRef = useRef<string | null | undefined>(undefined);\n useEffect(() => {\n const currentId = site?.currentRevisionId ?? null;\n if (prevRevisionIdRef.current === undefined) {\n prevRevisionIdRef.current = currentId;\n return;\n }\n if (currentId && currentId !== prevRevisionIdRef.current) {\n prevRevisionIdRef.current = currentId;\n refetchDocsContent();\n }\n }, [site?.currentRevisionId]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Compute gateway docs URL for iframe src (workspaceId prefix for isolation)\n const gatewayUrls = resolveGatewayUrls();\n const docsBaseUrl = site?.workspaceId\n ? `${gatewayUrls.workspaceBaseUrl}/workspaces/static/${site.workspaceId}/docs/${effectiveOwnerId}/`\n : null;\n\n // Mutations\n const [createSiteMutation, { loading: creating }] = useCreateDocsSiteMutation();\n const [updateSiteMutation] = useUpdateDocsSiteMutation();\n const [updateVisibilityMutation] = useUpdateDocsSiteVisibilityMutation();\n const [createPageMutation, { loading: pageAdding }] = useCreateDocsPageMutation();\n const [updatePageMutation] = useUpdateDocsPageMutation();\n const [deletePageMutation] = useDeleteDocsPageMutation();\n const [compileMutation] = useCompileDocsSiteMutation();\n const [generateSignedUrl] = useGenerateDocsSignedUrlMutation();\n const [rollbackRevision] = useRollbackDocsRevisionMutation();\n const [deleteSiteMutation] = useDeleteDocsSiteMutation();\n const [fetchRevision] = useGetDocsRevisionLazyQuery({\n fetchPolicy: 'network-only',\n });\n\n // Handlers\n const handleCreateSite = async (\n provider: 'DOCUSAURUS' | 'MKDOCS' | 'VITEPRESS' = 'DOCUSAURUS'\n ) => {\n try {\n await createSiteMutation({\n variables: {\n input: {\n ownerType: effectiveOwnerType as any,\n ownerId: effectiveOwnerId,\n name: 'Documentation',\n provider: provider as any,\n },\n },\n refetchQueries: ['GetDocsSite'],\n awaitRefetchQueries: true,\n });\n setMode('edit');\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n markQuotaHandledLocally();\n setShowQuotaExhausted(true);\n return;\n }\n throw err;\n }\n };\n\n const handleSavePage = async (\n id: string,\n data: { title?: string; content?: string; slug?: string }\n ) => {\n await updatePageMutation({ variables: { id, input: data } });\n };\n\n const handleAddPage = async (parentId?: string, category?: string) => {\n if (!site) return;\n const pageCount = pages.length;\n const slug = `page-${pageCount + 1}`;\n await createPageMutation({\n variables: {\n input: {\n siteId: site.id,\n parentId: parentId || null,\n slug,\n title: `New Page ${pageCount + 1}`,\n content: '# New Page\\n\\nStart writing here...',\n status: 'DRAFT',\n sidebarPosition: pageCount,\n category: category || null,\n },\n },\n });\n await refetch();\n };\n\n const handleDeletePage = async (pageId: string) => {\n if (!confirm('Delete this page?')) return;\n await deletePageMutation({ variables: { id: pageId } });\n await refetch();\n };\n\n const handleCompile = async () => {\n if (!site) return;\n setCompiling(true);\n setCompileError(null);\n try {\n const { data: compileData } = await compileMutation({\n variables: { siteId: site.id, publish: true },\n });\n if (compileData?.compileDocsSite) {\n setCompileRevision(compileData.compileDocsSite as DocsRevision);\n } else {\n setCompiling(false);\n setCompileError(\n 'Build could not be started — the server returned an empty response. Please try again.'\n );\n }\n } catch (err) {\n setCompiling(false);\n setCompileError(\n err instanceof Error ? err.message : 'Failed to start the build. Please try again.'\n );\n }\n };\n\n const handlePollRevision = async (revisionId: string): Promise<DocsRevision | null> => {\n const { data: revData } = await fetchRevision({ variables: { id: revisionId } });\n const rev = revData?.docsRevision as DocsRevision | null;\n if (rev) {\n setCompileRevision(rev);\n const done = ['SUCCEEDED', 'PUBLISHED', 'FAILED'].includes(rev.status);\n if (done) {\n setCompiling(false);\n if (rev.status === 'PUBLISHED' || rev.status === 'SUCCEEDED') {\n setSelectedPageSlug('');\n await refetch();\n }\n }\n }\n return rev;\n };\n\n const handleSaveSettings = async (data: {\n name?: string;\n visibility?: 'PRIVATE' | 'PUBLIC';\n provider?: 'DOCUSAURUS' | 'MKDOCS' | 'VITEPRESS';\n providerConfig?: Record<string, unknown>;\n }) => {\n if (!site) return;\n if (data.visibility && data.visibility !== site.visibility) {\n await updateVisibilityMutation({ variables: { id: site.id, visibility: data.visibility } });\n }\n const rest = {\n name: data.name,\n provider: data.provider,\n providerConfig: data.providerConfig,\n };\n if (Object.keys(rest).length > 0) {\n await updateSiteMutation({ variables: { id: site.id, input: rest } });\n }\n await refetch();\n };\n\n const handleGetShareUrl = async (): Promise<string | null> => {\n if (!site?.currentRevisionId) return null;\n try {\n const { data: urlData } = await generateSignedUrl({ variables: { siteId: site.id } });\n return urlData?.generateDocsSignedUrl?.url ?? null;\n } catch {\n return null;\n }\n };\n\n const handleRollback = async (revisionId: string) => {\n if (!site) return;\n if (!confirm('Roll back to this revision? The current published docs will be replaced.'))\n return;\n setRollingBack(revisionId);\n try {\n await rollbackRevision({ variables: { siteId: site.id, revisionId } });\n await refetch();\n } finally {\n setRollingBack(null);\n }\n };\n\n const handleDeleteSite = async () => {\n if (!site) return;\n if (!confirm('Delete this docs site and all its pages and revisions? This cannot be undone.'))\n return;\n await deleteSiteMutation({ variables: { id: site.id } });\n await refetch();\n };\n\n // Loading / Error states\n if (loading && !site) {\n return (\n <LoadingState message={tr('vibecontrols.docs.tab.loading', 'Loading documentation...')} />\n );\n }\n\n if (error && !site) {\n return (\n <ErrorState\n title={tr('vibecontrols.docs.tab.loadFailed', 'Failed to load docs')}\n message={error.message}\n onRetry={() => refetch()}\n />\n );\n }\n\n // No site yet\n if (!site) {\n return (\n <>\n <DocsEmptyState onCreate={handleCreateSite} loading={creating} />\n <QuotaExhaustedDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing');\n }}\n title=\"Docs Site Quota Reached\"\n message=\"You have reached the documentation site limit for your current plan. Upgrade to create more docs sites.\"\n />\n </>\n );\n }\n\n const compileErrorBanner = compileError ? (\n <div className=\"flex items-center gap-2 px-4 py-2 mb-2 bg-status-error-bg text-status-error-text text-sm rounded-md\">\n <AlertCircle className=\"size-4 shrink-0\" />\n <span className=\"flex-1\">{compileError}</span>\n <button\n type=\"button\"\n onClick={() => setCompileError(null)}\n className=\"p-0.5 hover:opacity-70\"\n >\n <X className=\"size-3.5\" />\n </button>\n </div>\n ) : null;\n\n // Edit mode\n if (mode === 'edit') {\n return (\n <>\n {compileErrorBanner}\n <DocsEditPanel\n site={site}\n pages={pages}\n onBack={() => setMode('preview')}\n onSavePage={handleSavePage}\n onAddPage={handleAddPage}\n pageAdding={pageAdding}\n onDeletePage={handleDeletePage}\n onCompile={handleCompile}\n onSaveSettings={handleSaveSettings}\n onRollback={handleRollback}\n onDeleteSite={handleDeleteSite}\n rollingBack={rollingBack}\n compileRevision={compileRevision}\n onPollRevision={handlePollRevision}\n compiling={compiling}\n />\n </>\n );\n }\n\n // Preview mode\n return (\n <>\n {compileErrorBanner}\n <DocsPreviewPanel\n site={site}\n pages={pages}\n selectedPageSlug={selectedPageSlug}\n onSelectPage={setSelectedPageSlug}\n docsBaseUrl={site.currentRevisionId ? (docsBaseUrl ?? null) : null}\n docsHtml={site.currentRevisionId ? docsHtml : null}\n docsContentLoading={docsContentLoading}\n onEdit={() => setMode('edit')}\n onCompile={handleCompile}\n onSettings={() => setMode('edit')}\n onGetShareUrl={handleGetShareUrl}\n onOpenFullScreen={() => {\n const pathMap: Record<string, string> = {\n VIBE: 'vibes',\n CATALOG: 'catalogs',\n COMPONENT: 'components',\n };\n const segment = pathMap[effectiveOwnerType] || 'vibes';\n navigate(`/${segment}/${effectiveOwnerId}/docs`);\n }}\n compileRevision={compileRevision}\n onPollRevision={handlePollRevision}\n compiling={compiling}\n />\n <QuotaExhaustedDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing');\n }}\n title=\"Docs Site Quota Reached\"\n message=\"You have reached the documentation site limit for your current plan. Upgrade to create more docs sites.\"\n />\n </>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DocsTabPanel.js","names":[],"sources":["../../../src/components/docs/DocsTabPanel.tsx"],"sourcesContent":["import { useState, useEffect, useRef } from 'react';\nimport { AlertCircle, X } from 'lucide-react';\nimport { LoadingState, ErrorState, QuotaExhaustedDialog } from '@/components/shared';\nimport { useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { resolveGatewayUrls } from '@burdenoff/fe-libs/shared/config';\nimport { DocsEmptyState } from './DocsEmptyState';\nimport { DocsPreviewPanel } from './DocsPreviewPanel';\nimport { DocsEditPanel } from './DocsEditPanel';\nimport type { DocsSite, DocsRevision } from './types';\nimport {\n isQuotaExhaustedError,\n markQuotaHandledLocally,\n getQuotaDialogContent,\n} from '@/utils/quotaUtils';\nimport { useTr } from '../../shared/hooks/useTr';\nimport {\n useGetDocsSiteQuery,\n useCreateDocsSiteMutation,\n useUpdateDocsSiteMutation,\n useUpdateDocsSiteVisibilityMutation,\n useCreateDocsPageMutation,\n useUpdateDocsPageMutation,\n useDeleteDocsPageMutation,\n useCompileDocsSiteMutation,\n useDocsContentQuery,\n useGetDocsRevisionLazyQuery,\n useGenerateDocsSignedUrlMutation,\n useRollbackDocsRevisionMutation,\n useDeleteDocsSiteMutation,\n} from '@/generated/wspace-operations';\n\ninterface DocsTabPanelProps {\n vibeId?: string;\n ownerType?: string;\n ownerId?: string;\n}\n\nexport function DocsTabPanel({ vibeId, ownerType, ownerId }: DocsTabPanelProps) {\n const tr = useTr();\n const effectiveOwnerType = ownerType || 'VIBE';\n const effectiveOwnerId = ownerId || vibeId || '';\n const [mode, setMode] = useState<'preview' | 'edit'>('preview');\n const [compileRevision, setCompileRevision] = useState<DocsRevision | null>(null);\n const [compiling, setCompiling] = useState(false);\n const [compileError, setCompileError] = useState<string | null>(null);\n const [selectedPageSlug, setSelectedPageSlug] = useState('');\n const [rollingBack, setRollingBack] = useState<string | null>(null);\n const navigate = useVibeNavigate();\n const [showQuotaExhausted, setShowQuotaExhausted] = useState(false);\n const [showCompileQuotaExhausted, setShowCompileQuotaExhausted] = useState(false);\n\n // Queries\n const { data, loading, error, refetch } = useGetDocsSiteQuery({\n variables: { ownerType: effectiveOwnerType as any, ownerId: effectiveOwnerId },\n skip: !effectiveOwnerId,\n fetchPolicy: 'cache-and-network',\n });\n\n const site = (data?.vibecontrolsDocsSiteByOwner ?? null) as DocsSite | null;\n const pages = site?.pages || [];\n\n const {\n data: docsContentData,\n loading: docsContentLoading,\n refetch: refetchDocsContent,\n } = useDocsContentQuery({\n variables: { siteId: site?.id || '', path: selectedPageSlug },\n skip: !site?.id || !site.currentRevisionId,\n fetchPolicy: 'network-only',\n });\n const docsHtml = docsContentData?.docsContent?.html ?? null;\n\n // Re-fetch docs content whenever currentRevisionId changes (compile finished or first publish).\n // This runs post-render so skip:false is guaranteed — imperative calls during async handlers\n // are no-ops when skip is still true in the closure.\n const prevRevisionIdRef = useRef<string | null | undefined>(undefined);\n useEffect(() => {\n const currentId = site?.currentRevisionId ?? null;\n if (prevRevisionIdRef.current === undefined) {\n prevRevisionIdRef.current = currentId;\n return;\n }\n if (currentId && currentId !== prevRevisionIdRef.current) {\n prevRevisionIdRef.current = currentId;\n refetchDocsContent();\n }\n }, [site?.currentRevisionId]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Compute gateway docs URL for iframe src (workspaceId prefix for isolation)\n const gatewayUrls = resolveGatewayUrls();\n const docsBaseUrl = site?.workspaceId\n ? `${gatewayUrls.workspaceBaseUrl}/workspaces/static/${site.workspaceId}/docs/${effectiveOwnerId}/`\n : null;\n\n // Mutations\n const [createSiteMutation, { loading: creating }] = useCreateDocsSiteMutation();\n const [updateSiteMutation] = useUpdateDocsSiteMutation();\n const [updateVisibilityMutation] = useUpdateDocsSiteVisibilityMutation();\n const [createPageMutation, { loading: pageAdding }] = useCreateDocsPageMutation();\n const [updatePageMutation] = useUpdateDocsPageMutation();\n const [deletePageMutation] = useDeleteDocsPageMutation();\n const [compileMutation] = useCompileDocsSiteMutation();\n const [generateSignedUrl] = useGenerateDocsSignedUrlMutation();\n const [rollbackRevision] = useRollbackDocsRevisionMutation();\n const [deleteSiteMutation] = useDeleteDocsSiteMutation();\n const [fetchRevision] = useGetDocsRevisionLazyQuery({\n fetchPolicy: 'network-only',\n });\n\n // Handlers\n const handleCreateSite = async (\n provider: 'DOCUSAURUS' | 'MKDOCS' | 'VITEPRESS' = 'DOCUSAURUS'\n ) => {\n try {\n await createSiteMutation({\n variables: {\n input: {\n ownerType: effectiveOwnerType as any,\n ownerId: effectiveOwnerId,\n name: 'Documentation',\n provider: provider as any,\n },\n },\n refetchQueries: ['GetDocsSite'],\n awaitRefetchQueries: true,\n });\n setMode('edit');\n } catch (err) {\n if (isQuotaExhaustedError(err)) {\n markQuotaHandledLocally();\n setShowQuotaExhausted(true);\n return;\n }\n throw err;\n }\n };\n\n const handleSavePage = async (\n id: string,\n data: { title?: string; content?: string; slug?: string }\n ) => {\n await updatePageMutation({ variables: { id, input: data } });\n };\n\n const handleAddPage = async (parentId?: string, category?: string) => {\n if (!site) return;\n const pageCount = pages.length;\n const slug = `page-${pageCount + 1}`;\n await createPageMutation({\n variables: {\n input: {\n siteId: site.id,\n parentId: parentId || null,\n slug,\n title: `New Page ${pageCount + 1}`,\n content: '# New Page\\n\\nStart writing here...',\n status: 'DRAFT',\n sidebarPosition: pageCount,\n category: category || null,\n },\n },\n });\n await refetch();\n };\n\n const handleDeletePage = async (pageId: string) => {\n if (!confirm('Delete this page?')) return;\n await deletePageMutation({ variables: { id: pageId } });\n await refetch();\n };\n\n const handleCompile = async () => {\n if (!site) return;\n setCompiling(true);\n setCompileError(null);\n try {\n const result = await compileMutation({\n variables: { siteId: site.id, publish: true },\n });\n if (result.error && isQuotaExhaustedError(result.error)) {\n markQuotaHandledLocally();\n setCompiling(false);\n setShowCompileQuotaExhausted(true);\n return;\n }\n if (result.data?.compileDocsSite) {\n setCompileRevision(result.data.compileDocsSite as DocsRevision);\n } else {\n setCompiling(false);\n setCompileError(\n 'Build could not be started — the server returned an empty response. Please try again.'\n );\n }\n } catch (err) {\n setCompiling(false);\n if (isQuotaExhaustedError(err)) {\n markQuotaHandledLocally();\n setShowCompileQuotaExhausted(true);\n return;\n }\n setCompileError(\n err instanceof Error ? err.message : 'Failed to start the build. Please try again.'\n );\n }\n };\n\n const handlePollRevision = async (revisionId: string): Promise<DocsRevision | null> => {\n const { data: revData } = await fetchRevision({ variables: { id: revisionId } });\n const rev = revData?.docsRevision as DocsRevision | null;\n if (rev) {\n setCompileRevision(rev);\n const done = ['SUCCEEDED', 'PUBLISHED', 'FAILED'].includes(rev.status);\n if (done) {\n setCompiling(false);\n if (rev.status === 'PUBLISHED' || rev.status === 'SUCCEEDED') {\n setSelectedPageSlug('');\n await refetch();\n }\n }\n }\n return rev;\n };\n\n const handleSaveSettings = async (data: {\n name?: string;\n visibility?: 'PRIVATE' | 'PUBLIC';\n provider?: 'DOCUSAURUS' | 'MKDOCS' | 'VITEPRESS';\n providerConfig?: Record<string, unknown>;\n }) => {\n if (!site) return;\n if (data.visibility && data.visibility !== site.visibility) {\n await updateVisibilityMutation({ variables: { id: site.id, visibility: data.visibility } });\n }\n const rest = {\n name: data.name,\n provider: data.provider,\n providerConfig: data.providerConfig,\n };\n if (Object.keys(rest).length > 0) {\n await updateSiteMutation({ variables: { id: site.id, input: rest } });\n }\n await refetch();\n };\n\n const handleGetShareUrl = async (): Promise<string | null> => {\n if (!site?.currentRevisionId) return null;\n try {\n const { data: urlData } = await generateSignedUrl({ variables: { siteId: site.id } });\n return urlData?.generateDocsSignedUrl?.url ?? null;\n } catch {\n return null;\n }\n };\n\n const handleRollback = async (revisionId: string) => {\n if (!site) return;\n if (!confirm('Roll back to this revision? The current published docs will be replaced.'))\n return;\n setRollingBack(revisionId);\n try {\n await rollbackRevision({ variables: { siteId: site.id, revisionId } });\n await refetch();\n } finally {\n setRollingBack(null);\n }\n };\n\n const handleDeleteSite = async () => {\n if (!site) return;\n if (!confirm('Delete this docs site and all its pages and revisions? This cannot be undone.'))\n return;\n await deleteSiteMutation({ variables: { id: site.id } });\n await refetch();\n };\n\n // Loading / Error states\n if (loading && !site) {\n return (\n <LoadingState message={tr('vibecontrols.docs.tab.loading', 'Loading documentation...')} />\n );\n }\n\n if (error && !site) {\n return (\n <ErrorState\n title={tr('vibecontrols.docs.tab.loadFailed', 'Failed to load docs')}\n message={error.message}\n onRetry={() => refetch()}\n />\n );\n }\n\n // No site yet\n if (!site) {\n return (\n <>\n <DocsEmptyState onCreate={handleCreateSite} loading={creating} />\n <QuotaExhaustedDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing/plans');\n }}\n title=\"Docs Site Quota Reached\"\n message=\"You have reached the documentation site limit for your current plan. Upgrade to create more docs sites.\"\n />\n </>\n );\n }\n\n const compileErrorBanner = compileError ? (\n <div className=\"flex items-center gap-2 px-4 py-2 mb-2 bg-status-error-bg text-status-error-text text-sm rounded-md\">\n <AlertCircle className=\"size-4 shrink-0\" />\n <span className=\"flex-1\">{compileError}</span>\n <button\n type=\"button\"\n onClick={() => setCompileError(null)}\n className=\"p-0.5 hover:opacity-70\"\n >\n <X className=\"size-3.5\" />\n </button>\n </div>\n ) : null;\n\n const compileQuotaDialog = (\n <QuotaExhaustedDialog\n isOpen={showCompileQuotaExhausted}\n onClose={() => setShowCompileQuotaExhausted(false)}\n onConfirm={() => {\n setShowCompileQuotaExhausted(false);\n navigate('/billing/plans');\n }}\n title={getQuotaDialogContent('docs-compilation').title}\n message={getQuotaDialogContent('docs-compilation').message}\n />\n );\n\n // Edit mode\n if (mode === 'edit') {\n return (\n <>\n {compileErrorBanner}\n {compileQuotaDialog}\n <DocsEditPanel\n site={site}\n pages={pages}\n onBack={() => setMode('preview')}\n onSavePage={handleSavePage}\n onAddPage={handleAddPage}\n pageAdding={pageAdding}\n onDeletePage={handleDeletePage}\n onCompile={handleCompile}\n onSaveSettings={handleSaveSettings}\n onRollback={handleRollback}\n onDeleteSite={handleDeleteSite}\n rollingBack={rollingBack}\n compileRevision={compileRevision}\n onPollRevision={handlePollRevision}\n compiling={compiling}\n />\n </>\n );\n }\n\n // Preview mode\n return (\n <>\n {compileErrorBanner}\n {compileQuotaDialog}\n <DocsPreviewPanel\n site={site}\n pages={pages}\n selectedPageSlug={selectedPageSlug}\n onSelectPage={setSelectedPageSlug}\n docsBaseUrl={site.currentRevisionId ? (docsBaseUrl ?? null) : null}\n docsHtml={site.currentRevisionId ? docsHtml : null}\n docsContentLoading={docsContentLoading}\n onEdit={() => setMode('edit')}\n onCompile={handleCompile}\n onSettings={() => setMode('edit')}\n onGetShareUrl={handleGetShareUrl}\n onOpenFullScreen={() => {\n const pathMap: Record<string, string> = {\n VIBE: 'vibes',\n CATALOG: 'catalogs',\n COMPONENT: 'components',\n };\n const segment = pathMap[effectiveOwnerType] || 'vibes';\n navigate(`/${segment}/${effectiveOwnerId}/docs`);\n }}\n compileRevision={compileRevision}\n onPollRevision={handlePollRevision}\n compiling={compiling}\n />\n <QuotaExhaustedDialog\n isOpen={showQuotaExhausted}\n onClose={() => setShowQuotaExhausted(false)}\n onConfirm={() => {\n setShowQuotaExhausted(false);\n navigate('/billing/plans');\n }}\n title=\"Docs Site Quota Reached\"\n message=\"You have reached the documentation site limit for your current plan. Upgrade to create more docs sites.\"\n />\n </>\n );\n}\n"],"mappings":"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"}
|
|
@@ -431,7 +431,7 @@ function g({ context: g, vibeId: _, agentVibes: v = [] }) {
|
|
|
431
431
|
isOpen: Le,
|
|
432
432
|
onClose: () => P(!1),
|
|
433
433
|
onConfirm: () => {
|
|
434
|
-
P(!1), ke("/billing");
|
|
434
|
+
P(!1), ke("/billing/plans");
|
|
435
435
|
},
|
|
436
436
|
title: "Note Quota Reached",
|
|
437
437
|
message: "You've used all available note quota on your current plan. Upgrade your plan to create or update more notes."
|