Feat: 이미지 업로드 form에 windowing 적용 - S11P21S002-265
This commit is contained in:
parent
3195d919b2
commit
3f05fec8de
45
frontend/package-lock.json
generated
45
frontend/package-lock.json
generated
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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 ? (
|
||||
|
@ -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}
|
||||
/>
|
||||
))}
|
||||
|
@ -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 (
|
||||
|
Loading…
Reference in New Issue
Block a user