@anchrd/intel-ui 0.40.0 → 0.42.0
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/package.json +8 -1
- package/src/app/app-tree/app-tree.tsx +21 -0
- package/src/attachment-viewer/attachment-viewer.tsx +305 -0
- package/src/board/board-assignee/board-assignee.tsx +45 -0
- package/src/board/board-chip/board-chip.tsx +31 -0
- package/src/board/board-crumbs/board-crumbs.ts +56 -0
- package/src/board/board-crumbs/board-crumbs.tsx +108 -0
- package/src/board/board-kanban/board-kanban.tsx +43 -8
- package/src/board/board-open-task/board-open-task.ts +32 -0
- package/src/board/board-panel/board-panel.tsx +17 -37
- package/src/board/board-status/board-status.tsx +60 -0
- package/src/board/board-table/board-table.tsx +207 -101
- package/src/board/board-task/board-task.tsx +144 -195
- package/src/board/board-title-row/board-title-row.tsx +68 -0
- package/src/file-preview/file-preview-view.tsx +342 -0
- package/src/file-preview/file-preview.tsx +28 -0
- package/src/file-preview/pdf-file-preview.tsx +5 -0
- package/src/file-preview/presentation-file-preview.tsx +21 -0
- package/src/file-preview/spreadsheet-file-preview.tsx +5 -0
- package/src/file-preview/word-file-preview.tsx +5 -0
- package/src/i18n/de.json +62 -6
- package/src/i18n/en.json +62 -6
- package/src/i18n/es.json +62 -6
- package/src/nodes/nodes.tsx +26 -52
- package/src/resource-menu/resource-menu.tsx +18 -12
- package/src/title-row/title-row.tsx +33 -6
- package/vite.config.ts +111 -3
package/src/i18n/es.json
CHANGED
|
@@ -31,11 +31,20 @@
|
|
|
31
31
|
"archive.title": "Archivo",
|
|
32
32
|
"auth.signOut": "Cerrar sesión",
|
|
33
33
|
"auth.signOutFailed": "El cierre de sesión ha fallado. Comprueba tu conexión e inténtalo de nuevo.",
|
|
34
|
+
"board.add": "Añadir algo",
|
|
35
|
+
"board.add.due": "Vencimiento",
|
|
36
|
+
"board.add.label": "Etiqueta",
|
|
37
|
+
"board.add.start": "Inicio",
|
|
34
38
|
"board.addCard": "+ Tarea",
|
|
35
39
|
"board.addCardIn": "Añadir una tarea a {column}",
|
|
36
40
|
"board.addLabel": "Añadir etiqueta",
|
|
37
41
|
"board.addLink": "Vínculo",
|
|
42
|
+
"board.backTo": "Volver a {board}",
|
|
38
43
|
"board.cardLabel": "Abrir {title}, en {column}. Alt y una flecha la mueve.",
|
|
44
|
+
"board.clearAssignee": "Quitar la responsabilidad de {name}",
|
|
45
|
+
"board.clearDependsOn": "dejar de esperarlo",
|
|
46
|
+
"board.clearDue": "quitar",
|
|
47
|
+
"board.clearStart": "quitar",
|
|
39
48
|
"board.column.archive": "Archivo",
|
|
40
49
|
"board.column.assignee": "Asignada a",
|
|
41
50
|
"board.column.default.backlog": "Backlog",
|
|
@@ -45,10 +54,12 @@
|
|
|
45
54
|
"board.column.dependsOn": "Espera a",
|
|
46
55
|
"board.column.due": "Vence",
|
|
47
56
|
"board.column.labels": "Etiquetas",
|
|
57
|
+
"board.column.start": "Inicio",
|
|
48
58
|
"board.column.status": "Columna",
|
|
49
59
|
"board.column.title": "Título",
|
|
50
|
-
"board.columnEmpty": "Aquí todavía no hay nada.",
|
|
51
60
|
"board.createFailed": "No se pudo crear la tarea.",
|
|
61
|
+
"board.crumbs": "Dónde está esta tarjeta",
|
|
62
|
+
"board.crumbsFolded": "Mostrar los niveles intermedios",
|
|
52
63
|
"board.drag.lifted": "{card} recogida",
|
|
53
64
|
"board.drag.moved": "{card} movida a {column}",
|
|
54
65
|
"board.drag.putBack": "{card} devuelta",
|
|
@@ -65,9 +76,9 @@
|
|
|
65
76
|
"board.link.outside": "Fuera de este tablero",
|
|
66
77
|
"board.link.subtask": "Subtarea",
|
|
67
78
|
"board.links": "Vinculado",
|
|
68
|
-
"board.moveTo": "
|
|
79
|
+
"board.moveTo": "moverla a otra columna",
|
|
69
80
|
"board.progress": "{done} de {total} hechas",
|
|
70
|
-
"board.removeLabel": "
|
|
81
|
+
"board.removeLabel": "quitar esta etiqueta",
|
|
71
82
|
"board.settings.addColumn": "+ Columna",
|
|
72
83
|
"board.settings.columnName": "Nombre de la columna {column}",
|
|
73
84
|
"board.settings.description": "Columnas y lo que muestra el tablero.",
|
|
@@ -82,6 +93,10 @@
|
|
|
82
93
|
"board.settings.showArchive": "Mostrar la columna de archivo",
|
|
83
94
|
"board.settings.showArchiveHint": "Está en todos los tableros. Oculta, sus tarjetas desaparecen de todas las vistas.",
|
|
84
95
|
"board.settings.title": "Ajustes del tablero",
|
|
96
|
+
"board.sort.asc": "{column}, A a Z",
|
|
97
|
+
"board.sort.desc": "{column}, Z a A",
|
|
98
|
+
"board.sort.none": "Sin orden",
|
|
99
|
+
"board.sortBy": "Ordenar",
|
|
85
100
|
"board.stripes.root": "Nivel {level}, tiene subtareas",
|
|
86
101
|
"board.stripes.under": "Nivel {level} · superior en {column}",
|
|
87
102
|
"board.table.collapse": "Ocultar lo que hay bajo {row}",
|
|
@@ -213,14 +228,55 @@
|
|
|
213
228
|
"flows.validate": "Comprobar si se ejecutaría",
|
|
214
229
|
"flows.validateReady": "Este flujo empezaría ahora mismo.",
|
|
215
230
|
"flows.validateWhen": "Comprobado {when}. El acceso a las herramientas se pide cada vez con tu propio token, así que esta respuesta es una instantánea.",
|
|
231
|
+
"attachment.details.checksum": "Suma de comprobación",
|
|
232
|
+
"attachment.details.dimensions": "Dimensiones",
|
|
233
|
+
"attachment.details.format": "Formato",
|
|
234
|
+
"attachment.details.mimeType": "Tipo MIME",
|
|
235
|
+
"attachment.details.name": "Nombre",
|
|
236
|
+
"attachment.details.pages": "Páginas",
|
|
237
|
+
"attachment.details.private": "Privado",
|
|
238
|
+
"attachment.details.size": "Tamaño",
|
|
239
|
+
"attachment.details.sections": "Secciones",
|
|
240
|
+
"attachment.details.slides": "Diapositivas",
|
|
241
|
+
"attachment.details.storage": "Almacenamiento",
|
|
242
|
+
"attachment.details.technical": "Técnico",
|
|
243
|
+
"attachment.details.title": "Detalles del archivo",
|
|
244
|
+
"attachment.details.type": "Tipo",
|
|
245
|
+
"attachment.details.uploaded": "Subido",
|
|
246
|
+
"attachment.details.uploadedBy": "Subido por",
|
|
247
|
+
"attachment.details.version": "Versión",
|
|
248
|
+
"attachment.details.worksheets": "Hojas",
|
|
249
|
+
"attachment.kind.image": "Imagen",
|
|
250
|
+
"attachment.kind.pdf": "Documento PDF",
|
|
251
|
+
"attachment.kind.presentation": "Presentación",
|
|
252
|
+
"attachment.kind.spreadsheet": "Hoja de cálculo",
|
|
253
|
+
"attachment.kind.unsupported": "Archivo",
|
|
254
|
+
"attachment.kind.word": "Documento de Word",
|
|
255
|
+
"attachment.detailsHide": "Ocultar detalles del archivo",
|
|
256
|
+
"attachment.detailsShow": "Mostrar detalles del archivo",
|
|
257
|
+
"attachment.empty": "Todavía no se ha subido ningún archivo.",
|
|
258
|
+
"attachment.loadFailed": "No se pudo cargar el archivo. Aún puedes exportar el original desde el menú.",
|
|
259
|
+
"attachment.unsupported": "No se puede previsualizar este tipo de archivo. Aún puedes exportar el original desde el menú.",
|
|
260
|
+
"attachment.viewer.controls": "Controles del archivo",
|
|
261
|
+
"attachment.viewer.navigation": "Mostrar navegación de páginas",
|
|
262
|
+
"attachment.viewer.nextPage": "Página siguiente",
|
|
263
|
+
"attachment.viewer.nextResult": "Siguiente resultado de búsqueda",
|
|
264
|
+
"attachment.viewer.previousPage": "Página anterior",
|
|
265
|
+
"attachment.viewer.previousResult": "Resultado de búsqueda anterior",
|
|
266
|
+
"attachment.viewer.resetZoom": "Restablecer zoom",
|
|
267
|
+
"attachment.viewer.rotateLeft": "Girar a la izquierda",
|
|
268
|
+
"attachment.viewer.rotateRight": "Girar a la derecha",
|
|
269
|
+
"attachment.viewer.search": "Buscar en el documento",
|
|
270
|
+
"attachment.viewer.searchNoResults": "Sin resultados",
|
|
271
|
+
"attachment.viewer.searchPlaceholder": "Buscar en el documento",
|
|
272
|
+
"attachment.viewer.searchResults": "Resultado {current} de {total}",
|
|
273
|
+
"attachment.viewer.zoomIn": "Ampliar",
|
|
274
|
+
"attachment.viewer.zoomOut": "Reducir",
|
|
216
275
|
"nav.primary": "Navegación principal",
|
|
217
276
|
"nav.tools": "Herramientas",
|
|
218
277
|
"node.access": "Acceso",
|
|
219
278
|
"node.accessDetails": "Mostrar detalles de acceso ({count})",
|
|
220
|
-
"node.attachmentHelp": "El archivo canónico se guarda en privado en Intel. Su proyección legible por la IA se indexa por separado.",
|
|
221
279
|
"node.changed": "Cambiado",
|
|
222
|
-
"node.download": "Descargar el archivo",
|
|
223
|
-
"node.downloadFailed": "El adjunto no se ha podido descargar. Comprueba tu acceso e inténtalo de nuevo.",
|
|
224
280
|
"node.email": "Dirección de correo",
|
|
225
281
|
"node.empty": "Todavía no se ha añadido nada.",
|
|
226
282
|
"node.folderEmpty": "En esta carpeta todavía no hay nada. Crea algo con el más de la barra lateral.",
|
package/src/nodes/nodes.tsx
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
1
|
+
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
3
2
|
import { useNavigate, useRouterState } from "@tanstack/react-router";
|
|
4
|
-
import { Download, Paperclip } from "lucide-react";
|
|
5
3
|
import { lazy, Suspense } from "react";
|
|
6
4
|
import { treeLevelKey } from "@/app/tree-move/tree-move.tsx";
|
|
7
5
|
import { ViewToggle } from "@/app/view-toggle/view-toggle.tsx";
|
|
8
6
|
import { BoardPanel } from "@/board/board-panel/board-panel.tsx";
|
|
7
|
+
import { BoardTitleRow } from "@/board/board-title-row/board-title-row.tsx";
|
|
9
8
|
import { RefusalNotice } from "@/data/request-refusal/refusal-notice.tsx";
|
|
10
9
|
import { refusalOf } from "@/data/request-refusal/request-refusal.ts";
|
|
11
10
|
import { FolderContents } from "@/folder-contents/folder-contents.tsx";
|
|
@@ -19,6 +18,9 @@ import { TitleRow, TitleRowFrame } from "@/title-row/title-row.tsx";
|
|
|
19
18
|
const NodeEditor = lazy(async () => ({
|
|
20
19
|
default: (await import("@/node-editor/node-editor.tsx")).NodeEditor,
|
|
21
20
|
}));
|
|
21
|
+
const AttachmentViewer = lazy(async () => ({
|
|
22
|
+
default: (await import("@/attachment-viewer/attachment-viewer.tsx")).AttachmentViewer,
|
|
23
|
+
}));
|
|
22
24
|
|
|
23
25
|
export function Nodes() {
|
|
24
26
|
const { data } = useIntelRouterContext();
|
|
@@ -138,13 +140,20 @@ export function Nodes() {
|
|
|
138
140
|
the search — where what applies everywhere stands. But a graph view does not apply
|
|
139
141
|
everywhere, it is a view onto THIS item. It is only drawn where there is a graph: on
|
|
140
142
|
a document it pointed at nothing. */}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
143
|
+
{/* ⚠️ A board brings its OWN title row, because an open card changes what the line
|
|
144
|
+
identifies: not the board any more, but where the card sits on it. It is the same
|
|
145
|
+
`TitleRow` underneath, only with a path in place of the name (#692). */}
|
|
146
|
+
{selected.kind === "board" ? (
|
|
147
|
+
<BoardTitleRow node={selected} />
|
|
148
|
+
) : (
|
|
149
|
+
<TitleRow
|
|
150
|
+
title={selected.title}
|
|
151
|
+
description={selected.description}
|
|
152
|
+
target={{ type: "node", node: selected }}
|
|
153
|
+
>
|
|
154
|
+
{graphable && <ViewToggle />}
|
|
155
|
+
</TitleRow>
|
|
156
|
+
)}
|
|
148
157
|
{graphable && selection.graph ? (
|
|
149
158
|
<GraphPane
|
|
150
159
|
query={relations}
|
|
@@ -158,7 +167,13 @@ export function Nodes() {
|
|
|
158
167
|
) : selected.kind === "folder" ? (
|
|
159
168
|
<FolderContents folderId={selected.id} />
|
|
160
169
|
) : selected.kind === "attachment" ? (
|
|
161
|
-
<
|
|
170
|
+
<Suspense
|
|
171
|
+
fallback={
|
|
172
|
+
<p className="p-6 text-sm text-muted-foreground">{i18n.t("common.loading")}</p>
|
|
173
|
+
}
|
|
174
|
+
>
|
|
175
|
+
<AttachmentViewer document={document.data} />
|
|
176
|
+
</Suspense>
|
|
162
177
|
) : selected.kind === "table" ? (
|
|
163
178
|
<NodeTablePanel node={selected} />
|
|
164
179
|
) : selected.kind === "board" ? (
|
|
@@ -186,44 +201,3 @@ export function Nodes() {
|
|
|
186
201
|
</TitleRowFrame>
|
|
187
202
|
);
|
|
188
203
|
}
|
|
189
|
-
|
|
190
|
-
function AttachmentPanel({ node }: { node: Node }) {
|
|
191
|
-
const { data } = useIntelRouterContext();
|
|
192
|
-
const i18n = useI18n();
|
|
193
|
-
const download = useMutation({
|
|
194
|
-
mutationFn: () => data.getNodeAttachment(node.id),
|
|
195
|
-
onSuccess: (blob) => {
|
|
196
|
-
const url = URL.createObjectURL(blob);
|
|
197
|
-
const anchor = document.createElement("a");
|
|
198
|
-
anchor.href = url;
|
|
199
|
-
anchor.download = node.title;
|
|
200
|
-
document.body.append(anchor);
|
|
201
|
-
anchor.click();
|
|
202
|
-
anchor.remove();
|
|
203
|
-
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
204
|
-
},
|
|
205
|
-
});
|
|
206
|
-
return (
|
|
207
|
-
<div className="grid flex-1 place-items-center p-8">
|
|
208
|
-
<div className="max-w-md rounded-xl border bg-background p-8 text-center shadow-sm">
|
|
209
|
-
<Paperclip aria-hidden="true" className="mx-auto size-10 text-primary" />
|
|
210
|
-
<h3 className="mt-4 font-semibold">{node.title}</h3>
|
|
211
|
-
<p className="mt-2 text-sm text-muted-foreground">{i18n.t("node.attachmentHelp")}</p>
|
|
212
|
-
<button
|
|
213
|
-
type="button"
|
|
214
|
-
onClick={() => download.mutate()}
|
|
215
|
-
disabled={download.isPending}
|
|
216
|
-
className="mt-5 inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-50"
|
|
217
|
-
>
|
|
218
|
-
<Download aria-hidden="true" className="size-4" />
|
|
219
|
-
{download.isPending ? i18n.t("common.loading") : i18n.t("node.download")}
|
|
220
|
-
</button>
|
|
221
|
-
{download.isError ? (
|
|
222
|
-
<p role="alert" className="mt-4 text-sm text-destructive">
|
|
223
|
-
{i18n.t("node.downloadFailed")}
|
|
224
|
-
</p>
|
|
225
|
-
) : null}
|
|
226
|
-
</div>
|
|
227
|
-
</div>
|
|
228
|
-
);
|
|
229
|
-
}
|
|
@@ -239,19 +239,25 @@ export function ResourceMenu({
|
|
|
239
239
|
},
|
|
240
240
|
});
|
|
241
241
|
|
|
242
|
-
//
|
|
243
|
-
//
|
|
244
|
-
//
|
|
245
|
-
const
|
|
246
|
-
mutationFn: async () =>
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
242
|
+
// An attachment already is one original file. Every structured Intel resource needs the bundle
|
|
243
|
+
// that carries its type and relationships, but wrapping uploaded bytes in a zip would make the
|
|
244
|
+
// one Export entry give a person something other than what they put in (#699).
|
|
245
|
+
const exportResource = useMutation({
|
|
246
|
+
mutationFn: async () => {
|
|
247
|
+
if (node?.kind === "attachment") {
|
|
248
|
+
return { blob: await data.getNodeAttachment(node.id), filename: title };
|
|
249
|
+
}
|
|
250
|
+
const blob =
|
|
251
|
+
target.type === "flow"
|
|
252
|
+
? await data.exportFlowBundle(target.flow.id)
|
|
253
|
+
: await data.exportNodeBundle(target.node.id);
|
|
254
|
+
return { blob, filename: `${title}.zip` };
|
|
255
|
+
},
|
|
256
|
+
onSuccess: ({ blob, filename }) => {
|
|
251
257
|
const url = URL.createObjectURL(blob);
|
|
252
258
|
const anchor = document.createElement("a");
|
|
253
259
|
anchor.href = url;
|
|
254
|
-
anchor.download =
|
|
260
|
+
anchor.download = filename;
|
|
255
261
|
document.body.append(anchor);
|
|
256
262
|
anchor.click();
|
|
257
263
|
anchor.remove();
|
|
@@ -326,7 +332,7 @@ export function ResourceMenu({
|
|
|
326
332
|
`excluded` in the zip's `manifest.json` and `BundleImportResult.excluded` after an
|
|
327
333
|
import, both of which are read only once the zip exists. That is a deliberate trade,
|
|
328
334
|
recorded in ADR-0006 and in #636, and NOT a leftover to be restored. */}
|
|
329
|
-
<DropdownMenuItem onSelect={() =>
|
|
335
|
+
<DropdownMenuItem onSelect={() => exportResource.mutate()}>
|
|
330
336
|
<FolderDown aria-hidden="true" />
|
|
331
337
|
{i18n.t("resource.export")}
|
|
332
338
|
</DropdownMenuItem>
|
|
@@ -392,7 +398,7 @@ export function ResourceMenu({
|
|
|
392
398
|
) : null}
|
|
393
399
|
{/* Its own sentence, not `resourceErrorKey`'s: nothing was changed, something failed to
|
|
394
400
|
arrive, and "the change was not saved" would send the reader looking for a change. */}
|
|
395
|
-
{
|
|
401
|
+
{exportResource.isError ? <MenuFailure>{i18n.t("resource.exportFailed")}</MenuFailure> : null}
|
|
396
402
|
{/* The import's own sentence, and its own pickers — only where the entry exists, because two
|
|
397
403
|
file inputs on every document's menu would be two elements nothing can ever open. */}
|
|
398
404
|
{bundleImport.isError ? <MenuFailure>{i18n.t("tree.importFailed")}</MenuFailure> : null}
|
|
@@ -67,14 +67,36 @@ export function TitleRowScrollArea({
|
|
|
67
67
|
*/
|
|
68
68
|
export function TitleRow({
|
|
69
69
|
title,
|
|
70
|
+
crumbs,
|
|
70
71
|
description,
|
|
71
72
|
target,
|
|
72
73
|
separated,
|
|
73
74
|
children,
|
|
74
75
|
}: {
|
|
76
|
+
/**
|
|
77
|
+
* ⚠️ **Not drawn while `crumbs` is set** — the path names the thing then, and nothing falls back
|
|
78
|
+
* to this. It stays required all the same, so every caller has to state in one word what the row
|
|
79
|
+
* is about: the next reader of this call site should not have to follow a component two files
|
|
80
|
+
* away to find out.
|
|
81
|
+
*/
|
|
75
82
|
title: string;
|
|
83
|
+
/**
|
|
84
|
+
* A path that stands in for the name.
|
|
85
|
+
*
|
|
86
|
+
* ⚠️ **It REPLACES the heading, it does not join it.** An open board card carries its name in the
|
|
87
|
+
* path already, and the same sentence twice above one another says nothing twice (#692). The row
|
|
88
|
+
* itself, its menu order and its slots stay exactly as they are: only what identifies the thing
|
|
89
|
+
* changes, because for a card the answer is "where it sits", not just "what it is called".
|
|
90
|
+
*/
|
|
91
|
+
crumbs?: ReactNode;
|
|
76
92
|
description?: string | null;
|
|
77
|
-
|
|
93
|
+
/**
|
|
94
|
+
* What the three-dot menu acts on. ⚠️ **Absent means NO menu**, and that is a real state rather
|
|
95
|
+
* than an oversight: a card whose node has not arrived yet has nothing the menu could rename,
|
|
96
|
+
* move or archive, and pointing it at the container instead would archive the wrong thing without
|
|
97
|
+
* asking (#692).
|
|
98
|
+
*/
|
|
99
|
+
target?: ResourceTarget;
|
|
78
100
|
/**
|
|
79
101
|
* A separator that does NOT wait for a scroll.
|
|
80
102
|
*
|
|
@@ -89,7 +111,8 @@ export function TitleRow({
|
|
|
89
111
|
}) {
|
|
90
112
|
const scroll = useContext(TitleRowScrollContext);
|
|
91
113
|
const setScrolled = scroll?.setScrolled;
|
|
92
|
-
const targetId =
|
|
114
|
+
const targetId =
|
|
115
|
+
target === undefined ? undefined : target.type === "flow" ? target.flow.id : target.node.id;
|
|
93
116
|
useEffect(() => {
|
|
94
117
|
void targetId;
|
|
95
118
|
setScrolled?.(false);
|
|
@@ -105,13 +128,17 @@ export function TitleRow({
|
|
|
105
128
|
<div className="flex min-w-0 items-center gap-3">
|
|
106
129
|
<div className="min-w-0">
|
|
107
130
|
<div className="flex min-w-0 flex-wrap items-baseline gap-x-3">
|
|
108
|
-
|
|
109
|
-
|
|
131
|
+
{crumbs === undefined ? (
|
|
132
|
+
<h2 className="truncate text-lg font-semibold">{title}</h2>
|
|
133
|
+
) : (
|
|
134
|
+
crumbs
|
|
135
|
+
)}
|
|
136
|
+
{target?.type === "node" && target.node.kind === "folder" ? (
|
|
110
137
|
<ResourceAccessSummary resourceId={target.node.id} ownerId={target.node.ownerId} />
|
|
111
138
|
) : null}
|
|
112
139
|
{/* A flow carries its own grants since #530, so who reaches it is worth showing where
|
|
113
140
|
it stands — the same question the folder above already answers here. */}
|
|
114
|
-
{target
|
|
141
|
+
{target?.type === "flow" ? (
|
|
115
142
|
<ResourceAccessSummary
|
|
116
143
|
kind="flow"
|
|
117
144
|
resourceId={target.flow.id}
|
|
@@ -129,7 +156,7 @@ export function TitleRow({
|
|
|
129
156
|
<div className="flex shrink-0 items-center gap-2">
|
|
130
157
|
<div data-slot="title-actions" className="flex items-center gap-2" />
|
|
131
158
|
{children}
|
|
132
|
-
<ResourceMenu target={target} variant="title" />
|
|
159
|
+
{target === undefined ? null : <ResourceMenu target={target} variant="title" />}
|
|
133
160
|
</div>
|
|
134
161
|
</div>
|
|
135
162
|
);
|
package/vite.config.ts
CHANGED
|
@@ -1,11 +1,119 @@
|
|
|
1
|
+
import { copyFileSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
1
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { fileViewerRenderers } from "@file-viewer/vite-plugin";
|
|
2
6
|
import tailwindcss from "@tailwindcss/vite";
|
|
3
7
|
import react from "@vitejs/plugin-react";
|
|
4
|
-
import { defineConfig } from "vite";
|
|
8
|
+
import { defineConfig, type Plugin } from "vite";
|
|
9
|
+
|
|
10
|
+
const require = createRequire(import.meta.url);
|
|
11
|
+
|
|
12
|
+
function fileViewerLicenses(): Plugin {
|
|
13
|
+
let outDir = "dist";
|
|
14
|
+
return {
|
|
15
|
+
name: "file-viewer-licenses",
|
|
16
|
+
configResolved(config) {
|
|
17
|
+
outDir = config.build.outDir;
|
|
18
|
+
},
|
|
19
|
+
writeBundle() {
|
|
20
|
+
const target = resolve(outDir, "licenses/file-viewer");
|
|
21
|
+
const reactPackage = require.resolve("@file-viewer/react/package.json");
|
|
22
|
+
const rendererPdfPackage = require.resolve("@file-viewer/renderer-pdf/package.json");
|
|
23
|
+
const rendererPresentationPackage = require.resolve(
|
|
24
|
+
"@file-viewer/renderer-presentation/package.json",
|
|
25
|
+
);
|
|
26
|
+
const rendererWordPackage = require.resolve("@file-viewer/renderer-word/package.json");
|
|
27
|
+
const packageLicenses = [
|
|
28
|
+
["@file-viewer/react", reactPackage],
|
|
29
|
+
[
|
|
30
|
+
"@file-viewer/core",
|
|
31
|
+
createRequire(reactPackage).resolve("@file-viewer/core/package.json"),
|
|
32
|
+
],
|
|
33
|
+
[
|
|
34
|
+
"@file-viewer/doc",
|
|
35
|
+
createRequire(rendererWordPackage).resolve("@file-viewer/doc/package.json"),
|
|
36
|
+
],
|
|
37
|
+
[
|
|
38
|
+
"@file-viewer/docx",
|
|
39
|
+
createRequire(rendererWordPackage).resolve("@file-viewer/docx/package.json"),
|
|
40
|
+
],
|
|
41
|
+
[
|
|
42
|
+
"@file-viewer/ppt",
|
|
43
|
+
resolve(
|
|
44
|
+
dirname(createRequire(rendererPresentationPackage).resolve("@file-viewer/ppt")),
|
|
45
|
+
"package.json",
|
|
46
|
+
),
|
|
47
|
+
],
|
|
48
|
+
[
|
|
49
|
+
"@file-viewer/pptx",
|
|
50
|
+
createRequire(rendererPresentationPackage).resolve("@file-viewer/pptx/package.json"),
|
|
51
|
+
],
|
|
52
|
+
["@file-viewer/renderer-pdf", rendererPdfPackage],
|
|
53
|
+
["@file-viewer/renderer-presentation", rendererPresentationPackage],
|
|
54
|
+
[
|
|
55
|
+
"@file-viewer/renderer-spreadsheet",
|
|
56
|
+
require.resolve("@file-viewer/renderer-spreadsheet/package.json"),
|
|
57
|
+
],
|
|
58
|
+
["@file-viewer/renderer-word", rendererWordPackage],
|
|
59
|
+
["@file-viewer/vite-plugin", require.resolve("@file-viewer/vite-plugin/package.json")],
|
|
60
|
+
["pdfjs-dist", createRequire(rendererPdfPackage).resolve("pdfjs-dist/package.json")],
|
|
61
|
+
] as const;
|
|
62
|
+
mkdirSync(target, { recursive: true });
|
|
63
|
+
for (const [name, packageJson] of packageLicenses) {
|
|
64
|
+
copyFileSync(
|
|
65
|
+
resolve(dirname(packageJson), "LICENSE"),
|
|
66
|
+
resolve(target, `${name.replace("@file-viewer/", "")}.LICENSE`),
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
writeFileSync(
|
|
70
|
+
resolve(target, "THIRD_PARTY_NOTICES.txt"),
|
|
71
|
+
[
|
|
72
|
+
"File Viewer packages used by Intel",
|
|
73
|
+
"",
|
|
74
|
+
"Apache-2.0:",
|
|
75
|
+
"@file-viewer/react",
|
|
76
|
+
"@file-viewer/core",
|
|
77
|
+
"@file-viewer/docx",
|
|
78
|
+
"@file-viewer/pptx",
|
|
79
|
+
"@file-viewer/renderer-pdf",
|
|
80
|
+
"@file-viewer/renderer-presentation",
|
|
81
|
+
"@file-viewer/renderer-spreadsheet",
|
|
82
|
+
"@file-viewer/renderer-word",
|
|
83
|
+
"@file-viewer/vite-plugin",
|
|
84
|
+
"pdfjs-dist",
|
|
85
|
+
"",
|
|
86
|
+
"MIT:",
|
|
87
|
+
"@file-viewer/doc",
|
|
88
|
+
"",
|
|
89
|
+
"Package-specific license (bundled transitively, not exposed by Intel; see ppt.LICENSE):",
|
|
90
|
+
"@file-viewer/ppt",
|
|
91
|
+
"",
|
|
92
|
+
"The complete license text for every package is stored beside this notice.",
|
|
93
|
+
"",
|
|
94
|
+
].join("\n"),
|
|
95
|
+
);
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
5
99
|
|
|
6
100
|
export default defineConfig({
|
|
7
|
-
plugins: [
|
|
8
|
-
|
|
101
|
+
plugins: [
|
|
102
|
+
react(),
|
|
103
|
+
tailwindcss(),
|
|
104
|
+
fileViewerRenderers({
|
|
105
|
+
formats: ["pdf", "docx", "xlsx", "pptx"],
|
|
106
|
+
inject: false,
|
|
107
|
+
chunkStrategy: "renderer",
|
|
108
|
+
}),
|
|
109
|
+
fileViewerLicenses(),
|
|
110
|
+
],
|
|
111
|
+
resolve: {
|
|
112
|
+
alias: {
|
|
113
|
+
"@": fileURLToPath(new URL("./src", import.meta.url)),
|
|
114
|
+
stream: "readable-stream",
|
|
115
|
+
},
|
|
116
|
+
},
|
|
9
117
|
server: {
|
|
10
118
|
proxy: {
|
|
11
119
|
"/api": { target: "http://localhost:8788", changeOrigin: true },
|