@burdenoff/microfe-vibecontrols 2026.602.1 → 2026.602.3
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/sessions/SessionShareDialog.js +24 -462
- package/dist/components/sessions/SessionShareDialog.js.map +1 -1
- package/dist/components/sharing/entityShareOps.js +106 -0
- package/dist/components/sharing/entityShareOps.js.map +1 -1
- package/dist/components/sharing/shareRegistry.js +3 -3
- package/dist/components/sharing/shareRegistry.js.map +1 -1
- package/dist/components/vibedeck/VibeDeckShareDialog.js +19 -335
- package/dist/components/vibedeck/VibeDeckShareDialog.js.map +1 -1
- package/dist/components/vibes/DeleteVibeDialog.js +130 -0
- package/dist/components/vibes/DeleteVibeDialog.js.map +1 -0
- package/dist/components/vibes/VibeCard.js +64 -56
- package/dist/components/vibes/VibeCard.js.map +1 -1
- package/dist/components/vibes/VibeList.js +132 -113
- package/dist/components/vibes/VibeList.js.map +1 -1
- package/dist/components/vibes/index.js +1 -0
- package/dist/constants/permissions.js +1 -0
- package/dist/constants/permissions.js.map +1 -1
- package/dist/generated/wspace-operations.js +2 -2
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.js +9 -11
- package/dist/generated/wspace-types.js.map +1 -1
- package/dist/pages/SessionsPage.js +1011 -1007
- package/dist/pages/SessionsPage.js.map +1 -1
- package/dist/pages/VibeDeckPage.js +40 -41
- package/dist/pages/VibeDeckPage.js.map +1 -1
- package/dist/pages/VibeDetailsPage.js +560 -523
- package/dist/pages/VibeDetailsPage.js.map +1 -1
- package/dist/pages/VibesPage.js +311 -280
- package/dist/pages/VibesPage.js.map +1 -1
- package/package.json +1 -1
- package/dist/utils/shareUrl.js +0 -41
- package/dist/utils/shareUrl.js.map +0 -1
|
@@ -1,467 +1,29 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { useEffect as ne, useRef as re, useState as l } from "react";
|
|
6
|
-
import { Check as ie, Clock as u, Copy as d, Eye as f, Gamepad2 as p, Link2 as m, Lock as ae, RefreshCw as h, Share2 as oe, Trash2 as g, Users as _, X as v } from "lucide-react";
|
|
7
|
-
import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
1
|
+
import { useEntityShareController as e } from "../sharing/useEntityShareController.js";
|
|
2
|
+
import { getStoredWorkspaceId as t } from "@burdenoff/fe-libs/shared/graphql";
|
|
3
|
+
import { jsx as n } from "react/jsx-runtime";
|
|
4
|
+
import { ShareDialog as r } from "@burdenoff/fe-libs/sharing";
|
|
8
5
|
//#region src/components/sessions/SessionShareDialog.tsx
|
|
9
|
-
var
|
|
10
|
-
let
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
expiresAt: e,
|
|
29
|
-
message: P.trim() || void 0
|
|
30
|
-
} } }), M(""), F(""), q();
|
|
31
|
-
} catch (e) {
|
|
32
|
-
console.error("Failed to share session:", e);
|
|
33
|
-
}
|
|
34
|
-
}, be = async (e) => {
|
|
35
|
-
e.preventDefault();
|
|
36
|
-
try {
|
|
37
|
-
await me({ variables: { input: {
|
|
38
|
-
sessionId: S.id,
|
|
39
|
-
name: L.trim() || void 0,
|
|
40
|
-
permission: z,
|
|
41
|
-
expiresInHours: V,
|
|
42
|
-
maxUses: G || void 0,
|
|
43
|
-
password: U.trim() || void 0
|
|
44
|
-
} } }), R(""), W(""), K(null), J();
|
|
45
|
-
} catch (e) {
|
|
46
|
-
console.error("Failed to create share link:", e);
|
|
47
|
-
}
|
|
48
|
-
}, xe = async (e) => {
|
|
49
|
-
try {
|
|
50
|
-
await he({ variables: { id: e } }), q();
|
|
51
|
-
} catch (e) {
|
|
52
|
-
console.error("Failed to revoke share:", e);
|
|
53
|
-
}
|
|
54
|
-
}, Se = async (e) => {
|
|
55
|
-
try {
|
|
56
|
-
await _e({ variables: { id: e } }), J();
|
|
57
|
-
} catch (e) {
|
|
58
|
-
console.error("Failed to revoke link:", e);
|
|
59
|
-
}
|
|
60
|
-
}, Ce = async (e, t) => {
|
|
61
|
-
let n = await te(c(t)).then(() => !0, (e) => (console.warn("Failed to copy session share link:", e), !1));
|
|
62
|
-
k(n ? e : null), A(n ? null : e), setTimeout(() => {
|
|
63
|
-
k((t) => t === e ? null : t), A((t) => t === e ? null : t);
|
|
64
|
-
}, 2e3);
|
|
65
|
-
}, $ = (e) => {
|
|
66
|
-
let t = new Date(e), n = /* @__PURE__ */ new Date(), r = t.getTime() - n.getTime(), i = Math.floor(r / (1e3 * 60 * 60)), a = Math.floor(r % (1e3 * 60 * 60) / (1e3 * 60));
|
|
67
|
-
return r < 0 ? "Expired" : i > 24 ? `${Math.floor(i / 24)}d` : i > 0 ? `${i}h ${a}m` : `${a}m`;
|
|
68
|
-
};
|
|
69
|
-
return C ? /* @__PURE__ */ b("dialog", {
|
|
70
|
-
ref: E,
|
|
71
|
-
className: "fixed inset-0 z-50 m-auto bg-bg-overlay/0 p-0 backdrop:bg-bg-overlay",
|
|
72
|
-
onClose: w,
|
|
73
|
-
children: /* @__PURE__ */ x("div", {
|
|
74
|
-
className: "w-full max-w-xl bg-bg-surface rounded-lg shadow-xl max-h-[85vh] flex flex-col",
|
|
75
|
-
children: [
|
|
76
|
-
/* @__PURE__ */ x("div", {
|
|
77
|
-
className: "flex items-center justify-between px-6 py-4 border-b border-border-default",
|
|
78
|
-
children: [/* @__PURE__ */ x("div", {
|
|
79
|
-
className: "flex items-center gap-3",
|
|
80
|
-
children: [/* @__PURE__ */ b("div", {
|
|
81
|
-
className: "p-2 bg-action-primary-bg/10 rounded-lg",
|
|
82
|
-
children: /* @__PURE__ */ b(oe, { className: "size-5 text-action-primary-bg" })
|
|
83
|
-
}), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("h2", {
|
|
84
|
-
className: "text-lg font-semibold text-text-primary",
|
|
85
|
-
children: T("vibecontrols.sessions.share.title", "Share Session")
|
|
86
|
-
}), /* @__PURE__ */ b("p", {
|
|
87
|
-
className: "text-sm text-text-secondary truncate max-w-[300px]",
|
|
88
|
-
children: S.name
|
|
89
|
-
})] })]
|
|
90
|
-
}), /* @__PURE__ */ b("button", {
|
|
91
|
-
type: "button",
|
|
92
|
-
onClick: w,
|
|
93
|
-
className: "p-1.5 rounded hover:bg-bg-sunken transition-colors",
|
|
94
|
-
children: /* @__PURE__ */ b(v, { className: "size-5 text-text-secondary" })
|
|
95
|
-
})]
|
|
96
|
-
}),
|
|
97
|
-
/* @__PURE__ */ x("div", {
|
|
98
|
-
className: "flex border-b border-border-default",
|
|
99
|
-
children: [/* @__PURE__ */ x("button", {
|
|
100
|
-
type: "button",
|
|
101
|
-
onClick: () => O("users"),
|
|
102
|
-
className: `flex items-center gap-2 px-6 py-3 text-sm font-medium transition-colors ${D === "users" ? "text-action-primary-bg border-b-2 border-action-primary-bg" : "text-text-secondary hover:text-text-primary"}`,
|
|
103
|
-
children: [
|
|
104
|
-
/* @__PURE__ */ b(_, { className: "size-4" }),
|
|
105
|
-
T("vibecontrols.sessions.share.shareWithUser", "Share with User"),
|
|
106
|
-
Z.length > 0 && /* @__PURE__ */ b("span", {
|
|
107
|
-
className: "ml-1 px-1.5 py-0.5 text-xs bg-bg-sunken rounded-full",
|
|
108
|
-
children: Z.length
|
|
109
|
-
})
|
|
110
|
-
]
|
|
111
|
-
}), /* @__PURE__ */ x("button", {
|
|
112
|
-
type: "button",
|
|
113
|
-
onClick: () => O("links"),
|
|
114
|
-
className: `flex items-center gap-2 px-6 py-3 text-sm font-medium transition-colors ${D === "links" ? "text-action-primary-bg border-b-2 border-action-primary-bg" : "text-text-secondary hover:text-text-primary"}`,
|
|
115
|
-
children: [
|
|
116
|
-
/* @__PURE__ */ b(m, { className: "size-4" }),
|
|
117
|
-
T("vibecontrols.sessions.share.createLink", "Create Link"),
|
|
118
|
-
Q.length > 0 && /* @__PURE__ */ b("span", {
|
|
119
|
-
className: "ml-1 px-1.5 py-0.5 text-xs bg-bg-sunken rounded-full",
|
|
120
|
-
children: Q.length
|
|
121
|
-
})
|
|
122
|
-
]
|
|
123
|
-
})]
|
|
124
|
-
}),
|
|
125
|
-
/* @__PURE__ */ b("div", {
|
|
126
|
-
className: "flex-1 overflow-y-auto p-6",
|
|
127
|
-
children: D === "users" ? /* @__PURE__ */ x("div", {
|
|
128
|
-
className: "space-y-6",
|
|
129
|
-
children: [/* @__PURE__ */ x("form", {
|
|
130
|
-
onSubmit: ye,
|
|
131
|
-
className: "space-y-4",
|
|
132
|
-
children: [
|
|
133
|
-
/* @__PURE__ */ x("div", { children: [
|
|
134
|
-
/* @__PURE__ */ b("label", {
|
|
135
|
-
className: "block text-sm font-medium text-text-primary mb-1",
|
|
136
|
-
children: T("vibecontrols.sessions.share.emailAddress", "Email Address")
|
|
137
|
-
}),
|
|
138
|
-
/* @__PURE__ */ b("input", {
|
|
139
|
-
"aria-label": "teammate@company.com",
|
|
140
|
-
type: "email",
|
|
141
|
-
value: j,
|
|
142
|
-
onChange: (e) => M(e.target.value),
|
|
143
|
-
placeholder: "teammate@company.com",
|
|
144
|
-
required: !0,
|
|
145
|
-
className: "w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg"
|
|
146
|
-
}),
|
|
147
|
-
/* @__PURE__ */ b("p", {
|
|
148
|
-
className: "mt-1 text-xs text-text-secondary",
|
|
149
|
-
children: T("vibecontrols.sessions.share.mustBeWorkspaceMember", "Must be an existing workspace member")
|
|
150
|
-
})
|
|
151
|
-
] }),
|
|
152
|
-
/* @__PURE__ */ x("div", {
|
|
153
|
-
className: "grid grid-cols-2 gap-4",
|
|
154
|
-
children: [/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("label", {
|
|
155
|
-
className: "block text-sm font-medium text-text-primary mb-1",
|
|
156
|
-
children: T("vibecontrols.sessions.share.permission", "Permission")
|
|
157
|
-
}), /* @__PURE__ */ x("select", {
|
|
158
|
-
value: N,
|
|
159
|
-
onChange: (e) => le(e.target.value),
|
|
160
|
-
className: "w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg",
|
|
161
|
-
children: [/* @__PURE__ */ b("option", {
|
|
162
|
-
value: o.View,
|
|
163
|
-
children: T("vibecontrols.sessions.share.viewOnly", "View Only")
|
|
164
|
-
}), /* @__PURE__ */ b("option", {
|
|
165
|
-
value: o.Interact,
|
|
166
|
-
children: T("vibecontrols.sessions.share.canControl", "Can Control")
|
|
167
|
-
})]
|
|
168
|
-
})] }), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("label", {
|
|
169
|
-
className: "block text-sm font-medium text-text-primary mb-1",
|
|
170
|
-
children: T("vibecontrols.sessions.share.expiresIn", "Expires In")
|
|
171
|
-
}), /* @__PURE__ */ x("select", {
|
|
172
|
-
value: I,
|
|
173
|
-
onChange: (e) => ue(Number(e.target.value)),
|
|
174
|
-
className: "w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg",
|
|
175
|
-
children: [
|
|
176
|
-
/* @__PURE__ */ b("option", {
|
|
177
|
-
value: 1,
|
|
178
|
-
children: "1 hour"
|
|
179
|
-
}),
|
|
180
|
-
/* @__PURE__ */ b("option", {
|
|
181
|
-
value: 4,
|
|
182
|
-
children: "4 hours"
|
|
183
|
-
}),
|
|
184
|
-
/* @__PURE__ */ b("option", {
|
|
185
|
-
value: 8,
|
|
186
|
-
children: "8 hours"
|
|
187
|
-
}),
|
|
188
|
-
/* @__PURE__ */ b("option", {
|
|
189
|
-
value: 24,
|
|
190
|
-
children: "24 hours"
|
|
191
|
-
}),
|
|
192
|
-
/* @__PURE__ */ b("option", {
|
|
193
|
-
value: 72,
|
|
194
|
-
children: "3 days"
|
|
195
|
-
}),
|
|
196
|
-
/* @__PURE__ */ b("option", {
|
|
197
|
-
value: 168,
|
|
198
|
-
children: "1 week"
|
|
199
|
-
})
|
|
200
|
-
]
|
|
201
|
-
})] })]
|
|
202
|
-
}),
|
|
203
|
-
/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("label", {
|
|
204
|
-
className: "block text-sm font-medium text-text-primary mb-1",
|
|
205
|
-
children: T("vibecontrols.sessions.share.messageOptional", "Message (optional)")
|
|
206
|
-
}), /* @__PURE__ */ b("textarea", {
|
|
207
|
-
"aria-label": "Let me show you this issue...",
|
|
208
|
-
value: P,
|
|
209
|
-
onChange: (e) => F(e.target.value),
|
|
210
|
-
placeholder: "Let me show you this issue...",
|
|
211
|
-
rows: 2,
|
|
212
|
-
className: "w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg resize-none"
|
|
213
|
-
})] }),
|
|
214
|
-
/* @__PURE__ */ b("div", {
|
|
215
|
-
className: "flex items-center gap-2 p-3 bg-bg-sunken rounded-lg text-sm",
|
|
216
|
-
children: N === o.View ? /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(f, { className: "size-4 text-text-secondary" }), /* @__PURE__ */ b("span", {
|
|
217
|
-
className: "text-text-secondary",
|
|
218
|
-
children: T("vibecontrols.sessions.share.viewOnlyHint", "User can watch the terminal but cannot type")
|
|
219
|
-
})] }) : /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(p, { className: "size-4 text-text-secondary" }), /* @__PURE__ */ b("span", {
|
|
220
|
-
className: "text-text-secondary",
|
|
221
|
-
children: T("vibecontrols.sessions.share.controlHint", "User can request control to type (turn-based)")
|
|
222
|
-
})] })
|
|
223
|
-
}),
|
|
224
|
-
/* @__PURE__ */ b("button", {
|
|
225
|
-
type: "submit",
|
|
226
|
-
disabled: Y || !j.trim(),
|
|
227
|
-
className: "w-full px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50",
|
|
228
|
-
children: Y ? T("vibecontrols.sessions.share.sharing", "Sharing...") : T("vibecontrols.sessions.share.shareSession", "Share Session")
|
|
229
|
-
})
|
|
230
|
-
]
|
|
231
|
-
}), Z.length > 0 && /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("h3", {
|
|
232
|
-
className: "text-sm font-medium text-text-primary mb-3",
|
|
233
|
-
children: T("vibecontrols.sessions.share.currentlySharedWith", "Currently Shared With")
|
|
234
|
-
}), /* @__PURE__ */ b("div", {
|
|
235
|
-
className: "space-y-2",
|
|
236
|
-
children: Z.map((e) => /* @__PURE__ */ x("div", {
|
|
237
|
-
className: "flex items-center justify-between p-3 bg-bg-sunken rounded-lg",
|
|
238
|
-
children: [/* @__PURE__ */ x("div", {
|
|
239
|
-
className: "flex items-center gap-3",
|
|
240
|
-
children: [/* @__PURE__ */ b("div", {
|
|
241
|
-
className: "size-8 rounded-full bg-action-primary-bg/20 flex items-center justify-center",
|
|
242
|
-
children: /* @__PURE__ */ b(_, { className: "size-4 text-action-primary-bg" })
|
|
243
|
-
}), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ x("p", {
|
|
244
|
-
className: "text-sm font-medium text-text-primary",
|
|
245
|
-
children: [
|
|
246
|
-
"User: ",
|
|
247
|
-
e.sharedWithId.slice(0, 8),
|
|
248
|
-
"..."
|
|
249
|
-
]
|
|
250
|
-
}), /* @__PURE__ */ x("div", {
|
|
251
|
-
className: "flex items-center gap-2 text-xs text-text-secondary",
|
|
252
|
-
children: [
|
|
253
|
-
e.permission === o.View ? /* @__PURE__ */ b(f, { className: "size-3" }) : /* @__PURE__ */ b(p, { className: "size-3" }),
|
|
254
|
-
/* @__PURE__ */ b("span", { children: e.permission }),
|
|
255
|
-
e.expiresAt && /* @__PURE__ */ x(y, { children: [
|
|
256
|
-
/* @__PURE__ */ b("span", { children: "·" }),
|
|
257
|
-
/* @__PURE__ */ b(u, { className: "size-3" }),
|
|
258
|
-
/* @__PURE__ */ b("span", { children: $(e.expiresAt) })
|
|
259
|
-
] })
|
|
260
|
-
]
|
|
261
|
-
})] })]
|
|
262
|
-
}), /* @__PURE__ */ b("button", {
|
|
263
|
-
type: "button",
|
|
264
|
-
onClick: () => xe(e.id),
|
|
265
|
-
disabled: ge,
|
|
266
|
-
className: "p-1.5 text-text-secondary hover:text-status-error-text hover:bg-status-error-bg/10 rounded transition-colors",
|
|
267
|
-
title: "Revoke access",
|
|
268
|
-
children: /* @__PURE__ */ b(g, { className: "size-4" })
|
|
269
|
-
})]
|
|
270
|
-
}, e.id))
|
|
271
|
-
})] })]
|
|
272
|
-
}) : /* @__PURE__ */ x("div", {
|
|
273
|
-
className: "space-y-6",
|
|
274
|
-
children: [/* @__PURE__ */ x("form", {
|
|
275
|
-
onSubmit: be,
|
|
276
|
-
className: "space-y-4",
|
|
277
|
-
children: [
|
|
278
|
-
/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("label", {
|
|
279
|
-
className: "block text-sm font-medium text-text-primary mb-1",
|
|
280
|
-
children: T("vibecontrols.sessions.share.linkNameOptional", "Link Name (optional)")
|
|
281
|
-
}), /* @__PURE__ */ b("input", {
|
|
282
|
-
"aria-label": "Debug session link",
|
|
283
|
-
type: "text",
|
|
284
|
-
value: L,
|
|
285
|
-
onChange: (e) => R(e.target.value),
|
|
286
|
-
placeholder: "Debug session link",
|
|
287
|
-
className: "w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg"
|
|
288
|
-
})] }),
|
|
289
|
-
/* @__PURE__ */ x("div", {
|
|
290
|
-
className: "grid grid-cols-2 gap-4",
|
|
291
|
-
children: [/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("label", {
|
|
292
|
-
className: "block text-sm font-medium text-text-primary mb-1",
|
|
293
|
-
children: T("vibecontrols.sessions.share.permission", "Permission")
|
|
294
|
-
}), /* @__PURE__ */ x("select", {
|
|
295
|
-
value: z,
|
|
296
|
-
onChange: (e) => B(e.target.value),
|
|
297
|
-
className: "w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg",
|
|
298
|
-
children: [/* @__PURE__ */ b("option", {
|
|
299
|
-
value: o.View,
|
|
300
|
-
children: T("vibecontrols.sessions.share.viewOnly", "View Only")
|
|
301
|
-
}), /* @__PURE__ */ b("option", {
|
|
302
|
-
value: o.Interact,
|
|
303
|
-
children: T("vibecontrols.sessions.share.canControl", "Can Control")
|
|
304
|
-
})]
|
|
305
|
-
})] }), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("label", {
|
|
306
|
-
className: "block text-sm font-medium text-text-primary mb-1",
|
|
307
|
-
children: T("vibecontrols.sessions.share.expiresIn", "Expires In")
|
|
308
|
-
}), /* @__PURE__ */ x("select", {
|
|
309
|
-
value: V,
|
|
310
|
-
onChange: (e) => H(Number(e.target.value)),
|
|
311
|
-
className: "w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg",
|
|
312
|
-
children: [
|
|
313
|
-
/* @__PURE__ */ b("option", {
|
|
314
|
-
value: 1,
|
|
315
|
-
children: "1 hour"
|
|
316
|
-
}),
|
|
317
|
-
/* @__PURE__ */ b("option", {
|
|
318
|
-
value: 4,
|
|
319
|
-
children: "4 hours"
|
|
320
|
-
}),
|
|
321
|
-
/* @__PURE__ */ b("option", {
|
|
322
|
-
value: 8,
|
|
323
|
-
children: "8 hours"
|
|
324
|
-
}),
|
|
325
|
-
/* @__PURE__ */ b("option", {
|
|
326
|
-
value: 24,
|
|
327
|
-
children: "24 hours"
|
|
328
|
-
}),
|
|
329
|
-
/* @__PURE__ */ b("option", {
|
|
330
|
-
value: 72,
|
|
331
|
-
children: "3 days"
|
|
332
|
-
})
|
|
333
|
-
]
|
|
334
|
-
})] })]
|
|
335
|
-
}),
|
|
336
|
-
/* @__PURE__ */ x("div", {
|
|
337
|
-
className: "grid grid-cols-2 gap-4",
|
|
338
|
-
children: [/* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("label", {
|
|
339
|
-
className: "block text-sm font-medium text-text-primary mb-1",
|
|
340
|
-
children: T("vibecontrols.sessions.share.passwordOptional", "Password (optional)")
|
|
341
|
-
}), /* @__PURE__ */ b("input", {
|
|
342
|
-
"aria-label": "••••••••",
|
|
343
|
-
type: "password",
|
|
344
|
-
value: U,
|
|
345
|
-
onChange: (e) => W(e.target.value),
|
|
346
|
-
placeholder: "••••••••",
|
|
347
|
-
className: "w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg"
|
|
348
|
-
})] }), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("label", {
|
|
349
|
-
className: "block text-sm font-medium text-text-primary mb-1",
|
|
350
|
-
children: T("vibecontrols.sessions.share.maxUses", "Max Uses")
|
|
351
|
-
}), /* @__PURE__ */ b("input", {
|
|
352
|
-
"aria-label": "Unlimited",
|
|
353
|
-
type: "number",
|
|
354
|
-
value: G ?? "",
|
|
355
|
-
onChange: (e) => K(e.target.value ? Number(e.target.value) : null),
|
|
356
|
-
placeholder: "Unlimited",
|
|
357
|
-
min: 1,
|
|
358
|
-
className: "w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg"
|
|
359
|
-
})] })]
|
|
360
|
-
}),
|
|
361
|
-
/* @__PURE__ */ b("button", {
|
|
362
|
-
type: "submit",
|
|
363
|
-
disabled: X,
|
|
364
|
-
className: "w-full px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50",
|
|
365
|
-
children: X ? T("vibecontrols.sessions.share.creating", "Creating...") : T("vibecontrols.sessions.share.createShareLink", "Create Share Link")
|
|
366
|
-
})
|
|
367
|
-
]
|
|
368
|
-
}), Q.length > 0 && /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("h3", {
|
|
369
|
-
className: "text-sm font-medium text-text-primary mb-3",
|
|
370
|
-
children: T("vibecontrols.sessions.share.activeLinks", "Active Links")
|
|
371
|
-
}), /* @__PURE__ */ b("div", {
|
|
372
|
-
className: "space-y-2",
|
|
373
|
-
children: Q.map((e) => /* @__PURE__ */ x("div", {
|
|
374
|
-
className: "p-3 bg-bg-sunken rounded-lg space-y-2",
|
|
375
|
-
children: [
|
|
376
|
-
/* @__PURE__ */ x("div", {
|
|
377
|
-
className: "flex items-center justify-between",
|
|
378
|
-
children: [/* @__PURE__ */ x("div", {
|
|
379
|
-
className: "flex items-center gap-2",
|
|
380
|
-
children: [
|
|
381
|
-
/* @__PURE__ */ b(m, { className: "size-4 text-action-primary-bg" }),
|
|
382
|
-
/* @__PURE__ */ b("span", {
|
|
383
|
-
className: "text-sm font-medium text-text-primary",
|
|
384
|
-
children: e.name || "Unnamed Link"
|
|
385
|
-
}),
|
|
386
|
-
e.hasPassword && /* @__PURE__ */ b(ae, { className: "size-3 text-text-secondary" })
|
|
387
|
-
]
|
|
388
|
-
}), /* @__PURE__ */ x("div", {
|
|
389
|
-
className: "flex items-center gap-1",
|
|
390
|
-
children: [/* @__PURE__ */ b("button", {
|
|
391
|
-
type: "button",
|
|
392
|
-
onClick: () => Ce(e.id, e.shareUrl),
|
|
393
|
-
className: "p-1.5 text-text-secondary hover:text-action-primary-bg hover:bg-action-primary-bg/10 rounded transition-colors",
|
|
394
|
-
title: "Copy link",
|
|
395
|
-
children: se === e.id ? /* @__PURE__ */ b(ie, { className: "size-4 text-status-success-text" }) : ce === e.id ? /* @__PURE__ */ b(v, { className: "size-4 text-status-error-text" }) : /* @__PURE__ */ b(d, { className: "size-4" })
|
|
396
|
-
}), /* @__PURE__ */ b("button", {
|
|
397
|
-
type: "button",
|
|
398
|
-
onClick: () => Se(e.id),
|
|
399
|
-
disabled: ve,
|
|
400
|
-
className: "p-1.5 text-text-secondary hover:text-status-error-text hover:bg-status-error-bg/10 rounded transition-colors",
|
|
401
|
-
title: "Revoke link",
|
|
402
|
-
children: /* @__PURE__ */ b(g, { className: "size-4" })
|
|
403
|
-
})]
|
|
404
|
-
})]
|
|
405
|
-
}),
|
|
406
|
-
/* @__PURE__ */ x("div", {
|
|
407
|
-
className: "flex items-center gap-3 text-xs text-text-secondary",
|
|
408
|
-
children: [
|
|
409
|
-
e.permission === o.View ? /* @__PURE__ */ x("span", {
|
|
410
|
-
className: "flex items-center gap-1",
|
|
411
|
-
children: [/* @__PURE__ */ b(f, { className: "size-3" }), " View"]
|
|
412
|
-
}) : /* @__PURE__ */ x("span", {
|
|
413
|
-
className: "flex items-center gap-1",
|
|
414
|
-
children: [/* @__PURE__ */ b(p, { className: "size-3" }), " Control"]
|
|
415
|
-
}),
|
|
416
|
-
/* @__PURE__ */ b("span", { children: "·" }),
|
|
417
|
-
/* @__PURE__ */ x("span", {
|
|
418
|
-
className: "flex items-center gap-1",
|
|
419
|
-
children: [
|
|
420
|
-
/* @__PURE__ */ b(u, { className: "size-3" }),
|
|
421
|
-
" ",
|
|
422
|
-
$(e.expiresAt)
|
|
423
|
-
]
|
|
424
|
-
}),
|
|
425
|
-
/* @__PURE__ */ b("span", { children: "·" }),
|
|
426
|
-
/* @__PURE__ */ x("span", {
|
|
427
|
-
className: "flex items-center gap-1",
|
|
428
|
-
children: [
|
|
429
|
-
/* @__PURE__ */ b(h, { className: "size-3" }),
|
|
430
|
-
" ",
|
|
431
|
-
e.useCount,
|
|
432
|
-
e.maxUses ? `/${e.maxUses}` : "",
|
|
433
|
-
" uses"
|
|
434
|
-
]
|
|
435
|
-
})
|
|
436
|
-
]
|
|
437
|
-
}),
|
|
438
|
-
/* @__PURE__ */ b("div", {
|
|
439
|
-
className: "flex items-center gap-2",
|
|
440
|
-
children: /* @__PURE__ */ b("input", {
|
|
441
|
-
"aria-label": "control",
|
|
442
|
-
type: "text",
|
|
443
|
-
value: c(e.shareUrl),
|
|
444
|
-
readOnly: !0,
|
|
445
|
-
className: "flex-1 px-2 py-1 text-xs font-mono bg-bg-surface border border-border-default rounded text-text-secondary truncate"
|
|
446
|
-
})
|
|
447
|
-
})
|
|
448
|
-
]
|
|
449
|
-
}, e.id))
|
|
450
|
-
})] })]
|
|
451
|
-
})
|
|
452
|
-
}),
|
|
453
|
-
/* @__PURE__ */ b("div", {
|
|
454
|
-
className: "px-6 py-4 bg-bg-sunken border-t border-border-default rounded-b-lg",
|
|
455
|
-
children: /* @__PURE__ */ b("p", {
|
|
456
|
-
className: "text-xs text-text-secondary text-center",
|
|
457
|
-
children: T("vibecontrols.sessions.share.footerNote", "Shared users must be logged in to access the session")
|
|
458
|
-
})
|
|
459
|
-
})
|
|
460
|
-
]
|
|
461
|
-
})
|
|
462
|
-
}) : null;
|
|
6
|
+
var i = ({ session: i, isOpen: a, onClose: o }) => {
|
|
7
|
+
let s = e("session", {
|
|
8
|
+
id: i.id,
|
|
9
|
+
vibeId: i.vibeId ?? null
|
|
10
|
+
});
|
|
11
|
+
return /* @__PURE__ */ n(r, {
|
|
12
|
+
resource: {
|
|
13
|
+
type: "session",
|
|
14
|
+
id: i.id,
|
|
15
|
+
name: i.name,
|
|
16
|
+
vibeId: i.vibeId ?? void 0
|
|
17
|
+
},
|
|
18
|
+
controller: s,
|
|
19
|
+
open: a,
|
|
20
|
+
onOpenChange: (e) => {
|
|
21
|
+
e || o();
|
|
22
|
+
},
|
|
23
|
+
workspaceId: t() ?? void 0
|
|
24
|
+
});
|
|
463
25
|
};
|
|
464
26
|
//#endregion
|
|
465
|
-
export {
|
|
27
|
+
export { i as SessionShareDialog };
|
|
466
28
|
|
|
467
29
|
//# sourceMappingURL=SessionShareDialog.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionShareDialog.js","names":[],"sources":["../../../src/components/sessions/SessionShareDialog.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useState, useEffect, useRef } from 'react';\nimport {\n X,\n Share2,\n Link2,\n Users,\n Copy,\n Check,\n Eye,\n Gamepad2,\n Clock,\n Lock,\n Trash2,\n RefreshCw,\n} from 'lucide-react';\nimport type { Session } from './types';\nimport {\n useShareSessionMutation,\n useCreateSessionShareLinkMutation,\n useRevokeSessionShareMutation,\n useRevokeSessionShareLinkMutation,\n useGetSessionSharesQuery,\n useGetSessionShareLinksQuery,\n type SessionShareFieldsFragment,\n type SessionShareLinkFieldsFragment,\n} from '../../generated/wspace-operations';\nimport { SessionSharePermission, ShareStatus } from '../../generated/wspace-types';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { copyTextToClipboard, normalizeShareUrl } from '../../utils/shareUrl';\n\ntype TabType = 'users' | 'links';\n\ninterface SessionShareDialogProps {\n session: Session;\n isOpen: boolean;\n onClose: () => void;\n}\n\n/**\n * SessionShareDialog - Modal for sharing terminal sessions\n * Supports sharing with specific users or creating shareable links\n */\nexport const SessionShareDialog: FC<SessionShareDialogProps> = ({ session, isOpen, onClose }) => {\n const tr = useTr();\n const dialogRef = useRef<HTMLDialogElement>(null);\n const [activeTab, setActiveTab] = useState<TabType>('users');\n const [copied, setCopied] = useState<string | null>(null);\n const [copyFailed, setCopyFailed] = useState<string | null>(null);\n\n // Share with user form state\n const [email, setEmail] = useState('');\n const [permission, setPermission] = useState<SessionSharePermission>(SessionSharePermission.View);\n const [message, setMessage] = useState('');\n const [expiresInHours, setExpiresInHours] = useState(24);\n\n // Link form state\n const [linkName, setLinkName] = useState('');\n const [linkPermission, setLinkPermission] = useState<SessionSharePermission>(\n SessionSharePermission.View\n );\n const [linkExpiresInHours, setLinkExpiresInHours] = useState(1);\n const [linkPassword, setLinkPassword] = useState('');\n const [maxUses, setMaxUses] = useState<number | null>(null);\n\n // Queries for existing shares\n const { data: sharesData, refetch: refetchShares } = useGetSessionSharesQuery({\n variables: { sessionId: session.id },\n skip: !isOpen,\n });\n\n const { data: linksData, refetch: refetchLinks } = useGetSessionShareLinksQuery({\n variables: { sessionId: session.id },\n skip: !isOpen,\n });\n\n // Mutations\n const [shareSession, { loading: sharingUser }] = useShareSessionMutation();\n const [createLink, { loading: creatingLink }] = useCreateSessionShareLinkMutation();\n const [revokeShare, { loading: revokingShare }] = useRevokeSessionShareMutation();\n const [revokeLink, { loading: revokingLink }] = useRevokeSessionShareLinkMutation();\n\n const existingShares: SessionShareFieldsFragment[] =\n sharesData?.sessionShares?.filter(\n (s: SessionShareFieldsFragment) => s.status === ShareStatus.Active\n ) || [];\n const existingLinks: SessionShareLinkFieldsFragment[] =\n linksData?.sessionShareLinks?.filter(\n (l: SessionShareLinkFieldsFragment) => l.status === ShareStatus.Active\n ) || [];\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n\n if (isOpen) {\n dialog.showModal();\n } else {\n dialog.close();\n }\n }, [isOpen]);\n\n const handleShareWithUser = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!email.trim()) return;\n\n try {\n const expiresAt = new Date(Date.now() + expiresInHours * 60 * 60 * 1000).toISOString();\n await shareSession({\n variables: {\n input: {\n sessionId: session.id,\n sharedWithEmail: email.trim(),\n permission,\n expiresAt,\n message: message.trim() || undefined,\n },\n },\n });\n setEmail('');\n setMessage('');\n refetchShares();\n } catch (error) {\n console.error('Failed to share session:', error);\n }\n };\n\n const handleCreateLink = async (e: React.FormEvent) => {\n e.preventDefault();\n\n try {\n await createLink({\n variables: {\n input: {\n sessionId: session.id,\n name: linkName.trim() || undefined,\n permission: linkPermission,\n expiresInHours: linkExpiresInHours,\n maxUses: maxUses || undefined,\n password: linkPassword.trim() || undefined,\n },\n },\n });\n setLinkName('');\n setLinkPassword('');\n setMaxUses(null);\n refetchLinks();\n } catch (error) {\n console.error('Failed to create share link:', error);\n }\n };\n\n const handleRevokeShare = async (shareId: string) => {\n try {\n await revokeShare({ variables: { id: shareId } });\n refetchShares();\n } catch (error) {\n console.error('Failed to revoke share:', error);\n }\n };\n\n const handleRevokeLink = async (linkId: string) => {\n try {\n await revokeLink({ variables: { id: linkId } });\n refetchLinks();\n } catch (error) {\n console.error('Failed to revoke link:', error);\n }\n };\n\n const copyToClipboard = async (id: string, text: string) => {\n const shareUrl = normalizeShareUrl(text);\n const ok = await copyTextToClipboard(shareUrl).then(\n () => true,\n (error) => {\n console.warn('Failed to copy session share link:', error);\n return false;\n }\n );\n setCopied(ok ? id : null);\n setCopyFailed(ok ? null : id);\n setTimeout(() => {\n setCopied((current) => (current === id ? null : current));\n setCopyFailed((current) => (current === id ? null : current));\n }, 2000);\n };\n\n const formatExpiry = (expiresAt: string) => {\n const expiry = new Date(expiresAt);\n const now = new Date();\n const diffMs = expiry.getTime() - now.getTime();\n const diffHours = Math.floor(diffMs / (1000 * 60 * 60));\n const diffMins = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));\n\n if (diffMs < 0) return 'Expired';\n if (diffHours > 24) return `${Math.floor(diffHours / 24)}d`;\n if (diffHours > 0) return `${diffHours}h ${diffMins}m`;\n return `${diffMins}m`;\n };\n\n if (!isOpen) return null;\n\n return (\n <dialog\n ref={dialogRef}\n className=\"fixed inset-0 z-50 m-auto bg-bg-overlay/0 p-0 backdrop:bg-bg-overlay\"\n onClose={onClose}\n >\n <div className=\"w-full max-w-xl bg-bg-surface rounded-lg shadow-xl max-h-[85vh] flex flex-col\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border-default\">\n <div className=\"flex items-center gap-3\">\n <div className=\"p-2 bg-action-primary-bg/10 rounded-lg\">\n <Share2 className=\"size-5 text-action-primary-bg\" />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('vibecontrols.sessions.share.title', 'Share Session')}\n </h2>\n <p className=\"text-sm text-text-secondary truncate max-w-[300px]\">{session.name}</p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1.5 rounded hover:bg-bg-sunken transition-colors\"\n >\n <X className=\"size-5 text-text-secondary\" />\n </button>\n </div>\n\n {/* Tabs */}\n <div className=\"flex border-b border-border-default\">\n <button\n type=\"button\"\n onClick={() => setActiveTab('users')}\n className={`flex items-center gap-2 px-6 py-3 text-sm font-medium transition-colors ${\n activeTab === 'users'\n ? 'text-action-primary-bg border-b-2 border-action-primary-bg'\n : 'text-text-secondary hover:text-text-primary'\n }`}\n >\n <Users className=\"size-4\" />\n {tr('vibecontrols.sessions.share.shareWithUser', 'Share with User')}\n {existingShares.length > 0 && (\n <span className=\"ml-1 px-1.5 py-0.5 text-xs bg-bg-sunken rounded-full\">\n {existingShares.length}\n </span>\n )}\n </button>\n <button\n type=\"button\"\n onClick={() => setActiveTab('links')}\n className={`flex items-center gap-2 px-6 py-3 text-sm font-medium transition-colors ${\n activeTab === 'links'\n ? 'text-action-primary-bg border-b-2 border-action-primary-bg'\n : 'text-text-secondary hover:text-text-primary'\n }`}\n >\n <Link2 className=\"size-4\" />\n {tr('vibecontrols.sessions.share.createLink', 'Create Link')}\n {existingLinks.length > 0 && (\n <span className=\"ml-1 px-1.5 py-0.5 text-xs bg-bg-sunken rounded-full\">\n {existingLinks.length}\n </span>\n )}\n </button>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-y-auto p-6\">\n {activeTab === 'users' ? (\n <div className=\"space-y-6\">\n {/* Share form */}\n <form onSubmit={handleShareWithUser} className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.sessions.share.emailAddress', 'Email Address')}\n </label>\n <input\n aria-label=\"teammate@company.com\"\n type=\"email\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n placeholder=\"teammate@company.com\"\n required\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n <p className=\"mt-1 text-xs text-text-secondary\">\n {tr(\n 'vibecontrols.sessions.share.mustBeWorkspaceMember',\n 'Must be an existing workspace member'\n )}\n </p>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.sessions.share.permission', 'Permission')}\n </label>\n <select\n value={permission}\n onChange={(e) => setPermission(e.target.value as SessionSharePermission)}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n >\n <option value={SessionSharePermission.View}>\n {tr('vibecontrols.sessions.share.viewOnly', 'View Only')}\n </option>\n <option value={SessionSharePermission.Interact}>\n {tr('vibecontrols.sessions.share.canControl', 'Can Control')}\n </option>\n </select>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.sessions.share.expiresIn', 'Expires In')}\n </label>\n <select\n value={expiresInHours}\n onChange={(e) => setExpiresInHours(Number(e.target.value))}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n >\n <option value={1}>1 hour</option>\n <option value={4}>4 hours</option>\n <option value={8}>8 hours</option>\n <option value={24}>24 hours</option>\n <option value={72}>3 days</option>\n <option value={168}>1 week</option>\n </select>\n </div>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.sessions.share.messageOptional', 'Message (optional)')}\n </label>\n <textarea\n aria-label=\"Let me show you this issue...\"\n value={message}\n onChange={(e) => setMessage(e.target.value)}\n placeholder=\"Let me show you this issue...\"\n rows={2}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg resize-none\"\n />\n </div>\n\n <div className=\"flex items-center gap-2 p-3 bg-bg-sunken rounded-lg text-sm\">\n {permission === SessionSharePermission.View ? (\n <>\n <Eye className=\"size-4 text-text-secondary\" />\n <span className=\"text-text-secondary\">\n {tr(\n 'vibecontrols.sessions.share.viewOnlyHint',\n 'User can watch the terminal but cannot type'\n )}\n </span>\n </>\n ) : (\n <>\n <Gamepad2 className=\"size-4 text-text-secondary\" />\n <span className=\"text-text-secondary\">\n {tr(\n 'vibecontrols.sessions.share.controlHint',\n 'User can request control to type (turn-based)'\n )}\n </span>\n </>\n )}\n </div>\n\n <button\n type=\"submit\"\n disabled={sharingUser || !email.trim()}\n className=\"w-full px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {sharingUser\n ? tr('vibecontrols.sessions.share.sharing', 'Sharing...')\n : tr('vibecontrols.sessions.share.shareSession', 'Share Session')}\n </button>\n </form>\n\n {/* Existing shares */}\n {existingShares.length > 0 && (\n <div>\n <h3 className=\"text-sm font-medium text-text-primary mb-3\">\n {tr('vibecontrols.sessions.share.currentlySharedWith', 'Currently Shared With')}\n </h3>\n <div className=\"space-y-2\">\n {existingShares.map((share) => (\n <div\n key={share.id}\n className=\"flex items-center justify-between p-3 bg-bg-sunken rounded-lg\"\n >\n <div className=\"flex items-center gap-3\">\n <div className=\"size-8 rounded-full bg-action-primary-bg/20 flex items-center justify-center\">\n <Users className=\"size-4 text-action-primary-bg\" />\n </div>\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n User: {share.sharedWithId.slice(0, 8)}...\n </p>\n <div className=\"flex items-center gap-2 text-xs text-text-secondary\">\n {share.permission === SessionSharePermission.View ? (\n <Eye className=\"size-3\" />\n ) : (\n <Gamepad2 className=\"size-3\" />\n )}\n <span>{share.permission}</span>\n {share.expiresAt && (\n <>\n <span>·</span>\n <Clock className=\"size-3\" />\n <span>{formatExpiry(share.expiresAt)}</span>\n </>\n )}\n </div>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => handleRevokeShare(share.id)}\n disabled={revokingShare}\n className=\"p-1.5 text-text-secondary hover:text-status-error-text hover:bg-status-error-bg/10 rounded transition-colors\"\n title=\"Revoke access\"\n >\n <Trash2 className=\"size-4\" />\n </button>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n ) : (\n <div className=\"space-y-6\">\n {/* Create link form */}\n <form onSubmit={handleCreateLink} className=\"space-y-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.sessions.share.linkNameOptional', 'Link Name (optional)')}\n </label>\n <input\n aria-label=\"Debug session link\"\n type=\"text\"\n value={linkName}\n onChange={(e) => setLinkName(e.target.value)}\n placeholder=\"Debug session link\"\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.sessions.share.permission', 'Permission')}\n </label>\n <select\n value={linkPermission}\n onChange={(e) => setLinkPermission(e.target.value as SessionSharePermission)}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n >\n <option value={SessionSharePermission.View}>\n {tr('vibecontrols.sessions.share.viewOnly', 'View Only')}\n </option>\n <option value={SessionSharePermission.Interact}>\n {tr('vibecontrols.sessions.share.canControl', 'Can Control')}\n </option>\n </select>\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.sessions.share.expiresIn', 'Expires In')}\n </label>\n <select\n value={linkExpiresInHours}\n onChange={(e) => setLinkExpiresInHours(Number(e.target.value))}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n >\n <option value={1}>1 hour</option>\n <option value={4}>4 hours</option>\n <option value={8}>8 hours</option>\n <option value={24}>24 hours</option>\n <option value={72}>3 days</option>\n </select>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.sessions.share.passwordOptional', 'Password (optional)')}\n </label>\n <input\n aria-label=\"••••••••\"\n type=\"password\"\n value={linkPassword}\n onChange={(e) => setLinkPassword(e.target.value)}\n placeholder=\"••••••••\"\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n <div>\n <label className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('vibecontrols.sessions.share.maxUses', 'Max Uses')}\n </label>\n <input\n aria-label=\"Unlimited\"\n type=\"number\"\n value={maxUses ?? ''}\n onChange={(e) => setMaxUses(e.target.value ? Number(e.target.value) : null)}\n placeholder=\"Unlimited\"\n min={1}\n className=\"w-full px-3 py-2 text-sm bg-bg-sunken border border-border-default rounded-md text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n />\n </div>\n </div>\n\n <button\n type=\"submit\"\n disabled={creatingLink}\n className=\"w-full px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-md hover:bg-action-primary-bg-hover transition-colors disabled:opacity-50\"\n >\n {creatingLink\n ? tr('vibecontrols.sessions.share.creating', 'Creating...')\n : tr('vibecontrols.sessions.share.createShareLink', 'Create Share Link')}\n </button>\n </form>\n\n {/* Existing links */}\n {existingLinks.length > 0 && (\n <div>\n <h3 className=\"text-sm font-medium text-text-primary mb-3\">\n {tr('vibecontrols.sessions.share.activeLinks', 'Active Links')}\n </h3>\n <div className=\"space-y-2\">\n {existingLinks.map((link) => (\n <div key={link.id} className=\"p-3 bg-bg-sunken rounded-lg space-y-2\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <Link2 className=\"size-4 text-action-primary-bg\" />\n <span className=\"text-sm font-medium text-text-primary\">\n {link.name || 'Unnamed Link'}\n </span>\n {link.hasPassword && <Lock className=\"size-3 text-text-secondary\" />}\n </div>\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => copyToClipboard(link.id, link.shareUrl)}\n className=\"p-1.5 text-text-secondary hover:text-action-primary-bg hover:bg-action-primary-bg/10 rounded transition-colors\"\n title=\"Copy link\"\n >\n {copied === link.id ? (\n <Check className=\"size-4 text-status-success-text\" />\n ) : copyFailed === link.id ? (\n <X className=\"size-4 text-status-error-text\" />\n ) : (\n <Copy className=\"size-4\" />\n )}\n </button>\n <button\n type=\"button\"\n onClick={() => handleRevokeLink(link.id)}\n disabled={revokingLink}\n className=\"p-1.5 text-text-secondary hover:text-status-error-text hover:bg-status-error-bg/10 rounded transition-colors\"\n title=\"Revoke link\"\n >\n <Trash2 className=\"size-4\" />\n </button>\n </div>\n </div>\n <div className=\"flex items-center gap-3 text-xs text-text-secondary\">\n {link.permission === SessionSharePermission.View ? (\n <span className=\"flex items-center gap-1\">\n <Eye className=\"size-3\" /> View\n </span>\n ) : (\n <span className=\"flex items-center gap-1\">\n <Gamepad2 className=\"size-3\" /> Control\n </span>\n )}\n <span>·</span>\n <span className=\"flex items-center gap-1\">\n <Clock className=\"size-3\" /> {formatExpiry(link.expiresAt)}\n </span>\n <span>·</span>\n <span className=\"flex items-center gap-1\">\n <RefreshCw className=\"size-3\" /> {link.useCount}\n {link.maxUses ? `/${link.maxUses}` : ''} uses\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <input\n aria-label=\"control\"\n type=\"text\"\n value={normalizeShareUrl(link.shareUrl)}\n readOnly\n className=\"flex-1 px-2 py-1 text-xs font-mono bg-bg-surface border border-border-default rounded text-text-secondary truncate\"\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"px-6 py-4 bg-bg-sunken border-t border-border-default rounded-b-lg\">\n <p className=\"text-xs text-text-secondary text-center\">\n {tr(\n 'vibecontrols.sessions.share.footerNote',\n 'Shared users must be logged in to access the session'\n )}\n </p>\n </div>\n </div>\n </dialog>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionShareDialog.js","names":[],"sources":["../../../src/components/sessions/SessionShareDialog.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { ShareDialog } from '@burdenoff/fe-libs/sharing';\nimport { getStoredWorkspaceId } from '@burdenoff/fe-libs/shared/graphql';\n\nimport { useEntityShareController } from '../sharing/useEntityShareController';\nimport type { Session } from './types';\n\ninterface SessionShareDialogProps {\n session: Session;\n isOpen: boolean;\n onClose: () => void;\n}\n\n/**\n * SessionShareDialog — thin controlled wrapper around the generic fe-libs\n * `<ShareDialog>` for a terminal session.\n *\n * It previously hosted a bespoke share UI (legacy `shareSession` /\n * `createSessionShareLink` ops + `SessionShare` / `SessionShareLink` tables).\n * That bespoke surface was pure share-record management — it never drove\n * realtime collaboration. Live terminal control handoff + collaborator presence\n * live entirely in `SharedTerminalPanel` / `SharedSessionPage`, driven by the\n * session's collaborator list, NOT by this dialog. So the body has been\n * replaced with the richer generic dialog (email invite + accept-gate + four\n * visibility modes + expiry + public link) backed by the generic\n * `shareSessionGrant` grant mutations.\n *\n * The `{ session, isOpen, onClose }` controlled API is preserved so every\n * existing imperative trigger (command palette, keyboard shortcut, per-row\n * `onShare`) keeps opening this dialog unchanged — they now get the generic\n * surface for free. `session.vibeId` enables the \"Everyone with Vibe\" mode.\n */\nexport const SessionShareDialog: FC<SessionShareDialogProps> = ({ session, isOpen, onClose }) => {\n const controller = useEntityShareController('session', {\n id: session.id,\n vibeId: session.vibeId ?? null,\n });\n\n return (\n <ShareDialog\n resource={{\n type: 'session',\n id: session.id,\n name: session.name,\n vibeId: session.vibeId ?? undefined,\n }}\n controller={controller}\n open={isOpen}\n onOpenChange={(next) => {\n if (!next) onClose();\n }}\n workspaceId={getStoredWorkspaceId() ?? undefined}\n />\n );\n};\n"],"mappings":";;;;;AAgCA,IAAa,KAAmD,EAAE,YAAS,WAAQ,iBAAc;CAC/F,IAAM,IAAa,EAAyB,WAAW;EACrD,IAAI,EAAQ;EACZ,QAAQ,EAAQ,UAAU;EAC3B,CAAC;AAEF,QACE,kBAAC,GAAD;EACE,UAAU;GACR,MAAM;GACN,IAAI,EAAQ;GACZ,MAAM,EAAQ;GACd,QAAQ,EAAQ,UAAU,KAAA;GAC3B;EACW;EACZ,MAAM;EACN,eAAe,MAAS;AACtB,GAAK,KAAM,GAAS;;EAEtB,aAAa,GAAsB,IAAI,KAAA;EACvC,CAAA"}
|