ajout app
This commit is contained in:
22
Voltaserve/ui/src/store/configure-store.ts
Normal file
22
Voltaserve/ui/src/store/configure-store.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { configureStore } from '@reduxjs/toolkit'
|
||||
import reducer from './reducer'
|
||||
|
||||
const store = configureStore({
|
||||
reducer,
|
||||
middleware: (getDefaultMiddleware) =>
|
||||
getDefaultMiddleware({
|
||||
serializableCheck: {
|
||||
ignoredActions: [
|
||||
'uploads/uploadAdded',
|
||||
'uploads/uploadUpdated',
|
||||
'uploads/uploadDeleted',
|
||||
],
|
||||
ignoredPaths: ['entities.uploads.items'],
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
||||
export type RootState = ReturnType<typeof store.getState>
|
||||
export type AppDispatch = typeof store.dispatch
|
||||
|
||||
export default store
|
22
Voltaserve/ui/src/store/entities/files.ts
Normal file
22
Voltaserve/ui/src/store/entities/files.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||
import { List } from '@/client/api/file'
|
||||
|
||||
type FilesState = {
|
||||
list?: List
|
||||
}
|
||||
|
||||
const initialState: FilesState = {}
|
||||
|
||||
const slice = createSlice({
|
||||
name: 'files',
|
||||
initialState,
|
||||
reducers: {
|
||||
listUpdated: (state, action: PayloadAction<List>) => {
|
||||
state.list = action.payload
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const { listUpdated } = slice.actions
|
||||
|
||||
export default slice.reducer
|
8
Voltaserve/ui/src/store/entities/index.ts
Normal file
8
Voltaserve/ui/src/store/entities/index.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { combineReducers } from 'redux'
|
||||
import files from './files'
|
||||
import uploads from './uploads'
|
||||
|
||||
export default combineReducers({
|
||||
files,
|
||||
uploads,
|
||||
})
|
141
Voltaserve/ui/src/store/entities/uploads.ts
Normal file
141
Voltaserve/ui/src/store/entities/uploads.ts
Normal file
@ -0,0 +1,141 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||
import { FileWithPath } from 'react-dropzone'
|
||||
import { newHashId } from '@/infra/id'
|
||||
|
||||
export type Upload = {
|
||||
id: string
|
||||
workspaceId: string
|
||||
parentId: string
|
||||
file: File | FileWithPath
|
||||
request?: any
|
||||
progress?: number
|
||||
error?: string
|
||||
completed: boolean
|
||||
}
|
||||
|
||||
export class UploadDecorator {
|
||||
public value: Upload
|
||||
|
||||
constructor(options: {
|
||||
id?: string
|
||||
workspaceId: string
|
||||
parentId: string
|
||||
file: File | FileWithPath
|
||||
request?: any
|
||||
progress?: number
|
||||
error?: string
|
||||
completed?: boolean
|
||||
}) {
|
||||
this.value = {
|
||||
id: newHashId(),
|
||||
completed: false,
|
||||
...options,
|
||||
}
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this.value.id
|
||||
}
|
||||
|
||||
get workspaceId(): string {
|
||||
return this.value.workspaceId
|
||||
}
|
||||
|
||||
get parentId(): string {
|
||||
return this.value.parentId
|
||||
}
|
||||
|
||||
get file(): File {
|
||||
return this.value.file
|
||||
}
|
||||
|
||||
get request(): any {
|
||||
return this.value.request
|
||||
}
|
||||
|
||||
get progress(): number | undefined {
|
||||
return this.value.progress
|
||||
}
|
||||
|
||||
get error(): string | undefined {
|
||||
return this.value.error
|
||||
}
|
||||
|
||||
get completed(): boolean {
|
||||
return this.value.completed
|
||||
}
|
||||
|
||||
get isProgressing() {
|
||||
return !this.value.completed && this.value.request
|
||||
}
|
||||
|
||||
get isPending() {
|
||||
return !this.value.completed && !this.value.request
|
||||
}
|
||||
|
||||
get isSucceeded() {
|
||||
return this.value.completed && !this.value.error
|
||||
}
|
||||
|
||||
get isFailed() {
|
||||
return this.value.completed && this.value.error
|
||||
}
|
||||
}
|
||||
|
||||
export type UploadsState = {
|
||||
items: Upload[]
|
||||
}
|
||||
|
||||
type UploadUpdateOptions = {
|
||||
id: string
|
||||
workspaceId?: string
|
||||
parentId?: string
|
||||
file?: File
|
||||
request?: any
|
||||
progress?: number
|
||||
error?: string
|
||||
completed?: boolean
|
||||
}
|
||||
|
||||
const initialState: UploadsState = {
|
||||
items: [],
|
||||
}
|
||||
|
||||
const slice = createSlice({
|
||||
name: 'uploads',
|
||||
initialState,
|
||||
reducers: {
|
||||
uploadAdded: (state, action: PayloadAction<Upload>) => {
|
||||
state.items.unshift(action.payload)
|
||||
},
|
||||
uploadUpdated: (state, action: PayloadAction<UploadUpdateOptions>) => {
|
||||
const upload = state.items.find((e) => e.id === action.payload.id)
|
||||
if (upload) {
|
||||
Object.assign(upload, action.payload)
|
||||
}
|
||||
},
|
||||
uploadCompleted: (state, action: PayloadAction<string>) => {
|
||||
const index = state.items.findIndex((e) => e.id === action.payload)
|
||||
if (index !== -1) {
|
||||
state.items[index].completed = true
|
||||
state.items.push(state.items.splice(index, 1)[0])
|
||||
}
|
||||
},
|
||||
uploadRemoved: (state, action: PayloadAction<string>) => {
|
||||
state.items = state.items.filter((e) => e.id !== action.payload)
|
||||
},
|
||||
completedUploadsCleared: (state) => {
|
||||
state.items = state.items.filter((e) => !e.completed)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const {
|
||||
uploadAdded,
|
||||
uploadUpdated,
|
||||
uploadRemoved,
|
||||
uploadCompleted,
|
||||
completedUploadsCleared,
|
||||
} = slice.actions
|
||||
|
||||
export default slice.reducer
|
5
Voltaserve/ui/src/store/hook.ts
Normal file
5
Voltaserve/ui/src/store/hook.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
|
||||
import type { RootState, AppDispatch } from './configure-store'
|
||||
|
||||
export const useAppDispatch = () => useDispatch<AppDispatch>()
|
||||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
|
8
Voltaserve/ui/src/store/reducer.ts
Normal file
8
Voltaserve/ui/src/store/reducer.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { combineReducers } from 'redux'
|
||||
import entities from './entities'
|
||||
import ui from './ui'
|
||||
|
||||
export default combineReducers({
|
||||
entities,
|
||||
ui,
|
||||
})
|
26
Voltaserve/ui/src/store/ui/error.ts
Normal file
26
Voltaserve/ui/src/store/ui/error.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||
|
||||
type ErrorState = {
|
||||
value: string | null
|
||||
}
|
||||
|
||||
const initialState: ErrorState = {
|
||||
value: null,
|
||||
}
|
||||
|
||||
const slice = createSlice({
|
||||
name: 'error',
|
||||
initialState,
|
||||
reducers: {
|
||||
errorOccurred: (state, action: PayloadAction<string>) => {
|
||||
state.value = action.payload
|
||||
},
|
||||
errorCleared: (state) => {
|
||||
state.value = null
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const { errorOccurred, errorCleared } = slice.actions
|
||||
|
||||
export default slice.reducer
|
163
Voltaserve/ui/src/store/ui/files.ts
Normal file
163
Voltaserve/ui/src/store/ui/files.ts
Normal file
@ -0,0 +1,163 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||
import { SortBy, SortOrder } from '@/client/api/file'
|
||||
import {
|
||||
loadFileSortBy,
|
||||
loadFileSortOrder,
|
||||
loadFileViewType,
|
||||
loadIconScale,
|
||||
saveFileSortBy,
|
||||
saveFileSortOrder,
|
||||
saveFileViewType,
|
||||
saveIconScale,
|
||||
} from '@/local-storage'
|
||||
import { FileViewType } from '@/types/file'
|
||||
|
||||
export const SORT_ORDER_KEY = 'voltaserve_file_sort_order'
|
||||
|
||||
export type FilesState = {
|
||||
selection: string[]
|
||||
hidden: string[]
|
||||
isMultiSelectActive: boolean
|
||||
isRangeSelectActive: boolean
|
||||
isMoveModalOpen: boolean
|
||||
isCopyModalOpen: boolean
|
||||
isCreateModalOpen: boolean
|
||||
isDeleteModalOpen: boolean
|
||||
isRenameModalOpen: boolean
|
||||
isShareModalOpen: boolean
|
||||
isSelectionMode: boolean
|
||||
iconScale: number
|
||||
sortBy: SortBy
|
||||
sortOrder: SortOrder
|
||||
viewType: FileViewType
|
||||
}
|
||||
|
||||
const initialState: FilesState = {
|
||||
selection: [],
|
||||
hidden: [],
|
||||
isMultiSelectActive: false,
|
||||
isRangeSelectActive: false,
|
||||
isMoveModalOpen: false,
|
||||
isCopyModalOpen: false,
|
||||
isCreateModalOpen: false,
|
||||
isDeleteModalOpen: false,
|
||||
isRenameModalOpen: false,
|
||||
isShareModalOpen: false,
|
||||
iconScale: loadIconScale() || 1,
|
||||
sortBy: loadFileSortBy() || SortBy.DateCreated,
|
||||
sortOrder: loadFileSortOrder() || SortOrder.Desc,
|
||||
viewType: loadFileViewType() || FileViewType.Grid,
|
||||
isSelectionMode: false,
|
||||
}
|
||||
|
||||
const slice = createSlice({
|
||||
name: 'files',
|
||||
initialState,
|
||||
reducers: {
|
||||
selectionUpdated: (state, action: PayloadAction<string[]>) => {
|
||||
state.selection = action.payload
|
||||
},
|
||||
selectionAdded: (state, action: PayloadAction<string>) => {
|
||||
state.selection.push(action.payload)
|
||||
},
|
||||
selectionRemoved: (state, action: PayloadAction<string>) => {
|
||||
state.selection = state.selection.filter((e) => e !== action.payload)
|
||||
},
|
||||
hiddenUpdated: (state, action: PayloadAction<string[]>) => {
|
||||
state.hidden = action.payload
|
||||
},
|
||||
moveModalDidOpen: (state) => {
|
||||
state.isMoveModalOpen = true
|
||||
},
|
||||
copyModalDidOpen: (state) => {
|
||||
state.isCopyModalOpen = true
|
||||
},
|
||||
createModalDidOpen: (state) => {
|
||||
state.isCreateModalOpen = true
|
||||
},
|
||||
deleteModalDidOpen: (state) => {
|
||||
state.isDeleteModalOpen = true
|
||||
},
|
||||
renameModalDidOpen: (state) => {
|
||||
state.isRenameModalOpen = true
|
||||
},
|
||||
sharingModalDidOpen: (state) => {
|
||||
state.isShareModalOpen = true
|
||||
},
|
||||
moveModalDidClose: (state) => {
|
||||
state.isMoveModalOpen = false
|
||||
},
|
||||
copyModalDidClose: (state) => {
|
||||
state.isCopyModalOpen = false
|
||||
},
|
||||
createModalDidClose: (state) => {
|
||||
state.isCreateModalOpen = false
|
||||
},
|
||||
deleteModalDidClose: (state) => {
|
||||
state.isDeleteModalOpen = false
|
||||
},
|
||||
renameModalDidClose: (state) => {
|
||||
state.isRenameModalOpen = false
|
||||
},
|
||||
sharingModalDidClose: (state) => {
|
||||
state.isShareModalOpen = false
|
||||
},
|
||||
multiSelectKeyUpdated: (state, action: PayloadAction<boolean>) => {
|
||||
state.isMultiSelectActive = action.payload
|
||||
},
|
||||
rangeSelectKeyUpdated: (state, action: PayloadAction<boolean>) => {
|
||||
state.isRangeSelectActive = action.payload
|
||||
},
|
||||
iconScaleUpdated: (state, action: PayloadAction<number>) => {
|
||||
state.iconScale = action.payload
|
||||
saveIconScale(state.iconScale)
|
||||
},
|
||||
sortByUpdated: (state, action: PayloadAction<SortBy>) => {
|
||||
state.sortBy = action.payload
|
||||
saveFileSortBy(state.sortBy)
|
||||
},
|
||||
sortOrderToggled: (state) => {
|
||||
state.sortOrder =
|
||||
state.sortOrder === SortOrder.Asc ? SortOrder.Desc : SortOrder.Asc
|
||||
saveFileSortOrder(state.sortOrder)
|
||||
},
|
||||
viewTypeToggled: (state) => {
|
||||
state.viewType =
|
||||
state.viewType === FileViewType.Grid
|
||||
? FileViewType.List
|
||||
: FileViewType.Grid
|
||||
saveFileViewType(state.viewType)
|
||||
},
|
||||
selectionModeToggled: (state) => {
|
||||
state.isSelectionMode = !state.isSelectionMode
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const {
|
||||
selectionUpdated,
|
||||
selectionAdded,
|
||||
selectionRemoved,
|
||||
hiddenUpdated,
|
||||
moveModalDidOpen,
|
||||
copyModalDidOpen,
|
||||
createModalDidOpen,
|
||||
deleteModalDidOpen,
|
||||
renameModalDidOpen,
|
||||
sharingModalDidOpen,
|
||||
moveModalDidClose,
|
||||
copyModalDidClose,
|
||||
createModalDidClose,
|
||||
deleteModalDidClose,
|
||||
renameModalDidClose,
|
||||
sharingModalDidClose,
|
||||
multiSelectKeyUpdated,
|
||||
rangeSelectKeyUpdated,
|
||||
iconScaleUpdated,
|
||||
sortByUpdated,
|
||||
sortOrderToggled,
|
||||
viewTypeToggled,
|
||||
selectionModeToggled,
|
||||
} = slice.actions
|
||||
|
||||
export default slice.reducer
|
14
Voltaserve/ui/src/store/ui/index.ts
Normal file
14
Voltaserve/ui/src/store/ui/index.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { combineReducers } from 'redux'
|
||||
import error from './error'
|
||||
import files from './files'
|
||||
import nav from './nav'
|
||||
import organizations from './organizations'
|
||||
import uploadsDrawer from './uploads-drawer'
|
||||
|
||||
export default combineReducers({
|
||||
uploadsDrawer,
|
||||
files,
|
||||
nav,
|
||||
error,
|
||||
organizations,
|
||||
})
|
30
Voltaserve/ui/src/store/ui/nav.ts
Normal file
30
Voltaserve/ui/src/store/ui/nav.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||
|
||||
type NavState = {
|
||||
active: string | null
|
||||
}
|
||||
|
||||
export enum NavType {
|
||||
Account = 'account',
|
||||
Workspaces = 'workspaces',
|
||||
Groups = 'groups',
|
||||
Organizations = 'organizations',
|
||||
}
|
||||
|
||||
const initialState: NavState = {
|
||||
active: null,
|
||||
}
|
||||
|
||||
const slice = createSlice({
|
||||
name: 'nav',
|
||||
initialState,
|
||||
reducers: {
|
||||
activeNavChanged: (state, action: PayloadAction<NavType>) => {
|
||||
state.active = action.payload
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const { activeNavChanged } = slice.actions
|
||||
|
||||
export default slice.reducer
|
26
Voltaserve/ui/src/store/ui/organizations.ts
Normal file
26
Voltaserve/ui/src/store/ui/organizations.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { createSlice } from '@reduxjs/toolkit'
|
||||
|
||||
type OrganizationsState = {
|
||||
isInviteModalOpen: boolean
|
||||
}
|
||||
|
||||
const initialState: OrganizationsState = {
|
||||
isInviteModalOpen: false,
|
||||
}
|
||||
|
||||
const slice = createSlice({
|
||||
name: 'organizations',
|
||||
initialState,
|
||||
reducers: {
|
||||
inviteModalDidOpen: (state) => {
|
||||
state.isInviteModalOpen = true
|
||||
},
|
||||
inviteModalDidClose: (state) => {
|
||||
state.isInviteModalOpen = false
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const { inviteModalDidOpen, inviteModalDidClose } = slice.actions
|
||||
|
||||
export default slice.reducer
|
26
Voltaserve/ui/src/store/ui/uploads-drawer.ts
Normal file
26
Voltaserve/ui/src/store/ui/uploads-drawer.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { createSlice } from '@reduxjs/toolkit'
|
||||
|
||||
export type UploadsDrawerState = {
|
||||
open: boolean
|
||||
}
|
||||
|
||||
const initialState: UploadsDrawerState = {
|
||||
open: false,
|
||||
}
|
||||
|
||||
const slice = createSlice({
|
||||
name: 'ui',
|
||||
initialState,
|
||||
reducers: {
|
||||
uploadsDrawerOpened: (state) => {
|
||||
state.open = true
|
||||
},
|
||||
uploadsDrawerClosed: (state) => {
|
||||
state.open = false
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export const { uploadsDrawerOpened, uploadsDrawerClosed } = slice.actions
|
||||
|
||||
export default slice.reducer
|
Reference in New Issue
Block a user