@brftech/filex-core 0.4.2 → 0.6.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/dist/{ArchiveViewer-B_0IQExT.js → ArchiveViewer-EGgNqLPE.js} +2 -2
- package/dist/{ArchiveViewer-B_0IQExT.js.map → ArchiveViewer-EGgNqLPE.js.map} +1 -1
- package/dist/{CsvViewer-maMfUy5i.js → CsvViewer-BvriJ42M.js} +2 -2
- package/dist/{CsvViewer-maMfUy5i.js.map → CsvViewer-BvriJ42M.js.map} +1 -1
- package/dist/{DrawioViewer-DP_pXI00.js → DrawioViewer-B_bSPsWX.js} +2 -2
- package/dist/{DrawioViewer-DP_pXI00.js.map → DrawioViewer-B_bSPsWX.js.map} +1 -1
- package/dist/{EpubViewer-DSaqGnVx.js → EpubViewer-hl68h4gG.js} +2 -2
- package/dist/{EpubViewer-DSaqGnVx.js.map → EpubViewer-hl68h4gG.js.map} +1 -1
- package/dist/{IpynbViewer-BmdBanF1.js → IpynbViewer-lhwOjXK7.js} +2 -2
- package/dist/{IpynbViewer-BmdBanF1.js.map → IpynbViewer-lhwOjXK7.js.map} +1 -1
- package/dist/{MermaidViewer-Drlkl0Z5.js → MermaidViewer-H2Z6AYXg.js} +2 -2
- package/dist/{MermaidViewer-Drlkl0Z5.js.map → MermaidViewer-H2Z6AYXg.js.map} +1 -1
- package/dist/{PsdViewer-gftUJrsm.js → PsdViewer-Bsk-11yH.js} +2 -2
- package/dist/{PsdViewer-gftUJrsm.js.map → PsdViewer-Bsk-11yH.js.map} +1 -1
- package/dist/{TiffViewer-0Uv0-Lxh.js → TiffViewer-D-j9vycG.js} +2 -2
- package/dist/{TiffViewer-0Uv0-Lxh.js.map → TiffViewer-D-j9vycG.js.map} +1 -1
- package/dist/{Viewer3D-Gu3kUpxV.js → Viewer3D-Bcr70rTe.js} +2 -2
- package/dist/{Viewer3D-Gu3kUpxV.js.map → Viewer3D-Bcr70rTe.js.map} +1 -1
- package/dist/filex-core.js +50 -25
- package/dist/filex-core.umd.cjs +59 -58
- package/dist/filex-core.umd.cjs.map +1 -1
- package/dist/index-C_ZSnk_I.js +11109 -0
- package/dist/index-C_ZSnk_I.js.map +1 -0
- package/dist/index.d.ts +597 -4
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/FileExplorer.vue +636 -15
- package/src/components/CommandPalette.vue +24 -1
- package/src/components/ContextMenu.vue +114 -8
- package/src/components/GalleryView.vue +214 -0
- package/src/components/GridView.vue +34 -1
- package/src/components/InspectorPanel.vue +170 -0
- package/src/components/ListView.vue +40 -6
- package/src/components/OnboardingTour.vue +332 -0
- package/src/components/OperationsCenter.vue +284 -0
- package/src/components/PendingOpsTray.vue +50 -66
- package/src/components/QuickLook.vue +142 -0
- package/src/components/SecondaryPane.vue +411 -0
- package/src/components/ShortcutSettings.vue +270 -0
- package/src/components/ShortcutsHelp.vue +30 -9
- package/src/components/TabBar.vue +174 -0
- package/src/components/ThemeGallery.vue +253 -0
- package/src/components/Toolbar.vue +75 -11
- package/src/components/UploadProgress.vue +49 -57
- package/src/composables/useFileApi.ts +53 -0
- package/src/composables/useKeyboardShortcuts.ts +340 -137
- package/src/composables/useOperations.ts +291 -0
- package/src/composables/useTabs.ts +222 -0
- package/src/index.ts +51 -0
- package/src/lib/dragGhost.ts +41 -0
- package/src/lib/themes.ts +505 -0
- package/src/locales/en.ts +125 -0
- package/src/locales/tr.ts +125 -0
- package/src/modals/Modal.vue +41 -5
- package/src/styles/base.css +1210 -0
- package/src/types/FileNode.ts +1 -1
- package/dist/index-BLocdbmc.js +0 -7993
- package/dist/index-BLocdbmc.js.map +0 -1
|
@@ -1,78 +1,70 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
/**
|
|
3
|
-
* UploadProgress —
|
|
3
|
+
* UploadProgress — renderless upload publisher (wiring:c3).
|
|
4
|
+
*
|
|
5
|
+
* Historically this drew its own floating bottom-right footer. Since the
|
|
6
|
+
* unified operations center it renders NOTHING: it reconciles the host's
|
|
7
|
+
* `jobs` list into the shared useOperations store, and the visible UI is
|
|
8
|
+
* OperationsCenter's badge + panel. The original emit contract is kept —
|
|
9
|
+
* cancel/dismiss (and the new retry) still bubble to the host, which owns
|
|
10
|
+
* the actual upload machinery. Mount it exactly as before; just pass the
|
|
11
|
+
* store via `center`.
|
|
4
12
|
*/
|
|
5
|
-
import {
|
|
13
|
+
import { watch } from 'vue';
|
|
6
14
|
import type { UploadJob } from '../composables/useUploadChunked';
|
|
7
15
|
import type { LocaleCode } from '../types/ExplorerConfig';
|
|
8
|
-
import {
|
|
16
|
+
import type { OperationsStore, OperationStatus } from '../composables/useOperations';
|
|
9
17
|
|
|
10
18
|
const props = defineProps<{
|
|
11
19
|
jobs: UploadJob[];
|
|
20
|
+
/** Kept for mount compatibility — strings now render in OperationsCenter. */
|
|
12
21
|
locale: LocaleCode;
|
|
22
|
+
center: OperationsStore;
|
|
13
23
|
}>();
|
|
14
24
|
|
|
15
25
|
const emit = defineEmits<{
|
|
16
26
|
(e: 'cancel', job: UploadJob): void;
|
|
17
27
|
(e: 'dismiss', job: UploadJob): void;
|
|
28
|
+
(e: 'retry', job: UploadJob): void;
|
|
18
29
|
}>();
|
|
19
30
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
switch (j.status) {
|
|
26
|
-
case 'done':
|
|
27
|
-
return t('upload.done');
|
|
28
|
-
case 'error':
|
|
29
|
-
return `${t('upload.error')}: ${j.error ?? ''}`;
|
|
30
|
-
case 'aborted':
|
|
31
|
-
return t('upload.aborted');
|
|
32
|
-
default:
|
|
33
|
-
return t('upload.progress');
|
|
34
|
-
}
|
|
31
|
+
function mapStatus(s: UploadJob['status']): OperationStatus {
|
|
32
|
+
if (s === 'done') return 'done';
|
|
33
|
+
if (s === 'error') return 'error';
|
|
34
|
+
if (s === 'aborted') return 'aborted';
|
|
35
|
+
return 'running'; // pending | initializing | uploading | finalizing
|
|
35
36
|
}
|
|
37
|
+
|
|
38
|
+
watch(
|
|
39
|
+
() => props.jobs,
|
|
40
|
+
(jobs) => {
|
|
41
|
+
props.center.sync(
|
|
42
|
+
'upload',
|
|
43
|
+
jobs.map((j) => ({
|
|
44
|
+
input: {
|
|
45
|
+
id: j.id,
|
|
46
|
+
kind: 'upload' as const,
|
|
47
|
+
name: j.file.name,
|
|
48
|
+
percent: j.totalBytes > 0 || j.status === 'done' ? j.percent : null,
|
|
49
|
+
status: mapStatus(j.status),
|
|
50
|
+
error: j.error ?? null,
|
|
51
|
+
uploadedBytes: j.uploadedBytes,
|
|
52
|
+
totalBytes: j.totalBytes,
|
|
53
|
+
cancellable: j.status === 'uploading' || j.status === 'initializing',
|
|
54
|
+
retryable: j.status === 'error',
|
|
55
|
+
},
|
|
56
|
+
actions: {
|
|
57
|
+
cancel: () => emit('cancel', j),
|
|
58
|
+
dismiss: () => emit('dismiss', j),
|
|
59
|
+
retry: () => emit('retry', j),
|
|
60
|
+
},
|
|
61
|
+
})),
|
|
62
|
+
);
|
|
63
|
+
},
|
|
64
|
+
{ immediate: true },
|
|
65
|
+
);
|
|
36
66
|
</script>
|
|
37
67
|
|
|
38
68
|
<template>
|
|
39
|
-
<
|
|
40
|
-
<div v-if="visible.length > 0" class="fe-upload">
|
|
41
|
-
<div class="fe-upload__header">
|
|
42
|
-
<strong>{{ t('upload.progress') }}</strong>
|
|
43
|
-
<span class="fe-upload__count">{{ visible.length }}</span>
|
|
44
|
-
</div>
|
|
45
|
-
<ul class="fe-upload__list">
|
|
46
|
-
<li
|
|
47
|
-
v-for="j in visible"
|
|
48
|
-
:key="j.id"
|
|
49
|
-
class="fe-upload__item"
|
|
50
|
-
:class="`is-${j.status}`"
|
|
51
|
-
>
|
|
52
|
-
<div class="fe-upload__name" :title="j.file.name">{{ j.file.name }}</div>
|
|
53
|
-
<div class="fe-upload__bar" :aria-valuenow="j.percent" role="progressbar">
|
|
54
|
-
<div class="fe-upload__bar-fill" :style="{ width: j.percent + '%' }" />
|
|
55
|
-
</div>
|
|
56
|
-
<div class="fe-upload__meta">
|
|
57
|
-
<span>{{ statusLabel(j) }}</span>
|
|
58
|
-
<span>{{ formatSize(j.uploadedBytes) }} / {{ formatSize(j.totalBytes) }}</span>
|
|
59
|
-
<button
|
|
60
|
-
v-if="j.status === 'uploading' || j.status === 'initializing'"
|
|
61
|
-
type="button"
|
|
62
|
-
class="fe-upload__cancel"
|
|
63
|
-
@click="emit('cancel', j)"
|
|
64
|
-
>
|
|
65
|
-
{{ t('upload.cancel') }}
|
|
66
|
-
</button>
|
|
67
|
-
<button
|
|
68
|
-
v-else
|
|
69
|
-
type="button"
|
|
70
|
-
class="fe-upload__cancel"
|
|
71
|
-
@click="emit('dismiss', j)"
|
|
72
|
-
>×</button>
|
|
73
|
-
</div>
|
|
74
|
-
</li>
|
|
75
|
-
</ul>
|
|
76
|
-
</div>
|
|
77
|
-
</transition>
|
|
69
|
+
<i v-if="false" />
|
|
78
70
|
</template>
|
|
@@ -106,6 +106,23 @@ export interface UserSearchResponse {
|
|
|
106
106
|
users: UserSuggestion[];
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
/* === calisma:d3 — node comments (inspector panel) === */
|
|
110
|
+
|
|
111
|
+
/** Mirrors backend `model.NodeComment` (GET /api/files/comments?node_id=…). */
|
|
112
|
+
export interface NodeComment {
|
|
113
|
+
id: number;
|
|
114
|
+
node_id: number;
|
|
115
|
+
user_id: number;
|
|
116
|
+
body: string;
|
|
117
|
+
created_at: string;
|
|
118
|
+
updated_at?: string;
|
|
119
|
+
/** Joined author display name (email fallback), filled by the backend. */
|
|
120
|
+
author_name?: string;
|
|
121
|
+
/** Whether the CURRENT caller may delete this row (author or admin). */
|
|
122
|
+
can_delete?: boolean;
|
|
123
|
+
}
|
|
124
|
+
/* === /calisma:d3 === */
|
|
125
|
+
|
|
109
126
|
export interface InviteResponse {
|
|
110
127
|
mode: 'granted' | 'user_created' | 'shared';
|
|
111
128
|
user_id?: number;
|
|
@@ -741,6 +758,38 @@ export function useFileApi(config: ExplorerConfig) {
|
|
|
741
758
|
}
|
|
742
759
|
/* === /koru:k1 === */
|
|
743
760
|
|
|
761
|
+
/* === calisma:d3 — node comments (inspector panel) ===
|
|
762
|
+
* Same manager-URL derivation trick as versions/permissions so embedded
|
|
763
|
+
* proxies forwarding the whole /api/files/* subtree keep working.
|
|
764
|
+
* GET /api/files/comments?node_id=N → {comments, node_id}
|
|
765
|
+
* POST /api/files/comments → {node_id, body}
|
|
766
|
+
* DELETE /api/files/comments/{id} → {ok}
|
|
767
|
+
*/
|
|
768
|
+
function commentsUrl(sub = ''): string {
|
|
769
|
+
const base = endpoints.manager.replace(/\/manager(\?.*)?$/, '/comments');
|
|
770
|
+
return base + sub;
|
|
771
|
+
}
|
|
772
|
+
async function listComments(nodeId: number): Promise<NodeComment[]> {
|
|
773
|
+
const data = await jsonFetch<{ comments?: NodeComment[] | null }>(
|
|
774
|
+
commentsUrl() + '?node_id=' + encodeURIComponent(String(nodeId)),
|
|
775
|
+
);
|
|
776
|
+
return Array.isArray(data?.comments) ? data.comments : [];
|
|
777
|
+
}
|
|
778
|
+
async function addComment(nodeId: number, body: string): Promise<NodeComment> {
|
|
779
|
+
const data = await jsonFetch<{ comment: NodeComment }>(commentsUrl(), {
|
|
780
|
+
method: 'POST',
|
|
781
|
+
headers: { 'Content-Type': 'application/json' },
|
|
782
|
+
body: JSON.stringify({ node_id: nodeId, body }),
|
|
783
|
+
});
|
|
784
|
+
return data.comment;
|
|
785
|
+
}
|
|
786
|
+
async function deleteComment(id: number): Promise<void> {
|
|
787
|
+
await jsonFetch(commentsUrl('/' + encodeURIComponent(String(id))), {
|
|
788
|
+
method: 'DELETE',
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
/* === /calisma:d3 === */
|
|
792
|
+
|
|
744
793
|
// Mint a short-lived WebSocket auth ticket for the realtime layer. Derived
|
|
745
794
|
// from the manager URL (so it flows through the same host proxy) and uses the
|
|
746
795
|
// same auth/creds as every other call. Returns null on any failure (a backend
|
|
@@ -790,6 +839,10 @@ export function useFileApi(config: ExplorerConfig) {
|
|
|
790
839
|
listVersions,
|
|
791
840
|
restoreVersion,
|
|
792
841
|
snapshotVersion,
|
|
842
|
+
// Node comments (calisma:d3 inspector)
|
|
843
|
+
listComments,
|
|
844
|
+
addComment,
|
|
845
|
+
deleteComment,
|
|
793
846
|
// Permissions (RBAC panel)
|
|
794
847
|
listPermissions,
|
|
795
848
|
resolveEmail,
|