Fix bugs, convert thumbnail to png, add context menu
This commit is contained in:
parent
c545d4b17d
commit
eb8a302222
37 changed files with 1916 additions and 137 deletions
180
frontend/src/features/library/useLibrary.ts
Normal file
180
frontend/src/features/library/useLibrary.ts
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
import { create } from 'zustand'
|
||||
import { libraryApi } from './api'
|
||||
import type { DocumentMeta } from './types'
|
||||
|
||||
interface LibraryState {
|
||||
documents: DocumentMeta[]
|
||||
total: number
|
||||
isLoading: boolean
|
||||
error: string | null
|
||||
searchQuery: string
|
||||
|
||||
// Selection
|
||||
selectedIds: Set<string>
|
||||
toggleSelection: (id: string) => void
|
||||
clearSelection: () => void
|
||||
selectAll: () => void
|
||||
|
||||
// Actions
|
||||
fetchDocuments: (query?: string) => Promise<void>
|
||||
fetchTrash: () => Promise<void>
|
||||
uploadDocument: (file: File) => Promise<DocumentMeta>
|
||||
deleteDocument: (id: string, permanent?: boolean) => Promise<void>
|
||||
restoreDocument: (id: string) => Promise<void>
|
||||
bulkDelete: (permanent?: boolean) => Promise<void>
|
||||
bulkRestore: () => Promise<void>
|
||||
emptyTrash: () => Promise<void>
|
||||
setSearchQuery: (query: string) => void
|
||||
}
|
||||
|
||||
export const useLibrary = create<LibraryState>((set, get) => ({
|
||||
documents: [],
|
||||
total: 0,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
searchQuery: '',
|
||||
selectedIds: new Set(),
|
||||
|
||||
toggleSelection: (id) => set((state) => {
|
||||
const newSelection = new Set(state.selectedIds)
|
||||
if (newSelection.has(id)) newSelection.delete(id)
|
||||
else newSelection.add(id)
|
||||
return { selectedIds: newSelection }
|
||||
}),
|
||||
|
||||
clearSelection: () => set({ selectedIds: new Set() }),
|
||||
|
||||
selectAll: () => set((state) => ({
|
||||
selectedIds: new Set(state.documents.map(d => d.id))
|
||||
})),
|
||||
|
||||
setSearchQuery: (query) => set({ searchQuery: query }),
|
||||
|
||||
fetchDocuments: async (query = '') => {
|
||||
set({ isLoading: true, error: null, searchQuery: query })
|
||||
try {
|
||||
const data = await libraryApi.getDocuments(query)
|
||||
set({ documents: data.items, total: data.total, isLoading: false })
|
||||
} catch (err: any) {
|
||||
set({ error: err.error?.message || err.message, isLoading: false })
|
||||
}
|
||||
},
|
||||
|
||||
fetchTrash: async () => {
|
||||
set({ isLoading: true, error: null, searchQuery: '' })
|
||||
try {
|
||||
const data = await libraryApi.getTrash()
|
||||
set({ documents: data.items, total: data.total, isLoading: false })
|
||||
} catch (err: any) {
|
||||
set({ error: err.error?.message || err.message, isLoading: false })
|
||||
}
|
||||
},
|
||||
|
||||
uploadDocument: async (file: File) => {
|
||||
set({ isLoading: true, error: null })
|
||||
try {
|
||||
const newDoc = await libraryApi.uploadDocument(file)
|
||||
set((state) => ({
|
||||
documents: [newDoc, ...state.documents],
|
||||
total: state.total + 1,
|
||||
isLoading: false
|
||||
}))
|
||||
return newDoc
|
||||
} catch (err: any) {
|
||||
set({ error: err.error?.message || err.message, isLoading: false })
|
||||
throw err
|
||||
}
|
||||
},
|
||||
|
||||
deleteDocument: async (id: string, permanent = false) => {
|
||||
set({ isLoading: true, error: null })
|
||||
try {
|
||||
await libraryApi.deleteDocument(id, permanent)
|
||||
set((state) => ({
|
||||
documents: state.documents.filter(d => d.id !== id),
|
||||
total: state.total - 1,
|
||||
selectedIds: new Set(Array.from(state.selectedIds).filter(sid => sid !== id)),
|
||||
isLoading: false
|
||||
}))
|
||||
} catch (err: any) {
|
||||
set({ error: err.error?.message || err.message, isLoading: false })
|
||||
throw err
|
||||
}
|
||||
},
|
||||
|
||||
restoreDocument: async (id: string) => {
|
||||
set({ isLoading: true, error: null })
|
||||
try {
|
||||
await libraryApi.restoreDocument(id)
|
||||
set((state) => ({
|
||||
documents: state.documents.filter(d => d.id !== id),
|
||||
total: state.total - 1,
|
||||
selectedIds: new Set(Array.from(state.selectedIds).filter(sid => sid !== id)),
|
||||
isLoading: false
|
||||
}))
|
||||
} catch (err: any) {
|
||||
set({ error: err.error?.message || err.message, isLoading: false })
|
||||
throw err
|
||||
}
|
||||
},
|
||||
|
||||
bulkDelete: async (permanent = false) => {
|
||||
const { selectedIds } = get()
|
||||
if (selectedIds.size === 0) return
|
||||
|
||||
set({ isLoading: true, error: null })
|
||||
try {
|
||||
if (permanent) {
|
||||
// Must delete one by one if permanent
|
||||
await Promise.all(Array.from(selectedIds).map(id => libraryApi.deleteDocument(id, true)))
|
||||
} else {
|
||||
await libraryApi.bulkDelete({ ids: Array.from(selectedIds) })
|
||||
}
|
||||
|
||||
set((state) => ({
|
||||
documents: state.documents.filter(d => !state.selectedIds.has(d.id)),
|
||||
total: state.total - state.selectedIds.size,
|
||||
selectedIds: new Set(),
|
||||
isLoading: false
|
||||
}))
|
||||
} catch (err: any) {
|
||||
set({ error: err.error?.message || err.message, isLoading: false })
|
||||
throw err
|
||||
}
|
||||
},
|
||||
|
||||
bulkRestore: async () => {
|
||||
const { selectedIds } = get()
|
||||
if (selectedIds.size === 0) return
|
||||
|
||||
set({ isLoading: true, error: null })
|
||||
try {
|
||||
await libraryApi.bulkRestore({ ids: Array.from(selectedIds) })
|
||||
set((state) => ({
|
||||
documents: state.documents.filter(d => !state.selectedIds.has(d.id)),
|
||||
total: state.total - state.selectedIds.size,
|
||||
selectedIds: new Set(),
|
||||
isLoading: false
|
||||
}))
|
||||
} catch (err: any) {
|
||||
set({ error: err.error?.message || err.message, isLoading: false })
|
||||
throw err
|
||||
}
|
||||
},
|
||||
|
||||
emptyTrash: async () => {
|
||||
set({ isLoading: true, error: null })
|
||||
try {
|
||||
await libraryApi.emptyTrash()
|
||||
set({
|
||||
documents: [],
|
||||
total: 0,
|
||||
selectedIds: new Set(),
|
||||
isLoading: false
|
||||
})
|
||||
} catch (err: any) {
|
||||
set({ error: err.error?.message || err.message, isLoading: false })
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}))
|
||||
Loading…
Add table
Add a link
Reference in a new issue