From 17aaf1388a0ec6ddf27a6bfebda0bbfdb0285747 Mon Sep 17 00:00:00 2001 From: Jaemin Choi <1dotolee@gmail.com> Date: Fri, 23 Feb 2024 04:22:26 +0900 Subject: [PATCH] feat(fe): add problem uploading ui with excel (#1468) * feat: add file upload dialog * feat: configure apollo-upload-client --- Caddyfile | 2 +- .../app/admin/_components/ApolloProvider.tsx | 11 +- .../problem/_components/UploadDialog.tsx | 164 ++++++++++++++++++ frontend-client/app/admin/problem/page.tsx | 18 +- frontend-client/package.json | 2 + frontend-client/public/sample.xlsx | Bin 0 -> 9380 bytes pnpm-lock.yaml | 63 +++++-- 7 files changed, 233 insertions(+), 27 deletions(-) create mode 100644 frontend-client/app/admin/problem/_components/UploadDialog.tsx create mode 100644 frontend-client/public/sample.xlsx diff --git a/Caddyfile b/Caddyfile index b4a97057fe..280a6724ad 100644 --- a/Caddyfile +++ b/Caddyfile @@ -11,7 +11,7 @@ header Access-Control-Allow-Credentials true header Access-Control-Allow-Origin "{args[0]}" header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, DELETE" - header Access-Control-Allow-Headers "Content-Type, Authorization, Email-Auth" + header Access-Control-Allow-Headers "Content-Type, Authorization, Email-Auth, Apollo-Require-Preflight" respond "" 204 } diff --git a/frontend-client/app/admin/_components/ApolloProvider.tsx b/frontend-client/app/admin/_components/ApolloProvider.tsx index 86122a32d2..66af6c4b02 100644 --- a/frontend-client/app/admin/_components/ApolloProvider.tsx +++ b/frontend-client/app/admin/_components/ApolloProvider.tsx @@ -6,18 +6,21 @@ import { ApolloClient, ApolloLink, ApolloProvider, - InMemoryCache, - createHttpLink + InMemoryCache } from '@apollo/client' import { setContext } from '@apollo/client/link/context' +import createUploadLink from 'apollo-upload-client/createUploadLink.mjs' interface Props { children: React.ReactNode } export default function ClientApolloProvider({ children }: Props) { - const httpLink = createHttpLink({ - uri: adminBaseUrl + const httpLink = createUploadLink({ + uri: adminBaseUrl, + headers: { + 'Apollo-Require-Preflight': 'true' + } }) const authLink = setContext(async (_, { headers }) => { const session = await auth() diff --git a/frontend-client/app/admin/problem/_components/UploadDialog.tsx b/frontend-client/app/admin/problem/_components/UploadDialog.tsx new file mode 100644 index 0000000000..25790c09f8 --- /dev/null +++ b/frontend-client/app/admin/problem/_components/UploadDialog.tsx @@ -0,0 +1,164 @@ +import { gql } from '@generated' +import { Button } from '@/components/ui/button' +import { + Dialog, + DialogClose, + DialogContent, + DialogTrigger +} from '@/components/ui/dialog' +import { useMutation } from '@apollo/client' +import { UploadIcon, UploadCloudIcon } from 'lucide-react' +import { useRef, useState } from 'react' +import { createPortal } from 'react-dom' +import { RiFileExcel2Fill } from 'react-icons/ri' +import { useDrop } from 'react-use' +import { toast } from 'sonner' + +interface Props { + refetch: () => Promise +} + +const UPLOAD_PROBLEMS = gql(` + mutation uploadProblems ($groupId: Int!, $input: UploadFileInput!) { + uploadProblems(groupId: $groupId, input: $input) { + id + } + } +`) + +export default function UploadDialog({ refetch }: Props) { + const [file, setFile] = useState(null) + const fileRef = useRef(null) + + const state = useDrop({ + onFiles: (files) => { + if (files.length > 1) { + toast.error('Only one file is allowed') + } + const file = files[0] + if (file.name.endsWith('.xlsx')) { + setFile(files[0]) + } else { + toast.error('Only .xlsx files are allowed') + } + } + }) + + const openFileBrowser = () => { + fileRef.current?.click() + } + + const setFileFromInput = () => { + if (fileRef.current?.files) { + setFile(fileRef.current.files[0]) + } + } + + const resetFile = () => { + setFile(null) + if (fileRef.current) fileRef.current.value = '' + } + + const [uploadProblems, { loading }] = useMutation(UPLOAD_PROBLEMS) + const uploadFile = async () => { + try { + await uploadProblems({ + variables: { + groupId: 1, + input: { + file + } + } + }) + } catch (error) { + toast.error('Failed to upload file') + return + } + toast.success('File uploaded successfully') + document.getElementById('closeDialog')?.click() + resetFile() + await refetch() + } + + return ( + + + + + +

Upload Problem

+

+ Please upload Excel file containing problem data. If you are looking + for the required schema, you can download{' '} + + the sample file here. + +

+ + + {file ? ( +
+
+ + {file.name} +
+
+ + +
+ {loading && ( +
+
{/* spinner */} +
+ )} +
+ ) : ( +
+ +

Drag and Drop

+

or

+ +
+ )} + {state.over && + typeof window === 'object' && + createPortal( +
+ Drop file here +
, + document.body + )} +
+
+ ) +} diff --git a/frontend-client/app/admin/problem/page.tsx b/frontend-client/app/admin/problem/page.tsx index 532f1d699b..b673e6f8ad 100644 --- a/frontend-client/app/admin/problem/page.tsx +++ b/frontend-client/app/admin/problem/page.tsx @@ -11,6 +11,7 @@ import { PlusCircleIcon } from 'lucide-react' import Link from 'next/link' import * as React from 'react' import { columns } from './_components/Columns' +import UploadDialog from './_components/UploadDialog' const GET_PROBLEMS = gql(` query GetProblems( @@ -47,7 +48,7 @@ const GET_PROBLEMS = gql(` export const dynamic = 'force-dynamic' export default function Page() { - const { data, loading } = useQuery(GET_PROBLEMS, { + const { data, loading, refetch } = useQuery(GET_PROBLEMS, { variables: { groupId: 1, take: 100, @@ -88,12 +89,15 @@ export default function Page() { Here's a list you made

- - - +
+ + + + +
{loading ? ( <> diff --git a/frontend-client/package.json b/frontend-client/package.json index 14aba8a7d4..fe1742ffbd 100644 --- a/frontend-client/package.json +++ b/frontend-client/package.json @@ -45,6 +45,7 @@ "@uiw/codemirror-extensions-langs": "^4.21.22", "@uiw/codemirror-themes": "^4.21.22", "@uiw/react-codemirror": "^4.21.22", + "apollo-upload-client": "^18.0.1", "cmdk": "^0.2.1", "dayjs": "^1.11.10", "embla-carousel-react": "8.0.0-rc22", @@ -70,6 +71,7 @@ "@graphql-codegen/cli": "^5.0.2", "@graphql-codegen/client-preset": "^4.2.2", "@graphql-typed-document-node/core": "^3.2.0", + "@types/apollo-upload-client": "^18.0.0", "@types/node": "^20.11.19", "@types/react": "^18.2.56", "@types/react-copy-to-clipboard": "^5.0.7", diff --git a/frontend-client/public/sample.xlsx b/frontend-client/public/sample.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..98a965951e0504f576a4fcba35183b415ea3f674 GIT binary patch literal 9380 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 literal 0 HcmV?d00001 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e8b0b31abd..11281097c9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -580,6 +580,9 @@ importers: '@uiw/react-codemirror': specifier: ^4.21.22 version: 4.21.22(@babel/runtime@7.23.9)(@codemirror/autocomplete@6.12.0)(@codemirror/language@6.10.1)(@codemirror/lint@6.5.0)(@codemirror/search@6.5.5)(@codemirror/state@6.4.0)(@codemirror/theme-one-dark@6.1.2)(@codemirror/view@6.23.1)(codemirror@6.0.1)(react-dom@18.2.0)(react@18.2.0) + apollo-upload-client: + specifier: ^18.0.1 + version: 18.0.1(@apollo/client@3.9.5)(graphql@16.8.1) cmdk: specifier: ^0.2.1 version: 0.2.1(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) @@ -650,6 +653,9 @@ importers: '@graphql-typed-document-node/core': specifier: ^3.2.0 version: 3.2.0(graphql@16.8.1) + '@types/apollo-upload-client': + specifier: ^18.0.0 + version: 18.0.0(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0) '@types/node': specifier: ^20.11.19 version: 20.11.19 @@ -827,7 +833,6 @@ packages: zen-observable-ts: 1.2.5 transitivePeerDependencies: - '@types/react' - dev: false /@apollo/protobufjs@1.2.7: resolution: {integrity: sha512-Lahx5zntHPZia35myYDBRuF58tlwPskwHc5CWBZC/4bMKB6siTBWwtMrkqXcsNwQiFSzSx5hKdRPUmemrEp3Gg==} @@ -7711,6 +7716,20 @@ packages: '@types/node': 20.11.19 dev: true + /@types/apollo-upload-client@18.0.0(@types/react@18.2.56)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-cMgITNemktxasqvp6jiPj15dv84n3FTMvMoYBP1+xonDS+0l6JygIJrj2LJh85rShRzTOOkrElrAsCXXARa3KA==} + dependencies: + '@apollo/client': 3.9.5(@types/react@18.2.56)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) + '@types/extract-files': 13.0.1 + graphql: 16.8.1 + transitivePeerDependencies: + - '@types/react' + - graphql-ws + - react + - react-dom + - subscriptions-transport-ws + dev: true + /@types/body-parser@1.19.5: resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} dependencies: @@ -7799,6 +7818,10 @@ packages: '@types/qs': 6.9.11 '@types/serve-static': 1.15.5 + /@types/extract-files@13.0.1: + resolution: {integrity: sha512-/fRbzc2lAd7jDJSSnxWiUyXWjdUZZ4HbISLJzVgt1AvrdOa7U49YRPcvuCUywkmURZ7uwJOheDjx19itbQ5KvA==} + dev: true + /@types/flexsearch@0.7.6: resolution: {integrity: sha512-H5IXcRn96/gaDmo+rDl2aJuIJsob8dgOXDqf8K0t8rWZd1AFNaaspmRsElESiU+EWE33qfbFPgI0OC/B1g9FCA==} dev: true @@ -8819,35 +8842,30 @@ packages: engines: {node: '>=8'} dependencies: tslib: 2.6.2 - dev: false /@wry/context@0.7.4: resolution: {integrity: sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==} engines: {node: '>=8'} dependencies: tslib: 2.6.2 - dev: false /@wry/equality@0.5.7: resolution: {integrity: sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==} engines: {node: '>=8'} dependencies: tslib: 2.6.2 - dev: false /@wry/trie@0.4.3: resolution: {integrity: sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==} engines: {node: '>=8'} dependencies: tslib: 2.6.2 - dev: false /@wry/trie@0.5.0: resolution: {integrity: sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==} engines: {node: '>=8'} dependencies: tslib: 2.6.2 - dev: false /@xobotyi/scrollbar-width@1.9.5: resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==} @@ -9091,6 +9109,18 @@ packages: normalize-path: 3.0.0 picomatch: 2.3.1 + /apollo-upload-client@18.0.1(@apollo/client@3.9.5)(graphql@16.8.1): + resolution: {integrity: sha512-OQvZg1rK05VNI79D658FUmMdoI2oB/KJKb6QGMa2Si25QXOaAvLMBFUEwJct7wf+19U8vk9ILhidBOU1ZWv6QA==} + engines: {node: ^18.15.0 || >=20.4.0} + peerDependencies: + '@apollo/client': ^3.8.0 + graphql: 14 - 16 + dependencies: + '@apollo/client': 3.9.5(@types/react@18.2.56)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0) + extract-files: 13.0.0 + graphql: 16.8.1 + dev: false + /append-field@1.0.0: resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} @@ -11820,6 +11850,13 @@ packages: engines: {node: ^12.20 || >= 14.13} dev: true + /extract-files@13.0.0: + resolution: {integrity: sha512-FXD+2Tsr8Iqtm3QZy1Zmwscca7Jx3mMC5Crr+sEP1I303Jy1CYMuYCm7hRTplFNg3XdUavErkxnTzpaqdSoi6g==} + engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0} + dependencies: + is-plain-obj: 4.1.0 + dev: false + /fast-copy@3.0.1: resolution: {integrity: sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==} dev: false @@ -12712,7 +12749,6 @@ packages: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} dependencies: react-is: 16.13.1 - dev: false /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} @@ -13200,6 +13236,11 @@ packages: engines: {node: '>=8'} dev: true + /is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + dev: false + /is-plain-object@2.0.4: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} engines: {node: '>=0.10.0'} @@ -15700,7 +15741,6 @@ packages: '@wry/context': 0.7.4 '@wry/trie': 0.4.3 tslib: 2.6.2 - dev: false /optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} @@ -16844,7 +16884,6 @@ packages: loose-envify: 1.4.0 react: 18.2.0 scheduler: 0.23.0 - dev: false /react-hook-form@7.50.1(react@18.2.0): resolution: {integrity: sha512-3PCY82oE0WgeOgUtIr3nYNNtNvqtJ7BZjsbxh6TnYNbXButaD5WpjOmTjdxZfheuHKR68qfeFnEDVYoSSFPMTQ==} @@ -17159,7 +17198,6 @@ packages: dependencies: '@types/react': 18.2.56 react: 18.2.0 - dev: false /relateurl@0.2.7: resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} @@ -17266,7 +17304,6 @@ packages: /response-iterator@0.2.6: resolution: {integrity: sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==} engines: {node: '>=0.8'} - dev: false /restore-cursor@3.1.0: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} @@ -17453,7 +17490,6 @@ packages: resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} dependencies: loose-envify: 1.4.0 - dev: false /schema-utils@3.3.0: resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} @@ -18521,7 +18557,6 @@ packages: engines: {node: '>=8'} dependencies: tslib: 2.6.2 - dev: false /ts-loader@9.5.1(typescript@5.3.3)(webpack@5.90.1): resolution: {integrity: sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==} @@ -19825,11 +19860,9 @@ packages: resolution: {integrity: sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==} dependencies: zen-observable: 0.8.15 - dev: false /zen-observable@0.8.15: resolution: {integrity: sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==} - dev: false /zip-stream@4.1.1: resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==}