feat: use resource identifiers
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
@@ -8,7 +8,7 @@ import type { Ref, ComputedRef } from 'vue'
|
||||
import { useProvidersStore } from '@/stores/providersStore'
|
||||
import { useServicesStore } from '@/stores/servicesStore'
|
||||
import { useNodesStore, ROOT_ID } from '@/stores/nodesStore'
|
||||
import type { ListFilter, ListSort, ListRange } from '@/types/common'
|
||||
import type { ListFilter, ListSort, ListRange, ServiceIdentifier, CollectionIdentifier } from '@/types/common'
|
||||
import type { DocumentInterface } from '@/types/document'
|
||||
import { CollectionObject } from '@/models/collection'
|
||||
import { EntityObject } from '@/models/entity'
|
||||
@@ -16,6 +16,9 @@ import { EntityObject } from '@/models/entity'
|
||||
// Base URL for file manager transfer endpoints
|
||||
const TRANSFER_BASE_URL = '/m/documents_manager'
|
||||
|
||||
// Number of collections+entities requested per page
|
||||
const DEFAULT_PAGE_TALLY = 64
|
||||
|
||||
export interface UseDocumentManagerOptions {
|
||||
providerId: string | Ref<string> | ComputedRef<string>
|
||||
serviceId: string | Ref<string> | ComputedRef<string>
|
||||
@@ -32,6 +35,12 @@ export function useDocumentManager(options: UseDocumentManagerOptions) {
|
||||
const currentProviderId = () => unref(providerId)
|
||||
const currentServiceId = () => unref(serviceId)
|
||||
|
||||
const currentSources = (): (ServiceIdentifier | CollectionIdentifier)[] => [
|
||||
currentLocation.value === ROOT_ID
|
||||
? `${currentProviderId()}:${currentServiceId()}`
|
||||
: `${currentProviderId()}:${currentServiceId()}:${currentLocation.value}`,
|
||||
]
|
||||
|
||||
// Current location (folder being viewed)
|
||||
const currentLocation: Ref<string> = ref(ROOT_ID)
|
||||
|
||||
@@ -39,6 +48,13 @@ export function useDocumentManager(options: UseDocumentManagerOptions) {
|
||||
const isLoading = computed(() => nodesStore.transceiving)
|
||||
const error = computed(() => nodesStore.error)
|
||||
|
||||
// Pagination state for the current location + filter + sort
|
||||
const currentFilter: Ref<ListFilter | undefined> = ref(undefined)
|
||||
const currentSort: Ref<ListSort | undefined> = ref(undefined)
|
||||
const loadedCount = ref(0)
|
||||
const hasMore = ref(false)
|
||||
const isLoadingMore = ref(false)
|
||||
|
||||
// Provider and service
|
||||
const provider = computed(() => providersStore.provider(currentProviderId()))
|
||||
const service = computed(() => servicesStore.service(currentProviderId(), currentServiceId()))
|
||||
@@ -71,7 +87,7 @@ export function useDocumentManager(options: UseDocumentManagerOptions) {
|
||||
// Navigate to a folder
|
||||
const navigateTo = async (collectionId: string | null) => {
|
||||
currentLocation.value = collectionId || ROOT_ID
|
||||
await refresh()
|
||||
await resetAndLoad(currentFilter.value, currentSort.value)
|
||||
}
|
||||
|
||||
// Navigate up one level
|
||||
@@ -90,28 +106,55 @@ export function useDocumentManager(options: UseDocumentManagerOptions) {
|
||||
await navigateTo(ROOT_ID)
|
||||
}
|
||||
|
||||
// Refresh current location
|
||||
const refresh = async (
|
||||
filter?: ListFilter,
|
||||
sort?: ListSort,
|
||||
range?: ListRange
|
||||
) => {
|
||||
await nodesStore.fetchNodes(
|
||||
currentProviderId(),
|
||||
currentServiceId(),
|
||||
currentLocation.value === ROOT_ID ? ROOT_ID : currentLocation.value,
|
||||
// Reset the current location's loaded items and (re)fetch the first page,
|
||||
// optionally with a new filter/sort (e.g. search query or sort field change)
|
||||
const resetAndLoad = async (filter?: ListFilter, sort?: ListSort) => {
|
||||
currentFilter.value = filter
|
||||
currentSort.value = sort
|
||||
loadedCount.value = 0
|
||||
hasMore.value = false
|
||||
|
||||
const range: ListRange = { type: 'tally', anchor: 'absolute', position: 0, tally: DEFAULT_PAGE_TALLY }
|
||||
const result = await nodesStore.fetchNodes(
|
||||
currentSources(),
|
||||
filter,
|
||||
sort,
|
||||
range
|
||||
range,
|
||||
'reset'
|
||||
)
|
||||
|
||||
loadedCount.value = result.collections.length + result.entities.length
|
||||
hasMore.value = !result.isLastPage
|
||||
}
|
||||
|
||||
// Fetch the next page of the current location (infinite scroll "load more")
|
||||
const loadMore = async () => {
|
||||
if (!hasMore.value || isLoadingMore.value) {
|
||||
return
|
||||
}
|
||||
|
||||
isLoadingMore.value = true
|
||||
try {
|
||||
const range: ListRange = { type: 'tally', anchor: 'absolute', position: loadedCount.value, tally: DEFAULT_PAGE_TALLY }
|
||||
const result = await nodesStore.fetchNodes(
|
||||
currentSources(),
|
||||
currentFilter.value,
|
||||
currentSort.value,
|
||||
range,
|
||||
'append'
|
||||
)
|
||||
|
||||
loadedCount.value += result.collections.length + result.entities.length
|
||||
hasMore.value = !result.isLastPage
|
||||
} finally {
|
||||
isLoadingMore.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new folder
|
||||
const createFolder = async (label: string): Promise<CollectionObject> => {
|
||||
return await nodesStore.createCollection(
|
||||
currentProviderId(),
|
||||
currentServiceId(),
|
||||
currentLocation.value === ROOT_ID ? ROOT_ID : currentLocation.value,
|
||||
`${currentProviderId()}:${currentServiceId()}:${currentLocation.value}`,
|
||||
{ label, owner: '' }
|
||||
)
|
||||
}
|
||||
@@ -132,9 +175,7 @@ export function useDocumentManager(options: UseDocumentManagerOptions) {
|
||||
}
|
||||
|
||||
return await nodesStore.createEntity(
|
||||
currentProviderId(),
|
||||
currentServiceId(),
|
||||
currentLocation.value === ROOT_ID ? ROOT_ID : currentLocation.value,
|
||||
`${currentProviderId()}:${currentServiceId()}:${currentLocation.value}`,
|
||||
properties
|
||||
)
|
||||
}
|
||||
@@ -147,7 +188,7 @@ export function useDocumentManager(options: UseDocumentManagerOptions) {
|
||||
}
|
||||
|
||||
if (node instanceof CollectionObject) {
|
||||
return await nodesStore.updateCollection(currentProviderId(), currentServiceId(), nodeId, {
|
||||
return await nodesStore.updateCollection(`${node.provider}:${node.service}:${nodeId}`, {
|
||||
label: newLabel,
|
||||
owner: node.properties.owner,
|
||||
})
|
||||
@@ -161,7 +202,7 @@ export function useDocumentManager(options: UseDocumentManagerOptions) {
|
||||
format: node.properties.format,
|
||||
encoding: node.properties.encoding,
|
||||
}
|
||||
return await nodesStore.updateEntity(currentProviderId(), currentServiceId(), node.collection, nodeId, properties)
|
||||
return await nodesStore.updateEntity(`${node.provider}:${node.service}:${node.collection || ROOT_ID}:${nodeId}`, properties)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,9 +214,9 @@ export function useDocumentManager(options: UseDocumentManagerOptions) {
|
||||
}
|
||||
|
||||
if (node instanceof CollectionObject) {
|
||||
return await nodesStore.deleteCollection(currentProviderId(), currentServiceId(), nodeId)
|
||||
return await nodesStore.deleteCollection(`${node.provider}:${node.service}:${nodeId}`)
|
||||
} else {
|
||||
return await nodesStore.deleteEntity(currentProviderId(), currentServiceId(), node.collection, nodeId)
|
||||
return await nodesStore.deleteEntity(`${node.provider}:${node.service}:${node.collection || ROOT_ID}:${nodeId}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,7 +226,7 @@ export function useDocumentManager(options: UseDocumentManagerOptions) {
|
||||
if (!node || !(node instanceof EntityObject)) {
|
||||
throw new Error('Entity not found')
|
||||
}
|
||||
return await nodesStore.readEntity(currentProviderId(), currentServiceId(), node.collection || ROOT_ID, entityId)
|
||||
return await nodesStore.readEntity(`${node.provider}:${node.service}:${node.collection || ROOT_ID}:${entityId}`)
|
||||
}
|
||||
|
||||
// Write file content
|
||||
@@ -194,7 +235,7 @@ export function useDocumentManager(options: UseDocumentManagerOptions) {
|
||||
if (!node || !(node instanceof EntityObject)) {
|
||||
throw new Error('Entity not found')
|
||||
}
|
||||
return await nodesStore.writeEntity(currentProviderId(), currentServiceId(), node.collection, entityId, content)
|
||||
return await nodesStore.writeEntity(`${node.provider}:${node.service}:${node.collection || ROOT_ID}:${entityId}`, content)
|
||||
}
|
||||
|
||||
// Get a URL suitable for inline viewing (img src / video src)
|
||||
@@ -253,7 +294,7 @@ export function useDocumentManager(options: UseDocumentManagerOptions) {
|
||||
await providersStore.list([currentProviderId()])
|
||||
await servicesStore.list()
|
||||
if (autoFetch) {
|
||||
await refresh()
|
||||
await resetAndLoad()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,6 +303,8 @@ export function useDocumentManager(options: UseDocumentManagerOptions) {
|
||||
currentLocation,
|
||||
isLoading,
|
||||
error,
|
||||
hasMore,
|
||||
isLoadingMore,
|
||||
|
||||
// Provider/Service
|
||||
provider,
|
||||
@@ -279,7 +322,8 @@ export function useDocumentManager(options: UseDocumentManagerOptions) {
|
||||
navigateTo,
|
||||
navigateUp,
|
||||
navigateToRoot,
|
||||
refresh,
|
||||
resetAndLoad,
|
||||
loadMore,
|
||||
|
||||
// Operations
|
||||
createFolder,
|
||||
|
||||
Reference in New Issue
Block a user