Skip to content

Commit f4407c7

Browse files
committed
[17] Add animation sample gallery
1. Add DemoCart to represent a card of demo with basic information 2. Add DemoCards to represent gallery 3. Add DragUpload to allow user can drag or upload file with more APIs 4. Fix the bug when visualContent is empty in /demo page. 5. Add a tour guide of gallery. Resolves #17 modified: package.json new file: src/pages/PageOne/DemoCard.jsx new file: src/pages/PageOne/DemoCards.jsx new file: src/pages/PageOne/DragUpload.jsx modified: src/pages/PageOne/dropAndFetch.jsx modified: src/pages/PageOne/index.js
1 parent 7f14c43 commit f4407c7

File tree

6 files changed

+496
-28
lines changed

6 files changed

+496
-28
lines changed

package.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,24 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6+
"@ant-design/icons": "^5.3.7",
67
"@babel/core": "7.12.3",
8+
"@emotion/react": "11.11.1",
9+
"@emotion/styled": "11.11.0",
710
"@inlet/react-pixi": "^6.6.5",
811
"@material-ui/core": "^4.12.3",
912
"@material-ui/icons": "^4.11.2",
1013
"@material-ui/lab": "^4.0.0-alpha.60",
1114
"@mui/material": "5.14.7",
12-
"@emotion/styled": "11.11.0",
13-
"@emotion/react": "11.11.1",
1415
"@pmmmwh/react-refresh-webpack-plugin": "0.4.3",
1516
"@svgr/webpack": "5.5.0",
1617
"@testing-library/jest-dom": "^5.11.4",
1718
"@testing-library/react": "^11.1.0",
1819
"@testing-library/user-event": "^12.1.10",
1920
"@typescript-eslint/eslint-plugin": "^4.5.0",
2021
"@typescript-eslint/parser": "^4.5.0",
22+
"antd": "^5.17.2",
23+
"axios": "^1.6.8",
2124
"babel-eslint": "^10.1.0",
2225
"babel-jest": "^26.6.0",
2326
"babel-loader": "8.1.0",
@@ -80,8 +83,8 @@
8083
"workbox-webpack-plugin": "5.1.4"
8184
},
8285
"scripts": {
83-
"start": "node scripts/start.js",
84-
"build": "node scripts/build.js",
86+
"start": "NODE_OPTIONS=--openssl-legacy-provider node scripts/start.js ",
87+
"build": "NODE_OPTIONS=--openssl-legacy-provider node scripts/build.js",
8588
"test": "jest"
8689
},
8790
"eslintConfig": {

src/pages/PageOne/DemoCard.jsx

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
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+
58+
const [form] = Form.useForm()
59+
useEffect(() => {
60+
axios.get(url,{
61+
headers:{
62+
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+
iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg=="
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+

src/pages/PageOne/DemoCards.jsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import {useEffect, useState} from "react";
2+
import axios from "axios";
3+
import {Empty, Flex} from "antd";
4+
import DemoCard from "./DemoCard";
5+
6+
7+
8+
const DemoCards = ({uploadFiles,closeGallery=()=>{}})=>{
9+
const [cardsInfo,setCardsInfo] = useState();
10+
11+
useEffect(() => {
12+
// get all the subDirectory url from Github
13+
const owner = 'Lin064';
14+
const repo = 'PL-Profiles';
15+
const path = '';
16+
const branch = 'main';
17+
const githubApiUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=${branch}`;
18+
19+
axios.get(githubApiUrl,{
20+
headers:{
21+
22+
}
23+
})
24+
.then(response => {
25+
const files = response.data;
26+
let folders = files.map(item=>{
27+
if(item.type=='dir'){
28+
return {
29+
name: item.name,
30+
url: item.url
31+
}
32+
}
33+
})
34+
setCardsInfo(folders.filter(item=>item))
35+
})
36+
37+
}, []);
38+
39+
return(
40+
<>
41+
{
42+
(!cardsInfo || cardsInfo.length == 0)
43+
? <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
44+
:<Flex justify={'center'} wrap={"wrap"} align={'center'} gap={40}>
45+
{
46+
cardsInfo.map((item,index)=>{
47+
return <DemoCard title={item.name} url={item.url} isFirstCard={index === 0}
48+
closeGallery={closeGallery}
49+
uploadFiles={uploadFiles}/>
50+
})
51+
}
52+
</Flex>
53+
}
54+
55+
</>
56+
)
57+
}
58+
export default DemoCards;

0 commit comments

Comments
 (0)