Skip to content

Commit b2b2720

Browse files
authored
Merge pull request #19 from Lin064/feature/gallery
Create a gallery feature to load demo quickly
2 parents ad6d4c4 + 7ac6789 commit b2b2720

File tree

6 files changed

+494
-26
lines changed

6 files changed

+494
-26
lines changed

package.json

Lines changed: 5 additions & 2 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",

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+
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+

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 = 'planimation';
14+
const repo = 'documentation';
15+
const path = 'AnimationProfiles';
16+
const branch = 'master';
17+
const githubApiUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=${branch}`;
18+
const token = "ghp_WkIVNPY9eR5xZ3iLCsy" + "X2ttHsGuE321WyoPV"
19+
axios.get(githubApiUrl,{
20+
headers:{
21+
Authorization: `token ${token}`
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;

src/pages/PageOne/DragUpload.jsx

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { message, Upload } from 'antd';
2+
import {InboxOutlined, PaperClipOutlined} from "@ant-design/icons";
3+
import React, {useEffect, useState} from "react";
4+
import css from "../../Styles/index.module.less";
5+
const { Dragger } = Upload;
6+
7+
8+
const DragUpload = ({ name, desc, fileType, onFileLoad,initialFile})=>{
9+
const [fileList,setFileList] = useState([]);
10+
11+
12+
useEffect(() => {
13+
if(initialFile === undefined) return;
14+
setFileList([{...initialFile}])
15+
onFileLoad(name, initialFile.originFileObj)
16+
17+
}, [initialFile]);
18+
19+
const props = {
20+
21+
onChange(info) {
22+
// delete operation
23+
if(info.fileList.length==0){
24+
setFileList([])
25+
onFileLoad(name, undefined);
26+
return;
27+
}
28+
29+
30+
// add or change operation
31+
if (!info.file.name.endsWith(fileType)) {
32+
message.error("Wrong type error")
33+
return;
34+
}
35+
36+
37+
38+
onFileLoad(name, info.file);
39+
40+
info.file.url = URL.createObjectURL(info.file);
41+
info.file.originFileObj = info.file
42+
43+
setFileList([info.file])
44+
},
45+
beforeUpload(file){return false;},
46+
onPreview(file){
47+
48+
const reader = new FileReader();
49+
reader.onload = (e) => {
50+
const newWindow = window.open();
51+
newWindow.document.write('<pre>' + e.target.result + '</pre>');
52+
newWindow.document.close(); // 确保文档加载完成
53+
};
54+
reader.readAsText(file.originFileObj);
55+
}
56+
57+
};
58+
59+
return(
60+
<div className={css.dropzoneBox}>
61+
<div>
62+
<div className={css.fileTitle}>
63+
<b>{name} File </b>
64+
</div>
65+
<div className={css.fileDesc}>{desc}</div>
66+
</div>
67+
<Dragger {...props} style={{minWidth:350, minHeight:200}}
68+
fileList={fileList}
69+
accept={'.pddl'}
70+
>
71+
<p className="ant-upload-drag-icon">
72+
{fileList.length>0?<PaperClipOutlined />:<InboxOutlined />}
73+
</p>
74+
<p className="ant-upload-text">Click or drag file to this area to upload</p>
75+
<p className="ant-upload-hint">
76+
{`In this area, You should upload ${name} File`}
77+
</p>
78+
</Dragger>
79+
</div>
80+
81+
)
82+
}
83+
export default DragUpload;

0 commit comments

Comments
 (0)