@gentleduck/registry-ui 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +62 -0
- package/index.css +3 -0
- package/package.json +59 -0
- package/src/_old/_table/index.ts +5 -0
- package/src/_old/_table/table-advanced.constants.tsx +24 -0
- package/src/_old/_table/table-advanced.tsx +311 -0
- package/src/_old/_table/table-advanced.types.ts +272 -0
- package/src/_old/_table/table.constants.ts +2 -0
- package/src/_old/_table/table.hook.tsx +115 -0
- package/src/_old/_table/table.lib.ts +85 -0
- package/src/_old/_table/table.tsx +916 -0
- package/src/_old/_table/table.types.ts +118 -0
- package/src/_old/_table/todo.md +11 -0
- package/src/_old/_upload/index.ts +9 -0
- package/src/_old/_upload/todo.md +38 -0
- package/src/_old/_upload/upload-advanced-chunks.tsx +1624 -0
- package/src/_old/_upload/upload-advanced.tsx +507 -0
- package/src/_old/_upload/upload-sonner.tsx +58 -0
- package/src/_old/_upload/upload.assets.tsx +239 -0
- package/src/_old/_upload/upload.constants.tsx +75 -0
- package/src/_old/_upload/upload.dto.ts +19 -0
- package/src/_old/_upload/upload.lib.tsx +630 -0
- package/src/_old/_upload/upload.tsx +491 -0
- package/src/_old/_upload/upload.types.ts +436 -0
- package/src/accordion/accordion.tsx +247 -0
- package/src/accordion/index.ts +1 -0
- package/src/alert/alert.constants.ts +17 -0
- package/src/alert/alert.tsx +52 -0
- package/src/alert/index.ts +2 -0
- package/src/alert-dialog/alert-dialog.tsx +107 -0
- package/src/alert-dialog/index.ts +1 -0
- package/src/aspect-ratio/aspect-ratio.tsx +33 -0
- package/src/aspect-ratio/index.ts +1 -0
- package/src/audio/audio-record.tsx +776 -0
- package/src/audio/audio-visualizer.tsx +377 -0
- package/src/audio/audio.libs.ts +5 -0
- package/src/audio/audio.types.ts +50 -0
- package/src/audio/index.ts +2 -0
- package/src/avatar/avatar.tsx +78 -0
- package/src/avatar/index.ts +1 -0
- package/src/badge/badge.constants.ts +38 -0
- package/src/badge/badge.tsx +19 -0
- package/src/badge/index.ts +2 -0
- package/src/breadcrumb/breadcrumb.tsx +119 -0
- package/src/breadcrumb/index.ts +1 -0
- package/src/button/button.constants.ts +44 -0
- package/src/button/button.tsx +79 -0
- package/src/button/button.types.ts +38 -0
- package/src/button/index.ts +3 -0
- package/src/button-group/button-group.constants.ts +26 -0
- package/src/button-group/button-group.tsx +65 -0
- package/src/button-group/index.ts +2 -0
- package/src/calendar/calendar.tsx +191 -0
- package/src/calendar/index.ts +1 -0
- package/src/card/card.tsx +81 -0
- package/src/card/index.ts +1 -0
- package/src/carousel/carousel.tsx +211 -0
- package/src/carousel/carousel.types.ts +23 -0
- package/src/carousel/index.ts +2 -0
- package/src/chart/chart.libs.ts +27 -0
- package/src/chart/chart.tsx +260 -0
- package/src/chart/chart.types.ts +38 -0
- package/src/chart/index.ts +3 -0
- package/src/checkbox/checkbox.tsx +144 -0
- package/src/checkbox/checkbox.types.ts +24 -0
- package/src/checkbox/index.ts +2 -0
- package/src/collapsible/collapsible.tsx +151 -0
- package/src/collapsible/index.ts +1 -0
- package/src/combobox/combobox.tsx +132 -0
- package/src/combobox/index.ts +1 -0
- package/src/command/command.tsx +192 -0
- package/src/command/command.types.ts +11 -0
- package/src/command/index.ts +2 -0
- package/src/context-menu/context-menu.tsx +178 -0
- package/src/context-menu/index.ts +1 -0
- package/src/dialog/dialog-responsive.tsx +137 -0
- package/src/dialog/dialog.tsx +97 -0
- package/src/dialog/index.ts +2 -0
- package/src/direction/direction.tsx +13 -0
- package/src/direction/index.ts +1 -0
- package/src/drawer/drawer.tsx +185 -0
- package/src/drawer/index.ts +1 -0
- package/src/dropdown-menu/dropdown-menu.tsx +181 -0
- package/src/dropdown-menu/index.ts +1 -0
- package/src/empty/empty.constants.ts +15 -0
- package/src/empty/empty.tsx +73 -0
- package/src/empty/index.ts +2 -0
- package/src/field/field.constants.ts +22 -0
- package/src/field/field.tsx +203 -0
- package/src/field/index.ts +2 -0
- package/src/hover-card/hover-card.tsx +79 -0
- package/src/hover-card/index.ts +1 -0
- package/src/input/index.ts +1 -0
- package/src/input/input.tsx +45 -0
- package/src/input-group/index.ts +1 -0
- package/src/input-group/input-group.tsx +170 -0
- package/src/input-otp/index.ts +1 -0
- package/src/input-otp/input-otp.tsx +66 -0
- package/src/item/index.ts +2 -0
- package/src/item/item.constants.ts +22 -0
- package/src/item/item.tsx +185 -0
- package/src/json-editor/index.ts +4 -0
- package/src/json-editor/json-editor.hooks.ts +21 -0
- package/src/json-editor/json-editor.libs.ts +34 -0
- package/src/json-editor/json-editor.tsx +425 -0
- package/src/json-editor/json-editor.types.ts +80 -0
- package/src/json-editor/json-editor.view.tsx +110 -0
- package/src/json-editor/json-text-area.tsx +7 -0
- package/src/kbd/index.ts +1 -0
- package/src/kbd/kbd.tsx +39 -0
- package/src/label/index.ts +1 -0
- package/src/label/label.tsx +28 -0
- package/src/menubar/index.ts +1 -0
- package/src/menubar/menubar.tsx +213 -0
- package/src/navigation-menu/index.ts +1 -0
- package/src/navigation-menu/navigation-menu.tsx +152 -0
- package/src/pagination/index.ts +2 -0
- package/src/pagination/pagination.tsx +191 -0
- package/src/pagination/pagination.types.ts +17 -0
- package/src/popover/index.ts +1 -0
- package/src/popover/popover.tsx +35 -0
- package/src/preview-panel/index.ts +3 -0
- package/src/preview-panel/preview-panel-dialog.tsx +99 -0
- package/src/preview-panel/preview-panel.tsx +389 -0
- package/src/preview-panel/preview-panel.types.ts +49 -0
- package/src/progress/index.ts +1 -0
- package/src/progress/progress.tsx +32 -0
- package/src/radio-group/index.ts +1 -0
- package/src/radio-group/radio-group.tsx +92 -0
- package/src/resizable/index.ts +1 -0
- package/src/resizable/resizable.tsx +52 -0
- package/src/scroll-area/index.ts +1 -0
- package/src/scroll-area/scroll-area.tsx +30 -0
- package/src/select/index.ts +1 -0
- package/src/select/select.tsx +138 -0
- package/src/separator/index.ts +1 -0
- package/src/separator/separator.tsx +28 -0
- package/src/sheet/index.ts +2 -0
- package/src/sheet/sheet.constants.tsx +20 -0
- package/src/sheet/sheet.tsx +92 -0
- package/src/sidebar/index.ts +4 -0
- package/src/sidebar/sidebar.constants.ts +30 -0
- package/src/sidebar/sidebar.hooks.ts +13 -0
- package/src/sidebar/sidebar.tsx +676 -0
- package/src/sidebar/sidebar.types.ts +28 -0
- package/src/skeleton/index.ts +1 -0
- package/src/skeleton/skeleton.tsx +22 -0
- package/src/slider/index.ts +1 -0
- package/src/slider/slider.tsx +57 -0
- package/src/sonner/index.ts +4 -0
- package/src/sonner/sonner.chunks.tsx +80 -0
- package/src/sonner/sonner.libs.ts +13 -0
- package/src/sonner/sonner.tsx +31 -0
- package/src/sonner/sonner.types.ts +9 -0
- package/src/switch/index.ts +1 -0
- package/src/switch/switch.tsx +63 -0
- package/src/table/index.ts +1 -0
- package/src/table/table.tsx +95 -0
- package/src/tabs/index.ts +1 -0
- package/src/tabs/tabs.tsx +151 -0
- package/src/textarea/index.ts +1 -0
- package/src/textarea/textarea.tsx +24 -0
- package/src/toggle/index.ts +2 -0
- package/src/toggle/toggle.constants.ts +22 -0
- package/src/toggle/toggle.tsx +24 -0
- package/src/toggle-group/index.ts +1 -0
- package/src/toggle-group/toggle-group.tsx +69 -0
- package/src/tooltip/index.ts +1 -0
- package/src/tooltip/tooltip.tsx +32 -0
- package/src/upload/index.ts +1 -0
- package/src/upload/upload.constants.tsx +19 -0
- package/src/upload/upload.libs.ts +97 -0
- package/src/upload/upload.tsx +340 -0
- package/src/upload/upload.types.ts +44 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,630 @@
|
|
|
1
|
+
// //@ts-nocheck
|
|
2
|
+
// import { toast } from 'sonner'
|
|
3
|
+
// import {
|
|
4
|
+
// HandleAttachmentProps,
|
|
5
|
+
// SelectedFoldersType,
|
|
6
|
+
// UploadFilesArgs,
|
|
7
|
+
// UploadPromiseArgs,
|
|
8
|
+
// UploadPromiseReturn,
|
|
9
|
+
// } from './upload.types'
|
|
10
|
+
// import { uuidv7 } from 'uuidv7'
|
|
11
|
+
// import React from 'react'
|
|
12
|
+
// import { UploadSonnerContent, UploadSonnerContentMemo } from './upload-sonner'
|
|
13
|
+
// import { FileTypeEnum, MAX_FILE_SIZE } from './upload.constants'
|
|
14
|
+
// import { BucketFilesType, BucketFoldersType } from '../../../../upload-api/src/globals'
|
|
15
|
+
//
|
|
16
|
+
// export const uploadPromise = ({ files, toastId }: UploadPromiseArgs): Promise<UploadPromiseReturn> => {
|
|
17
|
+
// return new Promise(resolve => {
|
|
18
|
+
// let currentProgress = 0
|
|
19
|
+
// const remainingTime = getRemainingTime(currentProgress, 100)
|
|
20
|
+
//
|
|
21
|
+
// // Show initial toast loading message
|
|
22
|
+
// toast.loading(
|
|
23
|
+
// <UploadSonnerContentMemo
|
|
24
|
+
// progress={currentProgress}
|
|
25
|
+
// remainingTime={remainingTime}
|
|
26
|
+
// files={files}
|
|
27
|
+
// />,
|
|
28
|
+
// { id: toastId }
|
|
29
|
+
// )
|
|
30
|
+
//
|
|
31
|
+
// // Simulate progress update with interval
|
|
32
|
+
// const intervalId = setInterval(() => {
|
|
33
|
+
// currentProgress += Math.floor(Math.random() * 10) + 1
|
|
34
|
+
// if (currentProgress > 100) currentProgress = 100
|
|
35
|
+
//
|
|
36
|
+
// // Update toast content with the new progress and remaining time
|
|
37
|
+
// toast.loading(
|
|
38
|
+
// <UploadSonnerContentMemo
|
|
39
|
+
// progress={currentProgress}
|
|
40
|
+
// remainingTime={remainingTime}
|
|
41
|
+
// files={files}
|
|
42
|
+
// />,
|
|
43
|
+
// { id: toastId }
|
|
44
|
+
// )
|
|
45
|
+
//
|
|
46
|
+
// // Resolve the promise once progress reaches 100%
|
|
47
|
+
// if (currentProgress >= 100) {
|
|
48
|
+
// clearInterval(intervalId)
|
|
49
|
+
// resolve({ progress: currentProgress, files, remainingTime, message: 'Upload complete', toastId })
|
|
50
|
+
// }
|
|
51
|
+
// }, 20)
|
|
52
|
+
// })
|
|
53
|
+
// }
|
|
54
|
+
//
|
|
55
|
+
// export type FolderOpenArgs = {
|
|
56
|
+
// attachmentFolder: BucketFoldersType
|
|
57
|
+
// setSelected: React.Dispatch<React.SetStateAction<SelectedFoldersType>>
|
|
58
|
+
// exist_in_tree: boolean
|
|
59
|
+
// }
|
|
60
|
+
//
|
|
61
|
+
// export function folderOpen({ attachmentFolder, setSelected, exist_in_tree }: FolderOpenArgs) {
|
|
62
|
+
// setSelected(prev => {
|
|
63
|
+
// // if (!exist_in_tree)
|
|
64
|
+
// // return [...prev.filter(item => !(item.tree_level >= attachmentFolder.tree_level) && item), attachmentFolder]
|
|
65
|
+
// // return prev.filter(item => !(item.tree_level >= attachmentFolder.tree_level))
|
|
66
|
+
// })
|
|
67
|
+
// }
|
|
68
|
+
//
|
|
69
|
+
// // Helper function to calculate remaining time
|
|
70
|
+
// export function getRemainingTime(currentProgress: number, maxProgress: number) {
|
|
71
|
+
// const progressPercentage = (currentProgress / maxProgress) * 100
|
|
72
|
+
// const calculatedRemainingTime = 200 - progressPercentage * 2
|
|
73
|
+
// return calculatedRemainingTime > 0 ? calculatedRemainingTime : 0
|
|
74
|
+
// }
|
|
75
|
+
//
|
|
76
|
+
// export async function advancedUploadAttachments(props: UploadFilesArgs) {
|
|
77
|
+
// const { e, actions, ..._props } = props
|
|
78
|
+
//
|
|
79
|
+
// try {
|
|
80
|
+
// const files = e.currentTarget.files
|
|
81
|
+
//
|
|
82
|
+
// if (!files?.length)
|
|
83
|
+
// return toast.error('Please select a file', {
|
|
84
|
+
// position: 'top-right',
|
|
85
|
+
// })
|
|
86
|
+
//
|
|
87
|
+
// const newAttachments: InsertFileType[] = []
|
|
88
|
+
//
|
|
89
|
+
// for (let i = 0; i < files.length; i++) {
|
|
90
|
+
// const file = files[i]
|
|
91
|
+
//
|
|
92
|
+
// if (!file) return
|
|
93
|
+
//
|
|
94
|
+
// if (file.size > MAX_FILE_SIZE) {
|
|
95
|
+
// toast.error(`File has exceeded the max size: ${file.name.slice(0, 15)}...`, { position: 'top-right' })
|
|
96
|
+
// continue // Skip this file and continue with the next
|
|
97
|
+
// }
|
|
98
|
+
//
|
|
99
|
+
// const attachment: InsertFileType = {
|
|
100
|
+
// id: uuidv7(),
|
|
101
|
+
// name: file.name,
|
|
102
|
+
// type: file.type,
|
|
103
|
+
// size: file.size,
|
|
104
|
+
// file: await toBase64(file),
|
|
105
|
+
// tree_level: _props.selectedFolder.length
|
|
106
|
+
// ? (_props.selectedFolder[_props.selectedFolder.length - 1]?.tree_level ?? 0 + 1)
|
|
107
|
+
// : 1,
|
|
108
|
+
// bucket_id: '01947739-b98e-78da-bae0-0b9f9278598d',
|
|
109
|
+
// folder_id: '01947739-b994-7db2-b4ce-e9a65d188c80',
|
|
110
|
+
// }
|
|
111
|
+
//
|
|
112
|
+
// newAttachments.push(attachment)
|
|
113
|
+
// }
|
|
114
|
+
//
|
|
115
|
+
// // random id
|
|
116
|
+
// const toastId = uuidv7()
|
|
117
|
+
//
|
|
118
|
+
// // Upload promise
|
|
119
|
+
// const files_response = await actions.upload(newAttachments, _props)
|
|
120
|
+
// if (!files_response.data) return toast.error('Upload failed. Please try again.', { position: 'top-right' })
|
|
121
|
+
// const promise = await uploadPromise({ files: files.length, toastId })
|
|
122
|
+
//
|
|
123
|
+
// // Show upload progress toast
|
|
124
|
+
// promise &&
|
|
125
|
+
// toast.success(`Successfully Uploaded ${files.length} file${files.length > 1 ? 's' : ''}`, {
|
|
126
|
+
// duration: 2000,
|
|
127
|
+
// position: 'top-right',
|
|
128
|
+
// id: toastId,
|
|
129
|
+
// })
|
|
130
|
+
//
|
|
131
|
+
// _props.setAttachments(old => {
|
|
132
|
+
// if (_props.selectedFolder.length > 0) {
|
|
133
|
+
// const selectedFolderId = _props.selectedFolder[_props.selectedFolder.length - 1]?.id ?? ''
|
|
134
|
+
// // Update the attachments recursively
|
|
135
|
+
// return updateFolderContent(
|
|
136
|
+
// old,
|
|
137
|
+
// selectedFolderId,
|
|
138
|
+
// files_response.data as unknown as (BucketFilesType | BucketFoldersType)[]
|
|
139
|
+
// )
|
|
140
|
+
// }
|
|
141
|
+
//
|
|
142
|
+
// // If no folder is selected, just add new attachments to the old attachments
|
|
143
|
+
// return [...old, ...files_response.data]
|
|
144
|
+
// })
|
|
145
|
+
//
|
|
146
|
+
// // Clear the input
|
|
147
|
+
// e.target.value = ''
|
|
148
|
+
// } catch (error) {
|
|
149
|
+
// console.log(error)
|
|
150
|
+
// toast.error('Upload failed. Please try again.', { position: 'top-right' })
|
|
151
|
+
// }
|
|
152
|
+
// }
|
|
153
|
+
//
|
|
154
|
+
// export function updateFolderContent<T extends BucketFilesType | BucketFoldersType>(
|
|
155
|
+
// array: T[],
|
|
156
|
+
// folderId: string,
|
|
157
|
+
// newAttachments: T[]
|
|
158
|
+
// ): T[] {
|
|
159
|
+
// return array.map(item => {
|
|
160
|
+
// // If the current item is the folder we need to update
|
|
161
|
+
// if (item.id === folderId) {
|
|
162
|
+
// return {
|
|
163
|
+
// ...item,
|
|
164
|
+
// content: [...(item as BucketFoldersType).content, ...newAttachments],
|
|
165
|
+
// }
|
|
166
|
+
// }
|
|
167
|
+
//
|
|
168
|
+
// // If the current item contains nested folders, recursively call the function to go deeper
|
|
169
|
+
// if (Array.isArray((item as BucketFoldersType).content)) {
|
|
170
|
+
// return {
|
|
171
|
+
// ...item,
|
|
172
|
+
// content: updateFolderContent((item as BucketFoldersType).content, folderId, newAttachments),
|
|
173
|
+
// }
|
|
174
|
+
// }
|
|
175
|
+
//
|
|
176
|
+
// // If the item is not the folder and doesn't have nested folders, return it unchanged
|
|
177
|
+
// return item
|
|
178
|
+
// })
|
|
179
|
+
// }
|
|
180
|
+
//
|
|
181
|
+
// export function formatTime(seconds: number) {
|
|
182
|
+
// const days = Math.floor(seconds / (24 * 3600))
|
|
183
|
+
// seconds %= 24 * 3600
|
|
184
|
+
// const hours = Math.floor(seconds / 3600)
|
|
185
|
+
// seconds %= 3600
|
|
186
|
+
// const minutes = Math.floor(seconds / 60)
|
|
187
|
+
// seconds = Math.floor(seconds % 60)
|
|
188
|
+
//
|
|
189
|
+
// if (days > 0) return `${days}d `
|
|
190
|
+
// if (hours > 0) return `${hours}h `
|
|
191
|
+
// if (minutes > 0) return `${minutes}m `
|
|
192
|
+
// return `${seconds}s`
|
|
193
|
+
// }
|
|
194
|
+
//
|
|
195
|
+
// export const getFileType = (type: string): FileTypeEnum => {
|
|
196
|
+
// if (!type) return FileTypeEnum.Unknown
|
|
197
|
+
// if (type.startsWith('audio/')) return FileTypeEnum.Audio
|
|
198
|
+
// if (type.startsWith('text/')) return FileTypeEnum.Text
|
|
199
|
+
// if (type.startsWith('image/')) return FileTypeEnum.Image
|
|
200
|
+
// if (type.startsWith('video/')) return FileTypeEnum.Video
|
|
201
|
+
// if (type.startsWith('application/pdf')) return FileTypeEnum.Pdf
|
|
202
|
+
// return FileTypeEnum.Unknown
|
|
203
|
+
// }
|
|
204
|
+
//
|
|
205
|
+
// export const getAttachmentsToState = ({ e, setAttachmentsState }: HandleAttachmentProps) => {
|
|
206
|
+
// const files = e.currentTarget.files
|
|
207
|
+
//
|
|
208
|
+
// if (!files) return toast.error('Please select a file')
|
|
209
|
+
//
|
|
210
|
+
// const newAttachments: BucketFilesType[] = []
|
|
211
|
+
//
|
|
212
|
+
// for (let i = 0; i < files.length; i++) {
|
|
213
|
+
// const file = files[i]
|
|
214
|
+
//
|
|
215
|
+
// // if (file.size > 10 * 1024 * 1024) {
|
|
216
|
+
// // toast.error(`File has exceeded the max size: ${file.name.slice(0, 15)}...`)
|
|
217
|
+
// // continue // Skip this file and continue with the next
|
|
218
|
+
// // }
|
|
219
|
+
//
|
|
220
|
+
// const attachment: BucketFilesType = {
|
|
221
|
+
// id: uuidv7(),
|
|
222
|
+
// file: file,
|
|
223
|
+
// name: file.name,
|
|
224
|
+
// url: null,
|
|
225
|
+
// type: file.type,
|
|
226
|
+
// size: file.size.toString(),
|
|
227
|
+
// created_at: new Date(),
|
|
228
|
+
// updated_at: new Date(),
|
|
229
|
+
// }
|
|
230
|
+
//
|
|
231
|
+
// newAttachments.push(attachment)
|
|
232
|
+
// }
|
|
233
|
+
//
|
|
234
|
+
// setAttachmentsState(prev => [...prev, ...newAttachments])
|
|
235
|
+
// e.currentTarget.value = ''
|
|
236
|
+
// }
|
|
237
|
+
//
|
|
238
|
+
// export const handleAdvancedAttachment = ({ e, setAttachmentsState }: HandleAttachmentProps) => {
|
|
239
|
+
// const files = e.currentTarget.files
|
|
240
|
+
//
|
|
241
|
+
// if (!files)
|
|
242
|
+
// return toast.error('Please select a file', {
|
|
243
|
+
// position: 'top-right',
|
|
244
|
+
// })
|
|
245
|
+
//
|
|
246
|
+
// const newAttachments: BucketFilesType[] = []
|
|
247
|
+
//
|
|
248
|
+
// for (let i = 0; i < files.length; i++) {
|
|
249
|
+
// const file = files[i]
|
|
250
|
+
//
|
|
251
|
+
// // if (file.size > 10 * 1024 * 1024) {
|
|
252
|
+
// // toast.error(`File has exceeded the max size: ${file.name.slice(0, 15)}...`)
|
|
253
|
+
// // continue // Skip this file and continue with the next
|
|
254
|
+
// // }
|
|
255
|
+
//
|
|
256
|
+
// const attachment: BucketFilesType = {
|
|
257
|
+
// id: uuidv7(),
|
|
258
|
+
// file: file,
|
|
259
|
+
// name: file.name,
|
|
260
|
+
// url: null,
|
|
261
|
+
// type: file.type,
|
|
262
|
+
// size: file.size.toString(),
|
|
263
|
+
// created_at: new Date(),
|
|
264
|
+
// updated_at: new Date(),
|
|
265
|
+
// tree_level: 1,
|
|
266
|
+
// }
|
|
267
|
+
//
|
|
268
|
+
// newAttachments.push(attachment)
|
|
269
|
+
// }
|
|
270
|
+
//
|
|
271
|
+
// setAttachmentsState(prev => [...prev, ...newAttachments])
|
|
272
|
+
// e.currentTarget.value = ''
|
|
273
|
+
// }
|
|
274
|
+
//
|
|
275
|
+
// /**
|
|
276
|
+
// * Deep merge two objects, recursively merging properties.
|
|
277
|
+
// * - Handles arrays, objects, and primitive values.
|
|
278
|
+
// * - Ensures immutability by not mutating the original target object.
|
|
279
|
+
// *
|
|
280
|
+
// * @param target - The target object.
|
|
281
|
+
// * @param source - The source object.
|
|
282
|
+
// * @returns A new object with merged properties.
|
|
283
|
+
// */
|
|
284
|
+
// export const deepMerge = <T extends Record<string, any>>(target: T, source: Partial<T>): T => {
|
|
285
|
+
// // Create a new object to avoid mutating the original target
|
|
286
|
+
// const output = { ...target }
|
|
287
|
+
//
|
|
288
|
+
// for (const key in source) {
|
|
289
|
+
// if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
290
|
+
// const targetValue = target[key]
|
|
291
|
+
// const sourceValue = source[key]
|
|
292
|
+
//
|
|
293
|
+
// // Check if both target and source are objects, and not null
|
|
294
|
+
// if (isObject(targetValue) && isObject(sourceValue)) {
|
|
295
|
+
// // Recursively merge the objects
|
|
296
|
+
// output[key] = deepMerge(targetValue, sourceValue as Partial<T[Extract<keyof T, string>] & Record<string, any>>)
|
|
297
|
+
// } else {
|
|
298
|
+
// // Otherwise, directly assign the source value (includes arrays and primitives)
|
|
299
|
+
// output[key] = sourceValue as T[Extract<keyof T, string>]
|
|
300
|
+
// }
|
|
301
|
+
// }
|
|
302
|
+
// }
|
|
303
|
+
//
|
|
304
|
+
// return output
|
|
305
|
+
// }
|
|
306
|
+
//
|
|
307
|
+
// /**
|
|
308
|
+
// * Helper function to check if a value is a plain object (and not an array or null).
|
|
309
|
+
// *
|
|
310
|
+
// * @param value - The value to check.
|
|
311
|
+
// * @returns Whether the value is a plain object.
|
|
312
|
+
// */
|
|
313
|
+
// const isObject = (value: any): value is Record<string, any> => {
|
|
314
|
+
// return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
315
|
+
// }
|
|
316
|
+
//
|
|
317
|
+
// export function addFolderToPath({
|
|
318
|
+
// selectedFolder,
|
|
319
|
+
// setAttachments,
|
|
320
|
+
// setSelectedFolder,
|
|
321
|
+
// folderName,
|
|
322
|
+
// }: {
|
|
323
|
+
// selectedFolder: BucketFoldersType[]
|
|
324
|
+
// setSelectedFolder: React.Dispatch<React.SetStateAction<BucketFoldersType[]>>
|
|
325
|
+
// setAttachments: React.Dispatch<React.SetStateAction<(BucketFilesType | BucketFoldersType)[]>>
|
|
326
|
+
// folderName: string
|
|
327
|
+
// }) {
|
|
328
|
+
// const emptyFolder: BucketFoldersType = {
|
|
329
|
+
// id: Math.random().toString(36).slice(2),
|
|
330
|
+
// name: folderName,
|
|
331
|
+
// content: [],
|
|
332
|
+
// created_at: new Date(),
|
|
333
|
+
// updated_at: new Date(),
|
|
334
|
+
// tree_level: selectedFolder.length ? selectedFolder[selectedFolder.length - 1].tree_level + 1 : 1,
|
|
335
|
+
// }
|
|
336
|
+
//
|
|
337
|
+
// const addToFolderTree = (
|
|
338
|
+
// items: (BucketFilesType | BucketFoldersType)[],
|
|
339
|
+
// selectedId: string
|
|
340
|
+
// ): (BucketFilesType | BucketFoldersType)[] => {
|
|
341
|
+
// return items.map(item => {
|
|
342
|
+
// if ('content' in item && item.id === selectedId) {
|
|
343
|
+
// return {
|
|
344
|
+
// ...item,
|
|
345
|
+
// content: [...item.content, emptyFolder],
|
|
346
|
+
// updated_at: new Date(),
|
|
347
|
+
// }
|
|
348
|
+
// } else if ('content' in item) {
|
|
349
|
+
// return {
|
|
350
|
+
// ...item,
|
|
351
|
+
// content: addToFolderTree(item.content, selectedId),
|
|
352
|
+
// }
|
|
353
|
+
// }
|
|
354
|
+
// return item
|
|
355
|
+
// })
|
|
356
|
+
// }
|
|
357
|
+
//
|
|
358
|
+
// const updateSelectedFolder = (
|
|
359
|
+
// selectedFolder: BucketFoldersType[],
|
|
360
|
+
// emptyFolder: BucketFoldersType
|
|
361
|
+
// ): BucketFoldersType[] => {
|
|
362
|
+
// return selectedFolder.map((folder, index) => {
|
|
363
|
+
// if (index === selectedFolder.length - 1) {
|
|
364
|
+
// // Update the most deeply selected folder
|
|
365
|
+
// return {
|
|
366
|
+
// ...folder,
|
|
367
|
+
// content: [...folder.content, emptyFolder],
|
|
368
|
+
// updated_at: new Date(),
|
|
369
|
+
// }
|
|
370
|
+
// }
|
|
371
|
+
// return folder
|
|
372
|
+
// })
|
|
373
|
+
// }
|
|
374
|
+
//
|
|
375
|
+
// setAttachments(oldAttachments => {
|
|
376
|
+
// if (!selectedFolder.length) {
|
|
377
|
+
// // Add folder to root level if no folder is selected
|
|
378
|
+
// return [...oldAttachments, emptyFolder]
|
|
379
|
+
// }
|
|
380
|
+
//
|
|
381
|
+
// // Use the ID of the most deeply selected folder
|
|
382
|
+
// const selectedId = selectedFolder[selectedFolder.length - 1].id
|
|
383
|
+
// return addToFolderTree(oldAttachments, selectedId)
|
|
384
|
+
// })
|
|
385
|
+
//
|
|
386
|
+
// setSelectedFolder(oldSelectedFolder => {
|
|
387
|
+
// if (!selectedFolder.length) {
|
|
388
|
+
// // If no folder is selected, keep the selected folder unchanged
|
|
389
|
+
// return oldSelectedFolder
|
|
390
|
+
// }
|
|
391
|
+
// return updateSelectedFolder(oldSelectedFolder, emptyFolder)
|
|
392
|
+
// })
|
|
393
|
+
//
|
|
394
|
+
// toast.info('Folder added successfully!')
|
|
395
|
+
// }
|
|
396
|
+
//
|
|
397
|
+
// export function searchAttachmentsByKey<T>(array: T[], predicate: (item: T) => boolean, key: string): T | null {
|
|
398
|
+
// for (const item of array) {
|
|
399
|
+
// // Check if the current item satisfies the predicate for the specified key
|
|
400
|
+
// if (predicate(item)) {
|
|
401
|
+
// return item // Return the item directly if the predicate matches
|
|
402
|
+
// }
|
|
403
|
+
//
|
|
404
|
+
// // If the item has the specified key and it's an array, search the nested array
|
|
405
|
+
// if (Array.isArray(item[key as keyof T])) {
|
|
406
|
+
// const nestedResult = searchAttachmentsByKey(item[key as keyof T] as T[], predicate, key)
|
|
407
|
+
// if (nestedResult) {
|
|
408
|
+
// return nestedResult // Return the exact object found within the nested structure
|
|
409
|
+
// }
|
|
410
|
+
// }
|
|
411
|
+
// }
|
|
412
|
+
//
|
|
413
|
+
// return null // Return null if no match is found
|
|
414
|
+
// }
|
|
415
|
+
//
|
|
416
|
+
// /**
|
|
417
|
+
// * Recursively deletes folders by an array of IDs, including all their nested content.
|
|
418
|
+
// * @param attachments The list of folders or attachments.
|
|
419
|
+
// * @param targetIds The array of IDs of the folders to delete.
|
|
420
|
+
// * @returns Updated folder structure with the target folders and their nested content removed.
|
|
421
|
+
// */
|
|
422
|
+
// export function deleteAttachmentById<T extends BucketFilesType | BucketFoldersType>(
|
|
423
|
+
// attachments: T[],
|
|
424
|
+
// targetIds: string[]
|
|
425
|
+
// ): T[] {
|
|
426
|
+
// return attachments
|
|
427
|
+
// .filter(attachment => !targetIds.includes(attachment.id)) // Remove target folders at this level
|
|
428
|
+
// .map(attachment => {
|
|
429
|
+
// if ((attachment as BucketFoldersType).content) {
|
|
430
|
+
// // Recursively check and clean nested content
|
|
431
|
+
// return {
|
|
432
|
+
// ...attachment,
|
|
433
|
+
// content: deleteAttachmentById((attachment as BucketFoldersType).content, targetIds),
|
|
434
|
+
// }
|
|
435
|
+
// }
|
|
436
|
+
// return attachment // Return folder if no nested content
|
|
437
|
+
// })
|
|
438
|
+
// }
|
|
439
|
+
//
|
|
440
|
+
// /**
|
|
441
|
+
// * Recursively renames folders or files by their IDs.
|
|
442
|
+
// * @param attachments The list of folders or attachments.
|
|
443
|
+
// * @param targetIds The array of IDs of the folders or files to rename.
|
|
444
|
+
// * @param newName The new name for the target folders or files.
|
|
445
|
+
// * @returns Updated folder structure with the renamed items.
|
|
446
|
+
// */
|
|
447
|
+
// export function renameAttachmentById<T extends BucketFilesType | BucketFoldersType>(
|
|
448
|
+
// attachments: T[],
|
|
449
|
+
// targetIds: string[],
|
|
450
|
+
// newName: string
|
|
451
|
+
// ): T[] {
|
|
452
|
+
// return attachments.map(attachment => {
|
|
453
|
+
// if (targetIds.includes(attachment.id)) {
|
|
454
|
+
// // Rename the folder or file
|
|
455
|
+
// return { ...attachment, name: newName, updated_at: new Date() }
|
|
456
|
+
// }
|
|
457
|
+
// if ((attachment as BucketFoldersType).content) {
|
|
458
|
+
// // Recursively check and rename nested content
|
|
459
|
+
// return {
|
|
460
|
+
// ...attachment,
|
|
461
|
+
// content: renameAttachmentById((attachment as BucketFoldersType).content, targetIds, newName),
|
|
462
|
+
// }
|
|
463
|
+
// }
|
|
464
|
+
// return attachment // Return folder if no match
|
|
465
|
+
// })
|
|
466
|
+
// }
|
|
467
|
+
//
|
|
468
|
+
// export const moveAttachmentsToPath = ({
|
|
469
|
+
// setAttachments,
|
|
470
|
+
// setSelectedAttachment,
|
|
471
|
+
// selectedAttachments,
|
|
472
|
+
// path,
|
|
473
|
+
// }: {
|
|
474
|
+
// setAttachments: React.Dispatch<React.SetStateAction<(BucketFilesType | BucketFoldersType)[]>>
|
|
475
|
+
// setSelectedAttachment: React.Dispatch<React.SetStateAction<BucketFilesType[]>>
|
|
476
|
+
// selectedAttachments: BucketFilesType[]
|
|
477
|
+
// path: string
|
|
478
|
+
// }): void => {
|
|
479
|
+
// const pathParts = path.split('/').filter(part => part.trim() !== '')
|
|
480
|
+
//
|
|
481
|
+
// // Handle the state update for attachments
|
|
482
|
+
// setAttachments(prevAttachments => {
|
|
483
|
+
// const updatedAttachments = deleteAttachmentById(
|
|
484
|
+
// prevAttachments,
|
|
485
|
+
// selectedAttachments.map(attachment => attachment.id)
|
|
486
|
+
// )
|
|
487
|
+
//
|
|
488
|
+
// // Recursively process each part of the path
|
|
489
|
+
// const processPath = (
|
|
490
|
+
// attachments: (BucketFilesType | BucketFoldersType)[],
|
|
491
|
+
// pathParts: string[],
|
|
492
|
+
// treeLevel: number
|
|
493
|
+
// ): (BucketFilesType | BucketFoldersType)[] => {
|
|
494
|
+
// if (pathParts.length === 0) {
|
|
495
|
+
// // If path is empty, add to root (main attachments array)
|
|
496
|
+
// if (treeLevel === 1) {
|
|
497
|
+
// attachments = [...attachments, ...selectedAttachments]
|
|
498
|
+
// }
|
|
499
|
+
// return attachments
|
|
500
|
+
// }
|
|
501
|
+
//
|
|
502
|
+
// const currentFolderName = pathParts[0]
|
|
503
|
+
// const remainingPathParts = pathParts.slice(1)
|
|
504
|
+
//
|
|
505
|
+
// // Check if the current part is a folder or file
|
|
506
|
+
// let folder = attachments.find(attachment => 'name' in attachment && attachment.name === currentFolderName) as
|
|
507
|
+
// | BucketFoldersType
|
|
508
|
+
// | undefined
|
|
509
|
+
//
|
|
510
|
+
// // If we are at the last path part and we are dealing with a file, add to the file content
|
|
511
|
+
// if (remainingPathParts.length === 0 && folder) {
|
|
512
|
+
// folder.content = [...folder.content, ...selectedAttachments] // Add new attachments to file's content
|
|
513
|
+
// folder.updated_at = new Date() // Update the file's last updated time
|
|
514
|
+
// return attachments
|
|
515
|
+
// }
|
|
516
|
+
//
|
|
517
|
+
// // If the folder doesn't exist, create it
|
|
518
|
+
// if (!folder) {
|
|
519
|
+
// folder = {
|
|
520
|
+
// id: `${currentFolderName}-${Date.now()}`,
|
|
521
|
+
// name: currentFolderName,
|
|
522
|
+
// content: remainingPathParts.length > 0 ? [] : selectedAttachments, // Only add attachments if it's the last part
|
|
523
|
+
// created_at: new Date(),
|
|
524
|
+
// updated_at: new Date(),
|
|
525
|
+
// tree_level: treeLevel,
|
|
526
|
+
// }
|
|
527
|
+
//
|
|
528
|
+
// // Add the new folder to the attachments array
|
|
529
|
+
// attachments.push(folder)
|
|
530
|
+
// } else {
|
|
531
|
+
// // If folder exists, update it with new content at the last part
|
|
532
|
+
// folder.updated_at = new Date() // Update the folder's last updated time
|
|
533
|
+
// }
|
|
534
|
+
//
|
|
535
|
+
// // Continue processing subfolders if there are more path parts
|
|
536
|
+
// if ('content' in folder && remainingPathParts.length > 0) {
|
|
537
|
+
// folder.content = processPath(folder.content, remainingPathParts, treeLevel + 1)
|
|
538
|
+
// }
|
|
539
|
+
//
|
|
540
|
+
// return attachments
|
|
541
|
+
// }
|
|
542
|
+
//
|
|
543
|
+
// // Process the path recursively and update the attachments
|
|
544
|
+
// const updatedAttachmentsWithPath = processPath(updatedAttachments, pathParts, 1)
|
|
545
|
+
//
|
|
546
|
+
// // Update the selected attachments state
|
|
547
|
+
// setSelectedAttachment([])
|
|
548
|
+
//
|
|
549
|
+
// // Return the updated attachments array to set it into the state
|
|
550
|
+
// return updatedAttachmentsWithPath
|
|
551
|
+
// })
|
|
552
|
+
// }
|
|
553
|
+
//
|
|
554
|
+
// export function selectAttachmentFromFolderContent({
|
|
555
|
+
// filesInCurrentTree,
|
|
556
|
+
// setSelectedAttachment,
|
|
557
|
+
// }: {
|
|
558
|
+
// filesInCurrentTree: (BucketFilesType | BucketFoldersType)[]
|
|
559
|
+
// setSelectedAttachment: React.Dispatch<React.SetStateAction<BucketFilesType[]>>
|
|
560
|
+
// checkState?: boolean
|
|
561
|
+
// }) {
|
|
562
|
+
// setSelectedAttachment(prevSelected => {
|
|
563
|
+
// const allFilesSelected = filesInCurrentTree.every(file =>
|
|
564
|
+
// prevSelected.some(attachment => attachment.id === file.id)
|
|
565
|
+
// )
|
|
566
|
+
//
|
|
567
|
+
// // If all files are already selected, remove them
|
|
568
|
+
// if (allFilesSelected)
|
|
569
|
+
// return prevSelected.filter(attachment => !filesInCurrentTree.some(file => file.id === attachment.id))
|
|
570
|
+
// // Otherwise, add the files that are not already selected
|
|
571
|
+
// const newFiles = filesInCurrentTree.filter(file => !prevSelected.some(attachment => attachment.id === file.id))
|
|
572
|
+
// return [...prevSelected, ...newFiles] as BucketFilesType[]
|
|
573
|
+
// })
|
|
574
|
+
// }
|
|
575
|
+
//
|
|
576
|
+
// export const uploadAttachmentPromise = (files: number, toastId: string): Promise<UploadPromiseReturn> => {
|
|
577
|
+
// toast.loading(
|
|
578
|
+
// <UploadSonnerContent
|
|
579
|
+
// progress={0}
|
|
580
|
+
// files={files}
|
|
581
|
+
// />,
|
|
582
|
+
// {
|
|
583
|
+
// duration: 400000,
|
|
584
|
+
// id: toastId,
|
|
585
|
+
// }
|
|
586
|
+
// )
|
|
587
|
+
//
|
|
588
|
+
// return new Promise(resolve => {
|
|
589
|
+
// let currentProgress = 0
|
|
590
|
+
//
|
|
591
|
+
// toast.loading(
|
|
592
|
+
// <UploadSonnerContent
|
|
593
|
+
// progress={currentProgress}
|
|
594
|
+
// files={files}
|
|
595
|
+
// />,
|
|
596
|
+
// {
|
|
597
|
+
// duration: 400000,
|
|
598
|
+
// id: toastId,
|
|
599
|
+
// }
|
|
600
|
+
// )
|
|
601
|
+
//
|
|
602
|
+
// const intervalId = setInterval(() => {
|
|
603
|
+
// currentProgress += Math.floor(Math.random() * 10) + 1 // Increment progress by a random value
|
|
604
|
+
// if (currentProgress > 100) currentProgress = 100 // Ensure progress does not exceed 100%
|
|
605
|
+
//
|
|
606
|
+
// if (currentProgress >= 100) {
|
|
607
|
+
// clearInterval(intervalId) // Clear the interval once upload is complete
|
|
608
|
+
// resolve({ progress: currentProgress, message: 'Upload complete', files: 3, toastId }) // Resolve the promise when progress reaches 100
|
|
609
|
+
// }
|
|
610
|
+
//
|
|
611
|
+
// toast.loading(
|
|
612
|
+
// <UploadSonnerContent
|
|
613
|
+
// progress={currentProgress}
|
|
614
|
+
// files={files}
|
|
615
|
+
// />,
|
|
616
|
+
// {
|
|
617
|
+
// id: toastId,
|
|
618
|
+
// }
|
|
619
|
+
// )
|
|
620
|
+
// }, 20) // Adjust the interval time as needed
|
|
621
|
+
// })
|
|
622
|
+
// }
|
|
623
|
+
//
|
|
624
|
+
// export const toBase64 = (file: File): Promise<string> =>
|
|
625
|
+
// new Promise((resolve, reject) => {
|
|
626
|
+
// const reader = new FileReader()
|
|
627
|
+
// reader.readAsDataURL(file)
|
|
628
|
+
// reader.onload = () => resolve(reader.result as string)
|
|
629
|
+
// reader.onerror = reject
|
|
630
|
+
// })
|