ajout app

This commit is contained in:
2024-04-17 20:22:30 +02:00
parent cc017cfc5e
commit f9d05a2fd3
8025 changed files with 729805 additions and 0 deletions

View 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

View 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

View File

@ -0,0 +1,8 @@
import { combineReducers } from 'redux'
import files from './files'
import uploads from './uploads'
export default combineReducers({
files,
uploads,
})

View 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

View 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

View File

@ -0,0 +1,8 @@
import { combineReducers } from 'redux'
import entities from './entities'
import ui from './ui'
export default combineReducers({
entities,
ui,
})

View 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

View 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

View 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,
})

View 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

View 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

View 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