Feat: 이미지 업로드 form에 windowing 적용 - S11P21S002-265

This commit is contained in:
jhynsoo 2024-10-02 17:04:06 +09:00
parent 3195d919b2
commit 3f05fec8de
5 changed files with 96 additions and 44 deletions

View File

@ -22,6 +22,7 @@
"@radix-ui/react-toggle": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@tanstack/react-query": "^5.52.1",
"@types/react-window": "^1.8.8",
"axios": "^1.7.5",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
@ -35,6 +36,8 @@
"react-resizable-panels": "^2.1.1",
"react-router-dom": "^6.26.1",
"react-slick": "^0.30.2",
"react-virtualized-auto-sizer": "^1.0.24",
"react-window": "^1.8.10",
"recharts": "^2.12.7",
"slick-carousel": "^1.8.1",
"sweetalert2": "^11.14.1",
@ -6950,6 +6953,15 @@
"@types/react": "*"
}
},
"node_modules/@types/react-window": {
"version": "1.8.8",
"resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz",
"integrity": "sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==",
"license": "MIT",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/resolve": {
"version": "1.20.6",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz",
@ -11032,6 +11044,12 @@
"node": ">= 0.6"
}
},
"node_modules/memoize-one": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz",
"integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==",
"license": "MIT"
},
"node_modules/memoizerific": {
"version": "1.11.3",
"resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz",
@ -12696,6 +12714,33 @@
"react-dom": ">=16.6.0"
}
},
"node_modules/react-virtualized-auto-sizer": {
"version": "1.0.24",
"resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.24.tgz",
"integrity": "sha512-3kCn7N9NEb3FlvJrSHWGQ4iVl+ydQObq2fHMn12i5wbtm74zHOPhz/i64OL3c1S1vi9i2GXtZqNqUJTQ+BnNfg==",
"license": "MIT",
"peerDependencies": {
"react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0",
"react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-window": {
"version": "1.8.10",
"resolved": "https://registry.npmjs.org/react-window/-/react-window-1.8.10.tgz",
"integrity": "sha512-Y0Cx+dnU6NLa5/EvoHukUD0BklJ8qITCtVEPY1C/nL8wwoZ0b5aEw8Ff1dOVHw7fCzMt55XfJDd8S8W8LCaUCg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.0.0",
"memoize-one": ">=3.1.1 <6"
},
"engines": {
"node": ">8.0.0"
},
"peerDependencies": {
"react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",

View File

@ -28,6 +28,7 @@
"@radix-ui/react-toggle": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@tanstack/react-query": "^5.52.1",
"@types/react-window": "^1.8.8",
"axios": "^1.7.5",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
@ -41,6 +42,8 @@
"react-resizable-panels": "^2.1.1",
"react-router-dom": "^6.26.1",
"react-slick": "^0.30.2",
"react-virtualized-auto-sizer": "^1.0.24",
"react-window": "^1.8.10",
"recharts": "^2.12.7",
"slick-carousel": "^1.8.1",
"sweetalert2": "^11.14.1",

View File

@ -4,6 +4,7 @@ import { cn } from '@/lib/utils';
import useAuthStore from '@/stores/useAuthStore';
import { CircleCheckBig, CircleDashed, CircleX, X } from 'lucide-react';
import useUploadImageFileQuery from '@/queries/projects/useUploadImageFileQuery';
import { FixedSizeList } from 'react-window';
export default function ImageUploadFileForm({
onClose,
@ -135,48 +136,56 @@ export default function ImageUploadFileForm({
)}
{files.length > 0 && (
<ul className="m-0 max-h-[260px] list-none overflow-y-auto p-0">
{files.map((file, index) => (
<li
key={index}
className="flex items-center justify-between p-1"
>
<span className="truncate">{file.webkitRelativePath || file.name}</span>
{isUploading ? (
<div className="p-2">
{isUploaded ? (
<CircleCheckBig
className="stroke-green-500"
<FixedSizeList
height={260}
itemCount={files.length}
itemSize={40}
width="100%"
>
{({ index, style }) => (
<li
key={index}
className="flex items-center justify-between p-1"
style={style}
>
<span className="truncate">{files[index].webkitRelativePath || files[index].name}</span>
{isUploading ? (
<div className="p-2">
{isUploaded ? (
<CircleCheckBig
className="stroke-green-500"
size={16}
strokeWidth="2"
/>
) : isFailed ? (
<CircleX
className="stroke-red-500"
size={16}
strokeWidth="2"
/>
) : (
<CircleDashed
className="stroke-gray-500"
size={16}
strokeWidth="2"
/>
)}
</div>
) : (
<button
className={'cursor-pointer p-2'}
onClick={() => handleRemoveFile(index)}
>
<X
color="red"
size={16}
strokeWidth="2"
/>
) : isFailed ? (
<CircleX
className="stroke-red-500"
size={16}
strokeWidth="2"
/>
) : (
<CircleDashed
className="stroke-gray-500"
size={16}
strokeWidth="2"
/>
)}
</div>
) : (
<button
className={'cursor-pointer p-2'}
onClick={() => handleRemoveFile(index)}
>
<X
color="red"
size={16}
strokeWidth="2"
/>
</button>
)}
</li>
))}
</button>
)}
</li>
)}
</FixedSizeList>
</ul>
)}
{isUploading ? (

View File

@ -56,7 +56,6 @@ export default function ProjectDirectoryItem({
key={`${projectId}-${item.imageTitle}`}
item={item}
depth={depth + 1}
folderId={folderData.id}
selected={image?.id === item.id}
/>
))}

View File

@ -2,12 +2,10 @@ import { cn } from '@/lib/utils';
import { ImageResponse } from '@/types';
import { ArrowDownToLine, Check, CircleSlash, Image, Loader, Minus, Send } from 'lucide-react';
import useCanvasStore from '@/stores/useCanvasStore';
import useProjectStore from '@/stores/useProjectStore';
export default function ProjectFileItem({
className = '',
item,
folderId = 0,
depth = 0,
selected,
}: {
@ -19,11 +17,9 @@ export default function ProjectFileItem({
}) {
const paddingLeft = depth * 12;
const setImage = useCanvasStore((state) => state.setImage);
const setFolderId = useProjectStore((state) => state.setFolderId);
const handleClick = () => {
setImage(item);
setFolderId(folderId);
};
return (