Merge branch 'fe/feat/265-image-upload-windowing' into 'fe/develop'

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

See merge request s11-s-project/S11P21S002!265
This commit is contained in:
홍창기 2024-10-02 17:14:35 +09:00
commit 48da0d856a
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-toggle": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2", "@radix-ui/react-tooltip": "^1.1.2",
"@tanstack/react-query": "^5.52.1", "@tanstack/react-query": "^5.52.1",
"@types/react-window": "^1.8.8",
"axios": "^1.7.5", "axios": "^1.7.5",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"clsx": "^2.1.1", "clsx": "^2.1.1",
@ -35,6 +36,8 @@
"react-resizable-panels": "^2.1.1", "react-resizable-panels": "^2.1.1",
"react-router-dom": "^6.26.1", "react-router-dom": "^6.26.1",
"react-slick": "^0.30.2", "react-slick": "^0.30.2",
"react-virtualized-auto-sizer": "^1.0.24",
"react-window": "^1.8.10",
"recharts": "^2.12.7", "recharts": "^2.12.7",
"slick-carousel": "^1.8.1", "slick-carousel": "^1.8.1",
"sweetalert2": "^11.14.1", "sweetalert2": "^11.14.1",
@ -6950,6 +6953,15 @@
"@types/react": "*" "@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": { "node_modules/@types/resolve": {
"version": "1.20.6", "version": "1.20.6",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz",
@ -11032,6 +11044,12 @@
"node": ">= 0.6" "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": { "node_modules/memoizerific": {
"version": "1.11.3", "version": "1.11.3",
"resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz",
@ -12696,6 +12714,33 @@
"react-dom": ">=16.6.0" "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": { "node_modules/read-cache": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "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-toggle": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2", "@radix-ui/react-tooltip": "^1.1.2",
"@tanstack/react-query": "^5.52.1", "@tanstack/react-query": "^5.52.1",
"@types/react-window": "^1.8.8",
"axios": "^1.7.5", "axios": "^1.7.5",
"class-variance-authority": "^0.7.0", "class-variance-authority": "^0.7.0",
"clsx": "^2.1.1", "clsx": "^2.1.1",
@ -41,6 +42,8 @@
"react-resizable-panels": "^2.1.1", "react-resizable-panels": "^2.1.1",
"react-router-dom": "^6.26.1", "react-router-dom": "^6.26.1",
"react-slick": "^0.30.2", "react-slick": "^0.30.2",
"react-virtualized-auto-sizer": "^1.0.24",
"react-window": "^1.8.10",
"recharts": "^2.12.7", "recharts": "^2.12.7",
"slick-carousel": "^1.8.1", "slick-carousel": "^1.8.1",
"sweetalert2": "^11.14.1", "sweetalert2": "^11.14.1",

View File

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

View File

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

View File

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