a59dbff9f1
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
136 lines
3.5 KiB
TypeScript
136 lines
3.5 KiB
TypeScript
/**
|
|
* File selection composable
|
|
* Provides reactive selection management for file manager
|
|
*/
|
|
|
|
import { ref, computed } from 'vue'
|
|
import type { Ref, ComputedRef } from 'vue'
|
|
import { CollectionObject } from '@DocumentsManager/models/collection'
|
|
import { EntityObject } from '@DocumentsManager/models/entity'
|
|
|
|
type NodeRecord = CollectionObject | EntityObject
|
|
|
|
export interface UseFileSelectionOptions {
|
|
multiple?: boolean
|
|
allowFolders?: boolean
|
|
allowFiles?: boolean
|
|
}
|
|
|
|
export function useFileSelection(options: UseFileSelectionOptions = {}) {
|
|
const {
|
|
multiple = true,
|
|
allowFolders = true,
|
|
allowFiles = true,
|
|
} = options
|
|
|
|
const selectedIds: Ref<Set<string>> = ref(new Set())
|
|
const selectedNodes: Ref<Map<string, NodeRecord>> = ref(new Map())
|
|
|
|
const count: ComputedRef<number> = computed(() => selectedIds.value.size)
|
|
const hasSelection: ComputedRef<boolean> = computed(() => selectedIds.value.size > 0)
|
|
|
|
const selectedIdArray: ComputedRef<string[]> = computed(() => Array.from(selectedIds.value))
|
|
const selectedNodeArray: ComputedRef<NodeRecord[]> = computed(() => Array.from(selectedNodes.value.values()))
|
|
|
|
const selectedCollections: ComputedRef<CollectionObject[]> = computed(() =>
|
|
selectedNodeArray.value.filter((node): node is CollectionObject => node instanceof CollectionObject),
|
|
)
|
|
|
|
const selectedEntities: ComputedRef<EntityObject[]> = computed(() =>
|
|
selectedNodeArray.value.filter((node): node is EntityObject => node instanceof EntityObject),
|
|
)
|
|
|
|
const isSelected = (nodeId: string): boolean => selectedIds.value.has(nodeId)
|
|
|
|
const isTypeAllowed = (node: NodeRecord): boolean => {
|
|
if (node instanceof CollectionObject && !allowFolders) return false
|
|
if (node instanceof EntityObject && !allowFiles) return false
|
|
return true
|
|
}
|
|
|
|
const select = (node: NodeRecord) => {
|
|
if (!isTypeAllowed(node)) return
|
|
|
|
if (!multiple) {
|
|
selectedIds.value.clear()
|
|
selectedNodes.value.clear()
|
|
}
|
|
|
|
const nodeId = String(node.identifier)
|
|
selectedIds.value.add(nodeId)
|
|
selectedNodes.value.set(nodeId, node)
|
|
}
|
|
|
|
const deselect = (nodeId: string) => {
|
|
selectedIds.value.delete(nodeId)
|
|
selectedNodes.value.delete(nodeId)
|
|
}
|
|
|
|
const toggle = (node: NodeRecord) => {
|
|
const nodeId = String(node.identifier)
|
|
if (isSelected(nodeId)) {
|
|
deselect(nodeId)
|
|
return
|
|
}
|
|
select(node)
|
|
}
|
|
|
|
const selectMultiple = (nodes: NodeRecord[]) => {
|
|
if (!multiple) {
|
|
const lastNode = nodes[nodes.length - 1]
|
|
if (lastNode && isTypeAllowed(lastNode)) {
|
|
selectedIds.value.clear()
|
|
selectedNodes.value.clear()
|
|
const nodeId = String(lastNode.identifier)
|
|
selectedIds.value.add(nodeId)
|
|
selectedNodes.value.set(nodeId, lastNode)
|
|
}
|
|
return
|
|
}
|
|
|
|
for (const node of nodes) {
|
|
if (isTypeAllowed(node)) {
|
|
const nodeId = String(node.identifier)
|
|
selectedIds.value.add(nodeId)
|
|
selectedNodes.value.set(nodeId, node)
|
|
}
|
|
}
|
|
}
|
|
|
|
const selectAll = (nodes: NodeRecord[]) => {
|
|
if (!multiple) return
|
|
selectMultiple(nodes)
|
|
}
|
|
|
|
const clear = () => {
|
|
selectedIds.value.clear()
|
|
selectedNodes.value.clear()
|
|
}
|
|
|
|
const setSelection = (nodes: NodeRecord[]) => {
|
|
clear()
|
|
selectMultiple(nodes)
|
|
}
|
|
|
|
return {
|
|
selectedIds,
|
|
selectedNodes,
|
|
count,
|
|
hasSelection,
|
|
selectedIdArray,
|
|
selectedNodeArray,
|
|
selectedCollections,
|
|
selectedEntities,
|
|
isSelected,
|
|
select,
|
|
deselect,
|
|
toggle,
|
|
selectMultiple,
|
|
selectAll,
|
|
clear,
|
|
setSelection,
|
|
}
|
|
}
|
|
|
|
export default useFileSelection
|