|
| 1 | +import React, {useEffect, useRef, useState} from "react"; |
| 2 | + |
| 3 | +import Meta from "antd/es/card/Meta"; |
| 4 | +import {Card, Typography, Image, Modal, Form,Select,Tour,message} from "antd"; |
| 5 | +import {CloudUploadOutlined} from "@ant-design/icons"; |
| 6 | +import axios from "axios"; |
| 7 | + |
| 8 | + |
| 9 | +const DemoCard = ({uploadFiles, width=300, title="Hiking", url='', isFirstCard, closeGallery=()=>{}})=>{ |
| 10 | + |
| 11 | + // the description row size |
| 12 | + const [rows, setRows] = useState(2); |
| 13 | + |
| 14 | + // control the expanded status when description is too long |
| 15 | + const [expanded, setExpanded] = useState(false); |
| 16 | + const [description,setDescription] = useState("This domain don't have the description yet") |
| 17 | + const [coverSrc, setCoverSrc] = useState(); |
| 18 | + |
| 19 | + // all files from Github |
| 20 | + const [files,setFiles] = useState([]); |
| 21 | + const [selectModalOpen, setSelectModalOpen] = useState(false); |
| 22 | + |
| 23 | + const domainRef = useRef(null); |
| 24 | + const problemRef = useRef(null); |
| 25 | + const animationRef = useRef(null); |
| 26 | + |
| 27 | + |
| 28 | + |
| 29 | + const filteredFiles = (keyword)=>{ |
| 30 | + return files.filter(item=>item.name.toUpperCase().includes(keyword)) |
| 31 | + .map(item=>{ |
| 32 | + return {label:item.name, value:item.name} |
| 33 | + }) |
| 34 | + } |
| 35 | + |
| 36 | + |
| 37 | + |
| 38 | + const handleUpload = async ()=>{ |
| 39 | + try{ |
| 40 | + const data = await form.validateFields() |
| 41 | + |
| 42 | + let file_temp = {} |
| 43 | + file_temp['animation'] = files.find(item=>item.name === data.animation) |
| 44 | + file_temp['domain'] = files.find(item=>item.name === data.domain) |
| 45 | + file_temp['problem'] = files.find(item=>item.name === data.problem) |
| 46 | + uploadFiles(file_temp) |
| 47 | + |
| 48 | + message.success('Upload successfully!'); |
| 49 | + setSelectModalOpen(false) |
| 50 | + closeGallery() |
| 51 | + |
| 52 | + }catch (_){ |
| 53 | + |
| 54 | + } |
| 55 | + |
| 56 | + } |
| 57 | + const token = "ghp_WkIVNPY9eR5xZ3iLCsy" + "X2ttHsGuE321WyoPV" |
| 58 | + const [form] = Form.useForm() |
| 59 | + useEffect(() => { |
| 60 | + axios.get(url,{ |
| 61 | + headers:{ |
| 62 | + Authorization: `token ${token}` |
| 63 | + } |
| 64 | + }) |
| 65 | + .then(response => { |
| 66 | + // load files from Github URL |
| 67 | + const files = response.data; |
| 68 | + const filePromises = files.map((file,index) => { |
| 69 | + if (file.type === 'file') { |
| 70 | + if(file.name.toUpperCase().includes(".PNG")){ |
| 71 | + setCoverSrc(file.download_url) |
| 72 | + }else{ |
| 73 | + return axios.get(file.download_url, { responseType: 'blob', |
| 74 | + }) |
| 75 | + .then(fileResponse => { |
| 76 | + const fileName = file.name; |
| 77 | + const item = new File([fileResponse.data], fileName, |
| 78 | + { type: fileResponse.data.type }); |
| 79 | + return { |
| 80 | + uid:index, |
| 81 | + name:item.name, |
| 82 | + status:'done', |
| 83 | + type:item.type, |
| 84 | + size:item.size, |
| 85 | + originFileObj:item, |
| 86 | + url:file.url |
| 87 | + } |
| 88 | + }); |
| 89 | + } |
| 90 | + } |
| 91 | + }); |
| 92 | + return Promise.all(filePromises); |
| 93 | + }) |
| 94 | + .then(files => { |
| 95 | + |
| 96 | + let files_list = files.filter(item =>item) |
| 97 | + let description_files = files_list.filter(item=>item.name==='description.txt') |
| 98 | + if(description_files.length>0){ |
| 99 | + const reader = new FileReader(); |
| 100 | + reader.onload = (event)=>{ |
| 101 | + setDescription(event.target.result)} |
| 102 | + reader.readAsText(description_files[0].originFileObj); |
| 103 | + } |
| 104 | + setFiles(files_list) |
| 105 | + |
| 106 | + }) |
| 107 | + }, []); |
| 108 | + |
| 109 | + return ( |
| 110 | + <> |
| 111 | + <Card |
| 112 | + style={{ |
| 113 | + width: width, |
| 114 | + }} |
| 115 | + cover={ |
| 116 | + <div style={{display:"flex",justifyContent:'center'}}> |
| 117 | + <Image |
| 118 | + alt="background" |
| 119 | + width={'150'} |
| 120 | + preview={false} |
| 121 | + height={150} |
| 122 | + src={coverSrc?coverSrc:'error'} |
| 123 | + fallback="data:image/png;base64, |
| 124 | + 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" |
| 125 | + |
| 126 | + /> |
| 127 | + </div> |
| 128 | + } |
| 129 | + |
| 130 | + actions={[ |
| 131 | + <CloudUploadOutlined key="ellipsis" |
| 132 | + // {/*{...(isFirstCard ? { ref: buttonRef } : {})}*/} |
| 133 | + onClick={() => { setSelectModalOpen(true); }} />, |
| 134 | + ]} |
| 135 | + > |
| 136 | + <Meta |
| 137 | + title={title} |
| 138 | + description={<Typography.Paragraph |
| 139 | + ellipsis={{ |
| 140 | + rows, |
| 141 | + expandable: 'collapsible', |
| 142 | + expanded, |
| 143 | + onExpand: (_, |
| 144 | + info) => setExpanded(info.expanded), |
| 145 | + }} |
| 146 | + > |
| 147 | + {description} |
| 148 | + </Typography.Paragraph>} |
| 149 | + /> |
| 150 | + </Card> |
| 151 | + |
| 152 | + <Modal |
| 153 | + title={ |
| 154 | + <> |
| 155 | + <Typography.Title level={4} style={{margin:5}} >Select Item |
| 156 | + </Typography.Title> |
| 157 | + </> |
| 158 | + } |
| 159 | + open={selectModalOpen} |
| 160 | + |
| 161 | + centered |
| 162 | + onOk={handleUpload} |
| 163 | + okText={'Load'} |
| 164 | + onCancel={()=>{ |
| 165 | + setSelectModalOpen(false) |
| 166 | + }} |
| 167 | + > |
| 168 | + <Form |
| 169 | + labelCol={{span: 6,}} |
| 170 | + form={form} |
| 171 | + initialValues={ |
| 172 | + { |
| 173 | + problem:(filteredFiles("PROBLEM") && filteredFiles("PROBLEM")[0]) |
| 174 | + ?filteredFiles("PROBLEM")[0].value |
| 175 | + :null, |
| 176 | + domain:(filteredFiles("DOMAIN") && filteredFiles("DOMAIN")[0]) |
| 177 | + ?filteredFiles("DOMAIN")[0].value |
| 178 | + :null, |
| 179 | + animation:(filteredFiles("AP") && filteredFiles("AP")[0]) |
| 180 | + ?filteredFiles("AP")[0].value |
| 181 | + :null |
| 182 | + } |
| 183 | + } |
| 184 | + feedbackIcons |
| 185 | + > |
| 186 | + <Form.Item |
| 187 | + label="Domain file" name={'domain'} |
| 188 | + rules={[{required: true, message: "Please select a domain"},]} |
| 189 | + > |
| 190 | + <Select ref={domainRef} |
| 191 | + options={filteredFiles("DOMAIN")} |
| 192 | + /> |
| 193 | + </Form.Item> |
| 194 | + |
| 195 | + <Form.Item label="Problem File" name={'problem'} |
| 196 | + rules={[{required: true, message: "Please select a problem"}]} |
| 197 | + > |
| 198 | + <Select ref={problemRef} |
| 199 | + options={filteredFiles("PROBLEM")} |
| 200 | + |
| 201 | + /> |
| 202 | + </Form.Item> |
| 203 | + |
| 204 | + <Form.Item label="Animation file" name={'animation'} |
| 205 | + rules={[ {required: true, message: "Please select a animation file"}]} |
| 206 | + > |
| 207 | + <Select ref={animationRef} |
| 208 | + options={filteredFiles("AP")} |
| 209 | + |
| 210 | + /> |
| 211 | + </Form.Item> |
| 212 | + </Form> |
| 213 | + </Modal> |
| 214 | + |
| 215 | + </> |
| 216 | + |
| 217 | + ) |
| 218 | +} |
| 219 | +export default DemoCard; |
| 220 | + |
0 commit comments