Compare commits
3 Commits
6d64edb62c
...
11db1417a8
| Author | SHA1 | Date | |
|---|---|---|---|
| 11db1417a8 | |||
| c5a6461f5c | |||
| 0ceb6808c4 |
Generated
+62
-62
@@ -159,12 +159,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/parser": {
|
"node_modules/@babel/parser": {
|
||||||
"version": "7.29.7",
|
"version": "7.29.8",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz",
|
||||||
"integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==",
|
"integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.29.7"
|
"@babel/types": "^7.29.8"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
"parser": "bin/babel-parser.js"
|
"parser": "bin/babel-parser.js"
|
||||||
@@ -174,9 +174,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/types": {
|
"node_modules/@babel/types": {
|
||||||
"version": "7.29.7",
|
"version": "7.29.8",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
|
||||||
"integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==",
|
"integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-string-parser": "^7.29.7",
|
"@babel/helper-string-parser": "^7.29.7",
|
||||||
@@ -955,39 +955,39 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/compiler-core": {
|
"node_modules/@vue/compiler-core": {
|
||||||
"version": "3.5.40",
|
"version": "3.5.42",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.40.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.42.tgz",
|
||||||
"integrity": "sha512-39E8IgOhTbVDnoJFMKc2DvYnypcZwUqgUhQkccva/0m6FUwtIKSGV7n1hpVmYcFaoRAwf9pBcwnKlCEsN63ZEQ==",
|
"integrity": "sha512-2Ye1ilMtKXxl8qZUrQ5j0CdgenFp/HFQmta6rfRyfEsTG69L6Wk+tWuNoHYHMx9E8tF2Slvdg1FuwDvAXdy1LQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/parser": "^7.29.7",
|
"@babel/parser": "^7.29.8",
|
||||||
"@vue/shared": "3.5.40",
|
"@vue/shared": "3.5.42",
|
||||||
"entities": "^7.0.1",
|
"entities": "^7.0.1",
|
||||||
"estree-walker": "^2.0.2",
|
"estree-walker": "^2.0.2",
|
||||||
"source-map-js": "^1.2.1"
|
"source-map-js": "^1.2.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/compiler-dom": {
|
"node_modules/@vue/compiler-dom": {
|
||||||
"version": "3.5.40",
|
"version": "3.5.42",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.40.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.42.tgz",
|
||||||
"integrity": "sha512-pwkx4vqlqOspFstrcmzwkKLePVMD3PT65imRzLhanU2V1Fj4K13g6OXjanOyzw3aTAuRk84BOmY8f3rEHqPaVA==",
|
"integrity": "sha512-qbhQZEFmycr+ni/qyuccS4sucNN7VAbDfbkvNxWOX2VfgFm90MNs3/UhRNKoPMEIVn0F8gdlYjLPvqxHwHeQOA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-core": "3.5.40",
|
"@vue/compiler-core": "3.5.42",
|
||||||
"@vue/shared": "3.5.40"
|
"@vue/shared": "3.5.42"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/compiler-sfc": {
|
"node_modules/@vue/compiler-sfc": {
|
||||||
"version": "3.5.40",
|
"version": "3.5.42",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.40.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.42.tgz",
|
||||||
"integrity": "sha512-gIf497P4kpuALcvs5n3AEg1Vdn0pSY4XbjASIfHNYF1/MP3T2Mf2STERTubysBxCRxzJGJYtF/O7vwJrxFB3Vw==",
|
"integrity": "sha512-fkCAFB4okcAANGMThboWnScp/gzWjU0ZSkVnjTIiplmMDq2uq0tIB3j+xVu4rhv5rvOgBySCysudmbMd6xRRqw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/parser": "^7.29.7",
|
"@babel/parser": "^7.29.8",
|
||||||
"@vue/compiler-core": "3.5.40",
|
"@vue/compiler-core": "3.5.42",
|
||||||
"@vue/compiler-dom": "3.5.40",
|
"@vue/compiler-dom": "3.5.42",
|
||||||
"@vue/compiler-ssr": "3.5.40",
|
"@vue/compiler-ssr": "3.5.42",
|
||||||
"@vue/shared": "3.5.40",
|
"@vue/shared": "3.5.42",
|
||||||
"estree-walker": "^2.0.2",
|
"estree-walker": "^2.0.2",
|
||||||
"magic-string": "^0.30.21",
|
"magic-string": "^0.30.21",
|
||||||
"postcss": "^8.5.19",
|
"postcss": "^8.5.19",
|
||||||
@@ -995,13 +995,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/compiler-ssr": {
|
"node_modules/@vue/compiler-ssr": {
|
||||||
"version": "3.5.40",
|
"version": "3.5.42",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.40.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.42.tgz",
|
||||||
"integrity": "sha512-rrE5xiXG663+vHCHa3J9p2z5OcBRjXmoqenprJxAFQxg5pSshzeBiCE6pu46axapRJ2Adk0YDA2BRZVjiHXnhg==",
|
"integrity": "sha512-xmLk3wLkbizPAiLyomjgFFosf2ys9b5Ghb+oh/k2tnvipNz8OFrQOiTcWCzyK7MpBp9KkyGtfvgfLUivbmuGYA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-dom": "3.5.40",
|
"@vue/compiler-dom": "3.5.42",
|
||||||
"@vue/shared": "3.5.40"
|
"@vue/shared": "3.5.42"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/devtools-api": {
|
"node_modules/@vue/devtools-api": {
|
||||||
@@ -1048,51 +1048,51 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/reactivity": {
|
"node_modules/@vue/reactivity": {
|
||||||
"version": "3.5.40",
|
"version": "3.5.42",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.40.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.42.tgz",
|
||||||
"integrity": "sha512-B7ot9UlUZOi1zbq61/LvE88ZLTV8IlajTdiZTAEiDQgrnIMIZoPr9kGw0Zw46ObW62O9+H/Be3kMbfb7kYPQZA==",
|
"integrity": "sha512-TzNNfKpb7hDxbQltwAut8VDQA5YP+BuRlxntHUuRjyKwlMvmAPbs3unhCvieijifY6vFfVBwsS7wG/C7uq+bEQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/shared": "3.5.40"
|
"@vue/shared": "3.5.42"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/runtime-core": {
|
"node_modules/@vue/runtime-core": {
|
||||||
"version": "3.5.40",
|
"version": "3.5.42",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.40.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.42.tgz",
|
||||||
"integrity": "sha512-KAZLweuZ6uUJPK1PMSQPgBU5gCjgrrfjUhSglmU9NhH+Zjepa8cnwSydPWDWHDwOgY4g3VcZ+PljbiHlURNCbw==",
|
"integrity": "sha512-9uACtuHs7vJGkm5Bp3xu4xRDLFTIYy5DgxpToVjqGIAhAEKwQfsaLvKINhM6nFVp6bZPRFGdDqd1g52MqKsotA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/reactivity": "3.5.40",
|
"@vue/reactivity": "3.5.42",
|
||||||
"@vue/shared": "3.5.40"
|
"@vue/shared": "3.5.42"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/runtime-dom": {
|
"node_modules/@vue/runtime-dom": {
|
||||||
"version": "3.5.40",
|
"version": "3.5.42",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.40.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.42.tgz",
|
||||||
"integrity": "sha512-ZfrX8ssZQds900L9pr8AuK05ddnMsR4MPMZr8cPN9GoqoPWcXLhjvvbIA2SMv+7a97sJ1vv9pj/zxK0Cq/eEFQ==",
|
"integrity": "sha512-rsCmhiWLaRxGltLwhlCWyYkFn7WAbKRh0q17eZ1A6Dq6eqc2ACQ61IIryxz0LrsvCzHSilLA9JHovVwM8CNE2g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/reactivity": "3.5.40",
|
"@vue/reactivity": "3.5.42",
|
||||||
"@vue/runtime-core": "3.5.40",
|
"@vue/runtime-core": "3.5.42",
|
||||||
"@vue/shared": "3.5.40",
|
"@vue/shared": "3.5.42",
|
||||||
"csstype": "^3.2.3"
|
"csstype": "^3.2.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/server-renderer": {
|
"node_modules/@vue/server-renderer": {
|
||||||
"version": "3.5.40",
|
"version": "3.5.42",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.40.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.42.tgz",
|
||||||
"integrity": "sha512-XNJym9WpevhTVt1HuwOrCRJ5Q+9z4BjTMrDtjTrvx74SmUll8spNTw6whWJa9mEkO4PKn5TihI/bm/8ds2QVJw==",
|
"integrity": "sha512-2++5dUyYS4gvo7xQXSECUDhB7TS0aOl5SeVfC5qSq1Jgfhjvegw1zqhwTIR3imZ+QYPJQw9gfcFvXGAjGZ7ajQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-ssr": "3.5.40",
|
"@vue/compiler-ssr": "3.5.42",
|
||||||
"@vue/runtime-dom": "3.5.40",
|
"@vue/runtime-dom": "3.5.42",
|
||||||
"@vue/shared": "3.5.40"
|
"@vue/shared": "3.5.42"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@vue/shared": {
|
"node_modules/@vue/shared": {
|
||||||
"version": "3.5.40",
|
"version": "3.5.42",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.40.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.42.tgz",
|
||||||
"integrity": "sha512-WxnBtruIqOoV3rA4jeKDWzrYI5h7Cp4+pjwDi8kWGHz+IslhiN+wguLVVhtv2l8VoU02rzDCVfDjgCl1lNpZVg==",
|
"integrity": "sha512-2rPxex1jQf4jvl9MOHl6YaXCPcrNqz/FstMOEh3QWY+/OME9nQTvl9WYeCwhW7AFjaR0SnngZGlp/wkR6rkI6g==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@vue/test-utils": {
|
"node_modules/@vue/test-utils": {
|
||||||
@@ -3098,16 +3098,16 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/vue": {
|
"node_modules/vue": {
|
||||||
"version": "3.5.40",
|
"version": "3.5.42",
|
||||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.40.tgz",
|
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.42.tgz",
|
||||||
"integrity": "sha512-+8PJ4SJXdn/cHGImF4CKdxlWHIN5Dkt7DoufRREM6h6uVCx2m7QxgcEQmmzyOK8A9mcafg7sFbJFYsdFVubTig==",
|
"integrity": "sha512-4RyHQTbQvOPs3MfvUO1Sg0YRrKNnA0mAVtvpd12Tg1fKDN7OHBUl1IqSn8zGJjK9nI3NkNp8cgTpVrSZC5TTcA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vue/compiler-dom": "3.5.40",
|
"@vue/compiler-dom": "3.5.42",
|
||||||
"@vue/compiler-sfc": "3.5.40",
|
"@vue/compiler-sfc": "3.5.42",
|
||||||
"@vue/runtime-dom": "3.5.40",
|
"@vue/runtime-dom": "3.5.42",
|
||||||
"@vue/server-renderer": "3.5.40",
|
"@vue/server-renderer": "3.5.42",
|
||||||
"@vue/shared": "3.5.40"
|
"@vue/shared": "3.5.42"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "*"
|
"typescript": "*"
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref, watch } from 'vue'
|
||||||
|
import { EntityObject } from '@DocumentsManager/models/entity'
|
||||||
|
import { getFileIcon } from '@/utils/fileHelpers'
|
||||||
|
|
||||||
|
type PreviewSource = (item: { id: string; meta?: Record<string, unknown> }) => string | Blob | Promise<string | Blob>
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<{
|
||||||
|
entity: EntityObject
|
||||||
|
source?: PreviewSource
|
||||||
|
size?: number
|
||||||
|
}>(), {
|
||||||
|
source: undefined,
|
||||||
|
size: 32,
|
||||||
|
})
|
||||||
|
|
||||||
|
const failed = ref(false)
|
||||||
|
const url = computed(() => {
|
||||||
|
if (!props.source) return null
|
||||||
|
const result = props.source({
|
||||||
|
id: String(props.entity.identifier ?? ''),
|
||||||
|
meta: { collection: props.entity.collection ? String(props.entity.collection) : null },
|
||||||
|
})
|
||||||
|
return typeof result === 'string' ? result : null
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(url, () => {
|
||||||
|
failed.value = false
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="file-preview"
|
||||||
|
:style="{ width: `${size}px`, height: `${size}px` }"
|
||||||
|
>
|
||||||
|
<v-img
|
||||||
|
v-if="url && !failed"
|
||||||
|
:src="url"
|
||||||
|
:alt="entity.properties.label || 'File preview'"
|
||||||
|
contain
|
||||||
|
width="100%"
|
||||||
|
height="100%"
|
||||||
|
@error="failed = true"
|
||||||
|
/>
|
||||||
|
<v-icon v-else :size="size * 0.75" color="grey">{{ getFileIcon(entity) }}</v-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.file-preview {
|
||||||
|
flex: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 6px;
|
||||||
|
background-color: rgb(var(--v-theme-surface-variant), 0.4);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
import { VNavigationDrawer } from 'vuetify/components'
|
import { VNavigationDrawer } from 'vuetify/components'
|
||||||
import { CollectionObject } from '@DocumentsManager/models/collection'
|
import { CollectionObject } from '@DocumentsManager/models/collection'
|
||||||
import { EntityObject } from '@DocumentsManager/models/entity'
|
import { EntityObject } from '@DocumentsManager/models/entity'
|
||||||
@@ -8,8 +8,10 @@ import { getFileIcon, formatSize, formatDate } from '@/utils/fileHelpers'
|
|||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
selectedItems: (CollectionObject | EntityObject)[]
|
selectedItems: (CollectionObject | EntityObject)[]
|
||||||
embedded?: boolean
|
embedded?: boolean
|
||||||
|
previewUrl?: string | null
|
||||||
}>(), {
|
}>(), {
|
||||||
embedded: false,
|
embedded: false,
|
||||||
|
previewUrl: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -69,6 +71,13 @@ const totalSize = computed(() => {
|
|||||||
return sum
|
return sum
|
||||||
}, 0)
|
}, 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const previewFailed = ref(false)
|
||||||
|
const showPreview = computed(() => isEntity.value && !!props.previewUrl && !previewFailed.value)
|
||||||
|
|
||||||
|
watch(() => props.previewUrl, () => {
|
||||||
|
previewFailed.value = false
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -94,9 +103,24 @@ const totalSize = computed(() => {
|
|||||||
|
|
||||||
<!-- Single item selected -->
|
<!-- Single item selected -->
|
||||||
<template v-if="singleSelection && selectedItem">
|
<template v-if="singleSelection && selectedItem">
|
||||||
<!-- Icon and name -->
|
<!-- Preview/icon and name -->
|
||||||
<div class="text-center mb-4">
|
<div class="text-center mb-4">
|
||||||
<v-icon :color="itemIconColor" size="64">{{ itemIcon }}</v-icon>
|
<div v-if="showPreview" class="files-info-preview mb-3">
|
||||||
|
<v-img
|
||||||
|
:src="previewUrl!"
|
||||||
|
:alt="selectedItem.properties.label || 'File preview'"
|
||||||
|
aspect-ratio="1.45"
|
||||||
|
contain
|
||||||
|
@error="previewFailed = true"
|
||||||
|
>
|
||||||
|
<template #placeholder>
|
||||||
|
<div class="d-flex fill-height align-center justify-center">
|
||||||
|
<v-progress-circular indeterminate color="primary" size="28" width="2" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</v-img>
|
||||||
|
</div>
|
||||||
|
<v-icon v-else :color="itemIconColor" size="64">{{ itemIcon }}</v-icon>
|
||||||
<div class="text-h6 mt-2 text-truncate">{{ selectedItem.properties.label || String(selectedItem.identifier ?? '') }}</div>
|
<div class="text-h6 mt-2 text-truncate">{{ selectedItem.properties.label || String(selectedItem.identifier ?? '') }}</div>
|
||||||
<div class="text-caption text-grey">
|
<div class="text-caption text-grey">
|
||||||
{{ isCollection ? 'Folder' : entity?.properties.mime || 'File' }}
|
{{ isCollection ? 'Folder' : entity?.properties.mime || 'File' }}
|
||||||
@@ -205,4 +229,11 @@ const totalSize = computed(() => {
|
|||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
background-color: rgb(var(--v-theme-surface));
|
background-color: rgb(var(--v-theme-surface));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.files-info-preview {
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid rgb(var(--v-border-color));
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: rgb(var(--v-theme-surface-variant));
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { CollectionObject } from '@DocumentsManager/models/collection'
|
import { CollectionObject } from '@DocumentsManager/models/collection'
|
||||||
import { EntityObject } from '@DocumentsManager/models/entity'
|
import { EntityObject } from '@DocumentsManager/models/entity'
|
||||||
import { getFileIcon, formatSize, formatDate } from '@/utils/fileHelpers'
|
import { formatSize, formatDate } from '@/utils/fileHelpers'
|
||||||
import FileActionsMenu from '@/components/FileActionsMenu.vue'
|
import FileActionsMenu from '@/components/FileActionsMenu.vue'
|
||||||
|
import FilePreview from '@/components/FilePreview.vue'
|
||||||
import FilePreviewPopover from '@/components/viewer/FilePreviewPopover.vue'
|
import FilePreviewPopover from '@/components/viewer/FilePreviewPopover.vue'
|
||||||
|
|
||||||
type ItemWithType = {
|
type ItemWithType = {
|
||||||
@@ -18,6 +19,7 @@ const props = defineProps<{
|
|||||||
entities: EntityObject[]
|
entities: EntityObject[]
|
||||||
selectedIds: Set<string>
|
selectedIds: Set<string>
|
||||||
previewSource?: PreviewSource
|
previewSource?: PreviewSource
|
||||||
|
thumbnailSource?: PreviewSource
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -93,7 +95,12 @@ function isCollection(wrapped: ItemWithType): wrapped is { item: CollectionObjec
|
|||||||
@dblclick.stop="emit('open', wrapped.item)"
|
@dblclick.stop="emit('open', wrapped.item)"
|
||||||
>
|
>
|
||||||
<div class="files-details-cell files-details-name">
|
<div class="files-details-cell files-details-name">
|
||||||
<v-icon color="grey" size="small" class="mr-2">{{ getFileIcon(wrapped.item as EntityObject) }}</v-icon>
|
<FilePreview
|
||||||
|
:entity="(wrapped.item as EntityObject)"
|
||||||
|
:source="thumbnailSource"
|
||||||
|
:size="24"
|
||||||
|
class="mr-2"
|
||||||
|
/>
|
||||||
{{ wrapped.item.properties.label || String(wrapped.item.identifier ?? '') }}
|
{{ wrapped.item.properties.label || String(wrapped.item.identifier ?? '') }}
|
||||||
</div>
|
</div>
|
||||||
<div class="files-details-cell files-details-size">{{ formatSize(wrapped.item.properties.size) }}</div>
|
<div class="files-details-cell files-details-size">{{ formatSize(wrapped.item.properties.size) }}</div>
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { CollectionObject } from '@DocumentsManager/models/collection'
|
import { CollectionObject } from '@DocumentsManager/models/collection'
|
||||||
import { EntityObject } from '@DocumentsManager/models/entity'
|
import { EntityObject } from '@DocumentsManager/models/entity'
|
||||||
import { getFileIcon, formatSize } from '@/utils/fileHelpers'
|
import { formatSize } from '@/utils/fileHelpers'
|
||||||
import FileActionsMenu from '@/components/FileActionsMenu.vue'
|
import FileActionsMenu from '@/components/FileActionsMenu.vue'
|
||||||
|
import FilePreview from '@/components/FilePreview.vue'
|
||||||
import FilePreviewPopover from '@/components/viewer/FilePreviewPopover.vue'
|
import FilePreviewPopover from '@/components/viewer/FilePreviewPopover.vue'
|
||||||
|
|
||||||
type PreviewSource = (item: { id: string; meta?: Record<string, unknown> }) => string | Blob | Promise<string | Blob>
|
type PreviewSource = (item: { id: string; meta?: Record<string, unknown> }) => string | Blob | Promise<string | Blob>
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
collections: CollectionObject[]
|
collections: CollectionObject[]
|
||||||
entities: EntityObject[]
|
entities: EntityObject[]
|
||||||
selectedIds: Set<string>
|
selectedIds: Set<string>
|
||||||
previewSource?: PreviewSource
|
previewSource?: PreviewSource
|
||||||
|
thumbnailSource?: PreviewSource
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -74,7 +76,9 @@ const emit = defineEmits<{
|
|||||||
@show-details="emit('show-details', $event)"
|
@show-details="emit('show-details', $event)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<v-icon size="48" color="grey">{{ getFileIcon(entity) }}</v-icon>
|
<div class="files-grid-thumbnail">
|
||||||
|
<FilePreview :entity="entity" :source="thumbnailSource" :size="64" />
|
||||||
|
</div>
|
||||||
<div class="files-grid-label">{{ entity.properties.label || String(entity.identifier ?? '') }}</div>
|
<div class="files-grid-label">{{ entity.properties.label || String(entity.identifier ?? '') }}</div>
|
||||||
<div class="files-grid-size">{{ formatSize(entity.properties.size) }}</div>
|
<div class="files-grid-size">{{ formatSize(entity.properties.size) }}</div>
|
||||||
|
|
||||||
@@ -136,6 +140,17 @@ const emit = defineEmits<{
|
|||||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.files-grid-thumbnail {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: rgb(var(--v-theme-surface-variant), 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
.files-grid-label {
|
.files-grid-label {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { CollectionObject } from '@DocumentsManager/models/collection'
|
import { CollectionObject } from '@DocumentsManager/models/collection'
|
||||||
import { EntityObject } from '@DocumentsManager/models/entity'
|
import { EntityObject } from '@DocumentsManager/models/entity'
|
||||||
import { getFileIcon, formatSize } from '@/utils/fileHelpers'
|
import { formatSize } from '@/utils/fileHelpers'
|
||||||
import FileActionsMenu from '@/components/FileActionsMenu.vue'
|
import FileActionsMenu from '@/components/FileActionsMenu.vue'
|
||||||
|
import FilePreview from '@/components/FilePreview.vue'
|
||||||
import FilePreviewPopover from '@/components/viewer/FilePreviewPopover.vue'
|
import FilePreviewPopover from '@/components/viewer/FilePreviewPopover.vue'
|
||||||
|
|
||||||
type ItemWithType = {
|
type ItemWithType = {
|
||||||
@@ -18,6 +19,7 @@ const props = defineProps<{
|
|||||||
entities: EntityObject[]
|
entities: EntityObject[]
|
||||||
selectedIds: Set<string>
|
selectedIds: Set<string>
|
||||||
previewSource?: PreviewSource
|
previewSource?: PreviewSource
|
||||||
|
thumbnailSource?: PreviewSource
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
@@ -79,7 +81,11 @@ function isCollection(wrapped: ItemWithType): wrapped is { item: CollectionObjec
|
|||||||
@dblclick.stop="emit('open', wrapped.item)"
|
@dblclick.stop="emit('open', wrapped.item)"
|
||||||
>
|
>
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<v-icon color="grey">{{ getFileIcon(wrapped.item as EntityObject) }}</v-icon>
|
<FilePreview
|
||||||
|
:entity="(wrapped.item as EntityObject)"
|
||||||
|
:source="thumbnailSource"
|
||||||
|
:size="32"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<v-list-item-title>{{ wrapped.item.properties.label || String(wrapped.item.identifier ?? '') }}</v-list-item-title>
|
<v-list-item-title>{{ wrapped.item.properties.label || String(wrapped.item.identifier ?? '') }}</v-list-item-title>
|
||||||
<v-list-item-subtitle>{{ formatSize(wrapped.item.properties.size) }}</v-list-item-subtitle>
|
<v-list-item-subtitle>{{ formatSize(wrapped.item.properties.size) }}</v-list-item-subtitle>
|
||||||
|
|||||||
+42
-4
@@ -129,9 +129,42 @@ function entityToViewerItem(entity: EntityObject): ViewerItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function resolveViewerSource(item: ViewerItem): string {
|
function resolveViewerSource(item: ViewerItem): string {
|
||||||
return documentManager.getEntityUrl(item.id, (item.meta?.collection as string | null) ?? null)
|
return documentManager.getEntityPreviewUrl(
|
||||||
|
item.id,
|
||||||
|
(item.meta?.collection as string | null) ?? null,
|
||||||
|
'fullscreen',
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolvePreviewSource(item: ViewerItem): string {
|
||||||
|
return documentManager.getEntityPreviewUrl(
|
||||||
|
item.id,
|
||||||
|
(item.meta?.collection as string | null) ?? null,
|
||||||
|
'inline',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveThumbnailSource(item: ViewerItem): string {
|
||||||
|
return documentManager.getEntityPreviewUrl(
|
||||||
|
item.id,
|
||||||
|
(item.meta?.collection as string | null) ?? null,
|
||||||
|
'thumbnail',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Preview shown in the info panel sidebar for the current single selection
|
||||||
|
const infoPanelPreviewUrl = computed<string | null>(() => {
|
||||||
|
const items = selection.selectedNodeArray.value
|
||||||
|
if (items.length !== 1) return null
|
||||||
|
const item = items[0]
|
||||||
|
if (!(item instanceof EntityObject)) return null
|
||||||
|
return documentManager.getEntityPreviewUrl(
|
||||||
|
nodeId(item),
|
||||||
|
item.collection ? String(item.collection) : null,
|
||||||
|
'inline',
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
function downloadViewerItem(item: ViewerItem): void {
|
function downloadViewerItem(item: ViewerItem): void {
|
||||||
documentManager.downloadEntity(item.id, (item.meta?.collection as string | null) ?? null)
|
documentManager.downloadEntity(item.id, (item.meta?.collection as string | null) ?? null)
|
||||||
}
|
}
|
||||||
@@ -782,7 +815,8 @@ onMounted(async () => {
|
|||||||
:collections="sortedItems.collections"
|
:collections="sortedItems.collections"
|
||||||
:entities="sortedItems.entities"
|
:entities="sortedItems.entities"
|
||||||
:selected-ids="selectedIds"
|
:selected-ids="selectedIds"
|
||||||
:preview-source="resolveViewerSource"
|
:preview-source="resolvePreviewSource"
|
||||||
|
:thumbnail-source="resolveThumbnailSource"
|
||||||
@item-click="handleItemClick"
|
@item-click="handleItemClick"
|
||||||
@open="handleOpenItem"
|
@open="handleOpenItem"
|
||||||
@edit="handleEditItem"
|
@edit="handleEditItem"
|
||||||
@@ -798,7 +832,8 @@ onMounted(async () => {
|
|||||||
:collections="sortedItems.collections"
|
:collections="sortedItems.collections"
|
||||||
:entities="sortedItems.entities"
|
:entities="sortedItems.entities"
|
||||||
:selected-ids="selectedIds"
|
:selected-ids="selectedIds"
|
||||||
:preview-source="resolveViewerSource"
|
:preview-source="resolvePreviewSource"
|
||||||
|
:thumbnail-source="resolveThumbnailSource"
|
||||||
@item-click="handleItemClick"
|
@item-click="handleItemClick"
|
||||||
@open="handleOpenItem"
|
@open="handleOpenItem"
|
||||||
@edit="handleEditItem"
|
@edit="handleEditItem"
|
||||||
@@ -814,7 +849,8 @@ onMounted(async () => {
|
|||||||
:collections="sortedItems.collections"
|
:collections="sortedItems.collections"
|
||||||
:entities="sortedItems.entities"
|
:entities="sortedItems.entities"
|
||||||
:selected-ids="selectedIds"
|
:selected-ids="selectedIds"
|
||||||
:preview-source="resolveViewerSource"
|
:preview-source="resolvePreviewSource"
|
||||||
|
:thumbnail-source="resolveThumbnailSource"
|
||||||
@item-click="handleItemClick"
|
@item-click="handleItemClick"
|
||||||
@open="handleOpenItem"
|
@open="handleOpenItem"
|
||||||
@edit="handleEditItem"
|
@edit="handleEditItem"
|
||||||
@@ -830,6 +866,7 @@ onMounted(async () => {
|
|||||||
v-if="hasSelection && !isMobile"
|
v-if="hasSelection && !isMobile"
|
||||||
embedded
|
embedded
|
||||||
:selected-items="selection.selectedNodeArray.value"
|
:selected-items="selection.selectedNodeArray.value"
|
||||||
|
:preview-url="infoPanelPreviewUrl"
|
||||||
@close="selection.clear()"
|
@close="selection.clear()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -838,6 +875,7 @@ onMounted(async () => {
|
|||||||
<FilesInfoPanel
|
<FilesInfoPanel
|
||||||
v-if="isMobile"
|
v-if="isMobile"
|
||||||
:selected-items="selection.selectedNodeArray.value"
|
:selected-items="selection.selectedNodeArray.value"
|
||||||
|
:preview-url="infoPanelPreviewUrl"
|
||||||
@close="selection.clear()"
|
@close="selection.clear()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user