Files
documents/src/components/views/FilesListView.vue
T
Sebastian da6a407445 refactor: improvemets
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
2026-03-24 19:10:52 -04:00

103 lines
3.6 KiB
Vue

<script setup lang="ts">
import { computed } from 'vue'
import { CollectionObject } from '@DocumentsManager/models/collection'
import { EntityObject } from '@DocumentsManager/models/entity'
import { getFileIcon, formatSize } from '@/utils/fileHelpers'
import { FileActionsMenu } from '@/components'
type ItemWithType = {
item: CollectionObject | EntityObject
type: 'collection' | 'entity'
}
const props = defineProps<{
collections: CollectionObject[]
entities: EntityObject[]
selectedIds: Set<string>
}>()
const emit = defineEmits<{
'item-click': [item: CollectionObject | EntityObject, event: MouseEvent | KeyboardEvent]
'open': [item: CollectionObject | EntityObject]
'edit': [item: CollectionObject | EntityObject]
'rename': [item: CollectionObject | EntityObject]
'delete': [item: CollectionObject | EntityObject]
'download': [item: CollectionObject | EntityObject]
'show-details': [item: CollectionObject | EntityObject]
}>()
// Combine collections and entities into a single list for virtual scrolling
const allItems = computed<ItemWithType[]>(() => [
...props.collections.map(c => ({ item: c, type: 'collection' as const })),
...props.entities.map(e => ({ item: e, type: 'entity' as const }))
])
function isCollection(wrapped: ItemWithType): wrapped is { item: CollectionObject; type: 'collection' } {
return wrapped.type === 'collection'
}
</script>
<template>
<v-virtual-scroll
:items="allItems"
:item-height="56"
class="files-list-virtual pa-2"
>
<template #default="{ item: wrapped }">
<!-- Folder -->
<v-list-item
v-if="isCollection(wrapped)"
:active="selectedIds.has(String(wrapped.item.identifier))"
@click="($event: MouseEvent | KeyboardEvent) => emit('item-click', wrapped.item, $event)"
>
<template #prepend>
<v-icon color="amber-darken-2">mdi-folder</v-icon>
</template>
<v-list-item-title>{{ wrapped.item.properties.label || String(wrapped.item.identifier ?? '') }}</v-list-item-title>
<template #append>
<FileActionsMenu
:item="wrapped.item"
@open="emit('open', $event)"
@edit="emit('edit', $event)"
@rename="emit('rename', $event)"
@delete="emit('delete', $event)"
@download="emit('download', $event)"
@show-details="emit('show-details', $event)"
/>
</template>
</v-list-item>
<!-- File -->
<v-list-item
v-else
:active="selectedIds.has(String(wrapped.item.identifier))"
@click="($event: MouseEvent | KeyboardEvent) => emit('item-click', wrapped.item, $event)"
@dblclick.stop="emit('open', wrapped.item)"
>
<template #prepend>
<v-icon color="grey">{{ getFileIcon(wrapped.item as EntityObject) }}</v-icon>
</template>
<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>
<template #append>
<FileActionsMenu
:item="wrapped.item"
@open="emit('open', $event)"
@edit="emit('edit', $event)"
@rename="emit('rename', $event)"
@delete="emit('delete', $event)"
@download="emit('download', $event)"
@show-details="emit('show-details', $event)"
/>
</template>
</v-list-item>
</template>
</v-virtual-scroll>
</template>
<style scoped>
.files-list-virtual {
height: 100%;
}
</style>