@burdenoff/microfe-assethandler 2026.1110.1 → 2026.1111.2
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/assethandler/components/AttachmentsPanel.d.ts +23 -0
- package/dist/assethandler/components/AttachmentsPanel.js +189 -111
- package/dist/assethandler/components/AttachmentsPanel.js.map +1 -1
- package/dist/assethandler/components/FinanceRegisterExportDialog.d.ts +6 -0
- package/dist/assethandler/components/FinanceRegisterExportDialog.js +189 -0
- package/dist/assethandler/components/FinanceRegisterExportDialog.js.map +1 -0
- package/dist/assethandler/pages/FinanceFinanceHubPage.js +146 -208
- package/dist/assethandler/pages/FinanceFinanceHubPage.js.map +1 -1
- package/dist/assethandler/utils/financeExport.d.ts +32 -0
- package/dist/assethandler/utils/financeExport.js +85 -0
- package/dist/assethandler/utils/financeExport.js.map +1 -0
- package/dist/assethandler/utils/graphqlErrors.d.ts +25 -0
- package/dist/assethandler/utils/graphqlErrors.js +37 -0
- package/dist/assethandler/utils/graphqlErrors.js.map +1 -0
- package/dist/generated/wspace-operations.d.ts +144 -0
- package/dist/generated/wspace-operations.js +301 -0
- package/dist/generated/wspace-operations.js.map +1 -0
- package/dist/test/mocks/fe-libs-ui.d.ts +1 -0
- package/package.json +1 -1
|
@@ -5,6 +5,29 @@
|
|
|
5
5
|
* `initiateUpload` → presigned PUT → `completeUpload` flow, and mints public
|
|
6
6
|
* share links via `createFileShareLink`. All entries are live data.
|
|
7
7
|
*
|
|
8
|
+
* Sharing follows the files service's rules, which depend on visibility:
|
|
9
|
+
*
|
|
10
|
+
* - PRIVATE and TEAM files can only be shared by their uploader or someone
|
|
11
|
+
* holding a SHARE/MANAGE grant or a MANAGER share. For these the panel asks
|
|
12
|
+
* `getUserFilePermissions(fileId).canShare` before minting a link. The check
|
|
13
|
+
* runs lazily (on each desktop click and each time the mobile menu opens), so
|
|
14
|
+
* a long file list never fans out into one permission query per row.
|
|
15
|
+
* - WORKSPACE and PUBLIC files are governed only by the gateway's
|
|
16
|
+
* `@rbac(share, file)` check. `canShare` reflects explicit grants alone for
|
|
17
|
+
* these files, so it is not consulted: the panel calls `createFileShareLink`
|
|
18
|
+
* directly and treats its FORBIDDEN as the denial.
|
|
19
|
+
*
|
|
20
|
+
* The two denials arrive differently and get different copy. The gateway's
|
|
21
|
+
* role check answers HTTP 403 (an Apollo `ServerError`), so the caller is told
|
|
22
|
+
* their workspace role cannot share. The service's per-file rule answers HTTP
|
|
23
|
+
* 200 with a `FORBIDDEN` GraphQL error, so the caller is told who can share
|
|
24
|
+
* the file. A 503 `RBAC_SERVICE_UNAVAILABLE` is an outage, not a denial.
|
|
25
|
+
*
|
|
26
|
+
* `getUserFilePermissions` needs its own `@rbac(read, file-permission)`, which
|
|
27
|
+
* some roles lack. A FORBIDDEN from that query, from either source, means
|
|
28
|
+
* "unknown", never "cannot share": the panel falls through and lets the share
|
|
29
|
+
* mutation decide.
|
|
30
|
+
*
|
|
8
31
|
* `entityType`/`entityId` scope the panel to the record it is mounted on and
|
|
9
32
|
* are used for context labelling; uploaded files land in the workspace file
|
|
10
33
|
* store so they can be shared and reused.
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { notify as e } from "../utils/toast.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import { getForbiddenSource as t, isForbiddenError as n } from "../utils/graphqlErrors.js";
|
|
3
|
+
import { useCallback as r, useMemo as i, useRef as a, useState as o } from "react";
|
|
4
|
+
import { Download as s, File as c, FileArchive as l, FileAudio as u, FileCode2 as d, FileSpreadsheet as f, FileText as p, FileVideo as m, Image as h, Link2 as g, Loader2 as _, Lock as v, MoreHorizontal as y, Paperclip as b, Upload as ee } from "lucide-react";
|
|
5
|
+
import { gql as x } from "@apollo/client";
|
|
6
|
+
import { useApolloClient as te, useMutation as S, useQuery as C } from "@apollo/client/react";
|
|
7
|
+
import { jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
8
|
+
import { Button as ne, Card as E, CardContent as D, CardHeader as O, CardTitle as k, DropdownMenu as A, DropdownMenuContent as j, DropdownMenuItem as M, DropdownMenuTrigger as re, IllustratedEmptyState as ie } from "@burdenoff/fe-libs/ui";
|
|
8
9
|
// src/assethandler/components/AttachmentsPanel.tsx
|
|
9
|
-
var
|
|
10
|
+
var ae = x`
|
|
10
11
|
query AssetHandlerGetFiles($pagination: PaginationInput, $sort: FileSortInput) {
|
|
11
12
|
getFiles(pagination: $pagination, sort: $sort) {
|
|
12
13
|
total
|
|
@@ -19,10 +20,11 @@ var N = v`
|
|
|
19
20
|
size
|
|
20
21
|
downloadUrl
|
|
21
22
|
createdAt
|
|
23
|
+
visibility
|
|
22
24
|
}
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
|
-
`,
|
|
27
|
+
`, oe = x`
|
|
26
28
|
mutation AssetHandlerInitiateUpload($input: InitiateUploadInput!) {
|
|
27
29
|
initiateUpload(input: $input) {
|
|
28
30
|
uploadUrl
|
|
@@ -31,7 +33,7 @@ var N = v`
|
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
}
|
|
34
|
-
`,
|
|
36
|
+
`, se = x`
|
|
35
37
|
mutation AssetHandlerCompleteUpload($input: CompleteUploadInput!) {
|
|
36
38
|
completeUpload(input: $input) {
|
|
37
39
|
fileId
|
|
@@ -41,15 +43,40 @@ var N = v`
|
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
|
-
`,
|
|
46
|
+
`, ce = x`
|
|
45
47
|
mutation AssetHandlerCreateFileShareLink($input: CreateShareGrantLinkInput!) {
|
|
46
48
|
createFileShareLink(input: $input) {
|
|
47
49
|
id
|
|
48
50
|
shareUrl
|
|
49
51
|
}
|
|
50
52
|
}
|
|
53
|
+
`, N = x`
|
|
54
|
+
query AssetHandlerUserFilePermissions($fileId: ID!) {
|
|
55
|
+
getUserFilePermissions(fileId: $fileId) {
|
|
56
|
+
fileId
|
|
57
|
+
canShare
|
|
58
|
+
}
|
|
59
|
+
}
|
|
51
60
|
`;
|
|
52
|
-
function
|
|
61
|
+
function P(e) {
|
|
62
|
+
return e === "PRIVATE" || e === "TEAM";
|
|
63
|
+
}
|
|
64
|
+
var F = "You can't share this file", I = "Only the uploader, or someone with share or manage access to this file, can create a share link. Ask one of them to share it or to grant you access.", L = "Your workspace role doesn't allow sharing files. Ask a workspace admin for share access.", R = "You don't have permission to share this file. Ask the file's uploader or a workspace admin.";
|
|
65
|
+
function z(e) {
|
|
66
|
+
return e === "denied-role" || e === "denied-restricted" || e === "denied-other";
|
|
67
|
+
}
|
|
68
|
+
function B(e) {
|
|
69
|
+
switch (e) {
|
|
70
|
+
case "denied-role": return L;
|
|
71
|
+
case "denied-restricted": return I;
|
|
72
|
+
case "denied-other": return R;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function V(e, n) {
|
|
76
|
+
let r = t(e);
|
|
77
|
+
return r === "gateway" ? "denied-role" : r === "service" ? P(n) ? "denied-restricted" : "denied-other" : null;
|
|
78
|
+
}
|
|
79
|
+
function H(e) {
|
|
53
80
|
if (!e) return "0 B";
|
|
54
81
|
let t = [
|
|
55
82
|
"B",
|
|
@@ -59,11 +86,11 @@ function L(e) {
|
|
|
59
86
|
], n = Math.min(Math.floor(Math.log(e) / Math.log(1024)), t.length - 1);
|
|
60
87
|
return `${(e / 1024 ** n).toFixed(n === 0 ? 0 : 1)} ${t[n]}`;
|
|
61
88
|
}
|
|
62
|
-
function
|
|
89
|
+
function U(e) {
|
|
63
90
|
let t = e.lastIndexOf(".");
|
|
64
91
|
return t >= 0 ? e.slice(t + 1).toLowerCase() : "bin";
|
|
65
92
|
}
|
|
66
|
-
function
|
|
93
|
+
function W(e) {
|
|
67
94
|
let t = new Date(e).getTime();
|
|
68
95
|
if (Number.isNaN(t)) return "";
|
|
69
96
|
let n = Date.now() - t, r = Math.round(n / 1e3);
|
|
@@ -75,8 +102,8 @@ function z(e) {
|
|
|
75
102
|
let o = Math.round(a / 24);
|
|
76
103
|
return o < 30 ? `${o} day${o === 1 ? "" : "s"} ago` : new Date(e).toLocaleDateString();
|
|
77
104
|
}
|
|
78
|
-
function
|
|
79
|
-
let t = (e.mimeType || "").toLowerCase(), n = (e.extension ||
|
|
105
|
+
function G(e) {
|
|
106
|
+
let t = (e.mimeType || "").toLowerCase(), n = (e.extension || U(e.name)).toLowerCase();
|
|
80
107
|
return t.startsWith("image/") || [
|
|
81
108
|
"png",
|
|
82
109
|
"jpg",
|
|
@@ -135,68 +162,68 @@ function B(e) {
|
|
|
135
162
|
"pages"
|
|
136
163
|
].includes(n) ? "doc" : "other";
|
|
137
164
|
}
|
|
138
|
-
var
|
|
165
|
+
var K = {
|
|
139
166
|
image: {
|
|
140
|
-
Icon:
|
|
167
|
+
Icon: h,
|
|
141
168
|
iconClass: "text-status-success-text",
|
|
142
169
|
tileClass: "bg-status-success-bg-subtle"
|
|
143
170
|
},
|
|
144
171
|
pdf: {
|
|
145
|
-
Icon:
|
|
172
|
+
Icon: p,
|
|
146
173
|
iconClass: "text-status-error-text",
|
|
147
174
|
tileClass: "bg-status-error-bg-subtle"
|
|
148
175
|
},
|
|
149
176
|
sheet: {
|
|
150
|
-
Icon:
|
|
177
|
+
Icon: f,
|
|
151
178
|
iconClass: "text-status-success-text",
|
|
152
179
|
tileClass: "bg-status-success-bg-subtle"
|
|
153
180
|
},
|
|
154
181
|
doc: {
|
|
155
|
-
Icon:
|
|
182
|
+
Icon: p,
|
|
156
183
|
iconClass: "text-status-info-text",
|
|
157
184
|
tileClass: "bg-status-info-bg-subtle"
|
|
158
185
|
},
|
|
159
186
|
archive: {
|
|
160
|
-
Icon:
|
|
187
|
+
Icon: l,
|
|
161
188
|
iconClass: "text-status-warning-text",
|
|
162
189
|
tileClass: "bg-status-warning-bg-subtle"
|
|
163
190
|
},
|
|
164
191
|
code: {
|
|
165
|
-
Icon:
|
|
192
|
+
Icon: d,
|
|
166
193
|
iconClass: "text-status-info-text",
|
|
167
194
|
tileClass: "bg-status-info-bg-subtle"
|
|
168
195
|
},
|
|
169
196
|
video: {
|
|
170
|
-
Icon:
|
|
197
|
+
Icon: m,
|
|
171
198
|
iconClass: "text-status-info-text",
|
|
172
199
|
tileClass: "bg-status-info-bg-subtle"
|
|
173
200
|
},
|
|
174
201
|
audio: {
|
|
175
|
-
Icon:
|
|
202
|
+
Icon: u,
|
|
176
203
|
iconClass: "text-status-warning-text",
|
|
177
204
|
tileClass: "bg-status-warning-bg-subtle"
|
|
178
205
|
},
|
|
179
206
|
other: {
|
|
180
|
-
Icon:
|
|
207
|
+
Icon: c,
|
|
181
208
|
iconClass: "text-text-secondary",
|
|
182
209
|
tileClass: "bg-bg-sunken"
|
|
183
210
|
}
|
|
184
211
|
};
|
|
185
|
-
function
|
|
186
|
-
let t =
|
|
187
|
-
return t === "image" && e.downloadUrl ? /* @__PURE__ */
|
|
212
|
+
function le({ file: e }) {
|
|
213
|
+
let t = G(e), { Icon: n, iconClass: r, tileClass: i } = K[t];
|
|
214
|
+
return t === "image" && e.downloadUrl ? /* @__PURE__ */ w("img", {
|
|
188
215
|
src: e.downloadUrl,
|
|
189
216
|
alt: "",
|
|
190
217
|
loading: "lazy",
|
|
191
218
|
className: "h-10 w-10 shrink-0 rounded-lg border border-border-subtle object-cover"
|
|
192
|
-
}) : /* @__PURE__ */
|
|
219
|
+
}) : /* @__PURE__ */ w("span", {
|
|
193
220
|
className: `flex h-10 w-10 shrink-0 items-center justify-center rounded-lg ${i}`,
|
|
194
221
|
"aria-hidden": "true",
|
|
195
|
-
children: /* @__PURE__ */
|
|
222
|
+
children: /* @__PURE__ */ w(n, { className: `h-5 w-5 ${r}` })
|
|
196
223
|
});
|
|
197
224
|
}
|
|
198
|
-
function
|
|
199
|
-
let
|
|
225
|
+
function q({ entityType: t, entityId: c }) {
|
|
226
|
+
let l = a(null), [u, d] = o(!1), [f, p] = o(null), [m, h] = o({}), x = te(), { data: I, loading: L, refetch: R } = C(ae, {
|
|
200
227
|
variables: {
|
|
201
228
|
pagination: {
|
|
202
229
|
limit: 25,
|
|
@@ -209,14 +236,14 @@ function U({ entityType: a, entityId: o }) {
|
|
|
209
236
|
},
|
|
210
237
|
fetchPolicy: "cache-and-network",
|
|
211
238
|
errorPolicy: "all"
|
|
212
|
-
}), [
|
|
239
|
+
}), [G] = S(oe), [K] = S(se), [q] = S(ce), J = i(() => I?.getFiles.files ?? [], [I]), ue = async (t) => {
|
|
213
240
|
let n = t.target.files?.[0];
|
|
214
241
|
if (t.target.value = "", n) {
|
|
215
|
-
|
|
242
|
+
d(!0);
|
|
216
243
|
try {
|
|
217
|
-
let t = await
|
|
244
|
+
let t = await G({ variables: { input: {
|
|
218
245
|
fileName: n.name,
|
|
219
|
-
extension:
|
|
246
|
+
extension: U(n.name),
|
|
220
247
|
fileSize: n.size,
|
|
221
248
|
mimeType: n.type || "application/octet-stream",
|
|
222
249
|
visibility: "WORKSPACE"
|
|
@@ -228,150 +255,201 @@ function U({ entityType: a, entityId: o }) {
|
|
|
228
255
|
headers: { "Content-Type": n.type || "application/octet-stream" }
|
|
229
256
|
});
|
|
230
257
|
if (!a.ok) throw Error(`Storage rejected the upload (HTTP ${a.status}).`);
|
|
231
|
-
await
|
|
258
|
+
await K({ variables: { input: {
|
|
232
259
|
sessionId: i,
|
|
233
260
|
fileSize: n.size
|
|
234
|
-
} } }), e.success("File uploaded", `${n.name} is now available on this record.`), await
|
|
261
|
+
} } }), e.success("File uploaded", `${n.name} is now available on this record.`), await R();
|
|
235
262
|
} catch (t) {
|
|
236
263
|
e.error("Upload failed", t instanceof Error ? t.message : "The file could not be uploaded.");
|
|
237
264
|
} finally {
|
|
238
|
-
|
|
265
|
+
d(!1);
|
|
239
266
|
}
|
|
240
267
|
}
|
|
241
|
-
},
|
|
242
|
-
|
|
268
|
+
}, Y = r((e, t) => {
|
|
269
|
+
h((n) => {
|
|
270
|
+
let r = { ...n };
|
|
271
|
+
return t ? r[e] = t : delete r[e], r;
|
|
272
|
+
});
|
|
273
|
+
}, []), X = r(async (e) => {
|
|
274
|
+
Y(e, "checking");
|
|
275
|
+
try {
|
|
276
|
+
let t = (await x.query({
|
|
277
|
+
query: N,
|
|
278
|
+
variables: { fileId: e },
|
|
279
|
+
fetchPolicy: "network-only"
|
|
280
|
+
})).data?.getUserFilePermissions.canShare === !0 ? "allowed" : "denied-restricted";
|
|
281
|
+
return Y(e, t), t;
|
|
282
|
+
} catch (t) {
|
|
283
|
+
return n(t) ? (Y(e, "unverified"), "unverified") : (Y(e, null), "failed");
|
|
284
|
+
}
|
|
285
|
+
}, [x, Y]), de = (e, t) => {
|
|
286
|
+
t && (P(e.visibility) ? m[e.id] !== "checking" && X(e.id) : z(m[e.id]) && Y(e.id, null));
|
|
287
|
+
}, Z = async (t, { recheck: n }) => {
|
|
288
|
+
let r = t.id;
|
|
289
|
+
p(r);
|
|
243
290
|
try {
|
|
244
|
-
|
|
245
|
-
|
|
291
|
+
if (P(t.visibility)) {
|
|
292
|
+
let t = m[r], i = !n && (t === "allowed" || t === "unverified") ? t : await X(r);
|
|
293
|
+
if (i === "failed") throw Error("Your share access could not be checked. Please try again.");
|
|
294
|
+
if (i === "denied-restricted") {
|
|
295
|
+
e.error(F, B(i));
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
let i = (await q({ variables: { input: {
|
|
300
|
+
resourceId: r,
|
|
246
301
|
role: "VIEWER"
|
|
247
302
|
} } })).data?.createFileShareLink.shareUrl;
|
|
248
|
-
if (!
|
|
249
|
-
navigator.clipboard?.writeText ? (await navigator.clipboard.writeText(
|
|
250
|
-
} catch (
|
|
251
|
-
|
|
303
|
+
if (!i) throw Error("No share link was returned.");
|
|
304
|
+
Y(r, "allowed"), navigator.clipboard?.writeText ? (await navigator.clipboard.writeText(i), e.success("Share link copied", "A view-only link is on your clipboard.")) : e.info("Share link ready", i);
|
|
305
|
+
} catch (n) {
|
|
306
|
+
let i = V(n, t.visibility);
|
|
307
|
+
if (i) {
|
|
308
|
+
Y(r, i), e.error(F, B(i));
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
e.error("Could not create share link", n instanceof Error ? n.message : "Please try again.");
|
|
252
312
|
} finally {
|
|
253
|
-
|
|
313
|
+
p(null);
|
|
254
314
|
}
|
|
255
|
-
},
|
|
256
|
-
return /* @__PURE__ */
|
|
315
|
+
}, Q = I?.getFiles.total ?? 0, $ = J.length > 0;
|
|
316
|
+
return /* @__PURE__ */ T(E, { children: [/* @__PURE__ */ w(O, {
|
|
257
317
|
className: "flex flex-row items-center justify-between gap-2 space-y-0",
|
|
258
|
-
children: /* @__PURE__ */
|
|
318
|
+
children: /* @__PURE__ */ T(k, {
|
|
259
319
|
className: "flex items-center gap-2 text-base",
|
|
260
320
|
children: [
|
|
261
|
-
/* @__PURE__ */
|
|
321
|
+
/* @__PURE__ */ w(b, { className: "h-4 w-4" }),
|
|
262
322
|
"Attachments",
|
|
263
|
-
|
|
323
|
+
Q ? /* @__PURE__ */ T("span", {
|
|
264
324
|
className: "text-sm font-normal text-text-secondary",
|
|
265
325
|
children: [
|
|
266
|
-
|
|
326
|
+
Q,
|
|
267
327
|
" file",
|
|
268
|
-
|
|
328
|
+
Q === 1 ? "" : "s"
|
|
269
329
|
]
|
|
270
330
|
}) : null
|
|
271
331
|
]
|
|
272
332
|
})
|
|
273
|
-
}), /* @__PURE__ */
|
|
333
|
+
}), /* @__PURE__ */ T(D, {
|
|
274
334
|
className: "space-y-3",
|
|
275
335
|
children: [
|
|
276
|
-
/* @__PURE__ */
|
|
277
|
-
ref:
|
|
336
|
+
/* @__PURE__ */ w("input", {
|
|
337
|
+
ref: l,
|
|
278
338
|
type: "file",
|
|
279
339
|
className: "hidden",
|
|
280
|
-
onChange: (e) => void
|
|
281
|
-
"aria-label": `Upload a file for ${
|
|
340
|
+
onChange: (e) => void ue(e),
|
|
341
|
+
"aria-label": `Upload a file for ${t} ${c}`
|
|
282
342
|
}),
|
|
283
|
-
|
|
343
|
+
L && !$ ? /* @__PURE__ */ w("div", {
|
|
284
344
|
className: "space-y-2",
|
|
285
|
-
children: Array.from({ length: 3 }).map((e, t) => /* @__PURE__ */
|
|
286
|
-
}) :
|
|
345
|
+
children: Array.from({ length: 3 }).map((e, t) => /* @__PURE__ */ w("div", { className: "h-14 rounded-lg bg-bg-sunken motion-safe:animate-vc-shimmer" }, t))
|
|
346
|
+
}) : $ ? /* @__PURE__ */ w("ul", {
|
|
287
347
|
className: "space-y-1.5",
|
|
288
|
-
children:
|
|
289
|
-
let t =
|
|
290
|
-
return /* @__PURE__ */
|
|
348
|
+
children: J.map((e) => {
|
|
349
|
+
let t = f === e.id, n = m[e.id], r = n === "checking", i = z(n) ? n : null, a = i !== null;
|
|
350
|
+
return /* @__PURE__ */ T("li", {
|
|
291
351
|
className: "flex items-center gap-3 rounded-lg border border-border-subtle bg-bg-surface p-2.5",
|
|
292
352
|
children: [
|
|
293
|
-
/* @__PURE__ */
|
|
294
|
-
/* @__PURE__ */
|
|
353
|
+
/* @__PURE__ */ w(le, { file: e }),
|
|
354
|
+
/* @__PURE__ */ T("div", {
|
|
295
355
|
className: "min-w-0 flex-1",
|
|
296
|
-
children: [/* @__PURE__ */
|
|
356
|
+
children: [/* @__PURE__ */ w("p", {
|
|
297
357
|
className: "truncate text-sm font-medium",
|
|
298
358
|
title: e.name,
|
|
299
359
|
children: e.name
|
|
300
|
-
}), /* @__PURE__ */
|
|
360
|
+
}), /* @__PURE__ */ T("p", {
|
|
301
361
|
className: "truncate text-xs text-text-secondary",
|
|
302
362
|
children: [
|
|
303
|
-
|
|
363
|
+
H(Number(e.size)),
|
|
304
364
|
" · ",
|
|
305
|
-
|
|
365
|
+
W(e.createdAt)
|
|
306
366
|
]
|
|
307
367
|
})]
|
|
308
368
|
}),
|
|
309
|
-
/* @__PURE__ */
|
|
369
|
+
/* @__PURE__ */ T("div", {
|
|
310
370
|
className: "hidden items-center gap-1 sm:flex",
|
|
311
|
-
children: [e.downloadUrl ? /* @__PURE__ */
|
|
371
|
+
children: [e.downloadUrl ? /* @__PURE__ */ w("a", {
|
|
312
372
|
href: e.downloadUrl,
|
|
313
373
|
target: "_blank",
|
|
314
374
|
rel: "noreferrer",
|
|
315
375
|
className: "rounded-md p-1.5 text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary",
|
|
316
376
|
"aria-label": `Download ${e.name}`,
|
|
317
377
|
title: "Download",
|
|
318
|
-
children: /* @__PURE__ */
|
|
319
|
-
}) : null, /* @__PURE__ */
|
|
378
|
+
children: /* @__PURE__ */ w(s, { className: "h-4 w-4" })
|
|
379
|
+
}) : null, /* @__PURE__ */ w("button", {
|
|
320
380
|
type: "button",
|
|
321
|
-
disabled: t,
|
|
322
|
-
|
|
323
|
-
|
|
381
|
+
disabled: t || r,
|
|
382
|
+
"aria-disabled": a ? !0 : void 0,
|
|
383
|
+
"data-share-state": a ? "denied" : void 0,
|
|
384
|
+
onClick: () => void Z(e, { recheck: !0 }),
|
|
385
|
+
className: `rounded-md p-1.5 transition-colors disabled:opacity-60 ${a ? "cursor-not-allowed text-text-tertiary opacity-60" : "text-text-secondary hover:bg-bg-sunken hover:text-text-primary"}`,
|
|
324
386
|
"aria-label": `Copy share link for ${e.name}`,
|
|
325
|
-
title: "Copy share link",
|
|
326
|
-
children: t ? /* @__PURE__ */
|
|
387
|
+
title: i ? `${F}. ${B(i)}` : "Copy share link",
|
|
388
|
+
children: t || r ? /* @__PURE__ */ w(_, { className: "h-4 w-4 animate-spin" }) : a ? /* @__PURE__ */ w(v, {
|
|
389
|
+
className: "h-4 w-4",
|
|
390
|
+
"aria-hidden": "true"
|
|
391
|
+
}) : /* @__PURE__ */ w(g, { className: "h-4 w-4" })
|
|
327
392
|
})]
|
|
328
393
|
}),
|
|
329
|
-
/* @__PURE__ */
|
|
394
|
+
/* @__PURE__ */ w("div", {
|
|
330
395
|
className: "sm:hidden",
|
|
331
|
-
children: /* @__PURE__ */
|
|
332
|
-
|
|
333
|
-
children: /* @__PURE__ */
|
|
334
|
-
type: "button",
|
|
335
|
-
className: "rounded-md p-1.5 text-text-secondary hover:bg-bg-sunken hover:text-text-primary",
|
|
336
|
-
"aria-label": `Actions for ${e.name}`,
|
|
337
|
-
children: /* @__PURE__ */ x(h, { className: "h-4 w-4" })
|
|
338
|
-
})
|
|
339
|
-
}), /* @__PURE__ */ S(k, {
|
|
340
|
-
align: "end",
|
|
341
|
-
children: [e.downloadUrl ? /* @__PURE__ */ x(A, {
|
|
396
|
+
children: /* @__PURE__ */ T(A, {
|
|
397
|
+
onOpenChange: (t) => de(e, t),
|
|
398
|
+
children: [/* @__PURE__ */ w(re, {
|
|
342
399
|
asChild: !0,
|
|
343
|
-
children: /* @__PURE__ */
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
children:
|
|
400
|
+
children: /* @__PURE__ */ w("button", {
|
|
401
|
+
type: "button",
|
|
402
|
+
className: "rounded-md p-1.5 text-text-secondary hover:bg-bg-sunken hover:text-text-primary",
|
|
403
|
+
"aria-label": `Actions for ${e.name}`,
|
|
404
|
+
children: /* @__PURE__ */ w(y, { className: "h-4 w-4" })
|
|
348
405
|
})
|
|
349
|
-
})
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
406
|
+
}), /* @__PURE__ */ T(j, {
|
|
407
|
+
align: "end",
|
|
408
|
+
children: [
|
|
409
|
+
e.downloadUrl ? /* @__PURE__ */ w(M, {
|
|
410
|
+
asChild: !0,
|
|
411
|
+
children: /* @__PURE__ */ T("a", {
|
|
412
|
+
href: e.downloadUrl,
|
|
413
|
+
target: "_blank",
|
|
414
|
+
rel: "noreferrer",
|
|
415
|
+
children: [/* @__PURE__ */ w(s, { className: "mr-2 h-4 w-4" }), "Download"]
|
|
416
|
+
})
|
|
417
|
+
}) : null,
|
|
418
|
+
/* @__PURE__ */ T(M, {
|
|
419
|
+
disabled: t || r || a,
|
|
420
|
+
onSelect: (t) => {
|
|
421
|
+
t.preventDefault(), Z(e, { recheck: !1 });
|
|
422
|
+
},
|
|
423
|
+
children: [r ? /* @__PURE__ */ w(_, { className: "mr-2 h-4 w-4 animate-spin" }) : a ? /* @__PURE__ */ w(v, {
|
|
424
|
+
className: "mr-2 h-4 w-4",
|
|
425
|
+
"aria-hidden": "true"
|
|
426
|
+
}) : /* @__PURE__ */ w(g, { className: "mr-2 h-4 w-4" }), r ? "Checking share access…" : a ? "No share access" : "Copy share link"]
|
|
427
|
+
}),
|
|
428
|
+
i ? /* @__PURE__ */ w("p", {
|
|
429
|
+
className: "max-w-56 px-2 py-1.5 text-xs text-text-secondary",
|
|
430
|
+
children: B(i)
|
|
431
|
+
}) : null
|
|
432
|
+
]
|
|
355
433
|
})]
|
|
356
|
-
})
|
|
434
|
+
})
|
|
357
435
|
})
|
|
358
436
|
]
|
|
359
437
|
}, e.id);
|
|
360
438
|
})
|
|
361
|
-
}) : /* @__PURE__ */
|
|
439
|
+
}) : /* @__PURE__ */ w(ie, {
|
|
362
440
|
illustration: "empty-data",
|
|
363
441
|
title: "No files yet",
|
|
364
442
|
description: "Upload photos, receipts, warranties or documents to keep them with this record."
|
|
365
443
|
}),
|
|
366
|
-
/* @__PURE__ */
|
|
444
|
+
/* @__PURE__ */ T(ne, {
|
|
367
445
|
className: "w-full",
|
|
368
|
-
disabled:
|
|
369
|
-
onClick: () =>
|
|
370
|
-
children: [
|
|
446
|
+
disabled: u,
|
|
447
|
+
onClick: () => l.current?.click(),
|
|
448
|
+
children: [u ? /* @__PURE__ */ w(_, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ w(ee, { className: "mr-2 h-4 w-4" }), u ? "Uploading…" : "Upload files"]
|
|
371
449
|
})
|
|
372
450
|
]
|
|
373
451
|
})] });
|
|
374
452
|
}
|
|
375
|
-
export {
|
|
453
|
+
export { q as AttachmentsPanel };
|
|
376
454
|
|
|
377
455
|
//# sourceMappingURL=AttachmentsPanel.js.map
|