Skip to content

Commit 3f31935

Browse files
author
JerryLiu
committed
feat: JSON Upload
1 parent f0d01fd commit 3f31935

File tree

14 files changed

+399
-82
lines changed

14 files changed

+399
-82
lines changed

js/src/api/axios.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ const instance: AxiosInstance = axios.create({
1414
instance.interceptors.response.use(
1515
function (response) {
1616
// Any status code that lie within the range of 2xx cause this function to trigger
17-
17+
// console.log('response', response)
1818
const type = response?.data?.type
19-
const method = response.config.method
20-
const typeText = getTypeText(type)
19+
const method = response?.config?.method || ''
20+
const statusText = response?.statusText
21+
const typeText = getTypeText(type, method, statusText)
2122
if (method !== 'get') {
2223
notification.success({
2324
message: `${typeText}成功`,
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
import { ChangeEvent, useState } from 'react'
2+
import {
3+
UploadOutlined,
4+
ImportOutlined,
5+
LoadingOutlined,
6+
} from '@ant-design/icons'
7+
import {
8+
Upload,
9+
UploadProps,
10+
Button,
11+
Modal,
12+
Input,
13+
Row,
14+
Col,
15+
Divider,
16+
} from 'antd'
17+
import { createResource } from '@/api'
18+
import { addKey } from '@/utils'
19+
import { useQueryClient } from '@tanstack/react-query'
20+
import { Link } from 'react-router-dom'
21+
22+
const baseUrl = process.env.BASE_URL || ''
23+
24+
const JsonUpload = () => {
25+
const [
26+
isLoading,
27+
setIsLoading,
28+
] = useState(false)
29+
const [
30+
showLink,
31+
setShowLink,
32+
] = useState(false)
33+
34+
const [
35+
theProjectId,
36+
setTheProjectId,
37+
] = useState<number>(0)
38+
39+
const [
40+
jsonContent,
41+
setJsonContent,
42+
] = useState<string>('')
43+
44+
const [
45+
isJsonUploadModalOpen,
46+
setIsJsonUploadModalOpen,
47+
] = useState(false)
48+
49+
const queryClient = useQueryClient()
50+
51+
const showJsonUploadModal = () => {
52+
setIsJsonUploadModalOpen(true)
53+
}
54+
55+
const handleJsonUploadOk = () => {
56+
setIsJsonUploadModalOpen(false)
57+
}
58+
59+
const handleJsonUploadCancel = () => {
60+
setIsJsonUploadModalOpen(false)
61+
setShowLink(false)
62+
}
63+
64+
const props: UploadProps = {
65+
accept: '.json',
66+
name: 'file',
67+
multiple: false,
68+
69+
onChange({ file }) {
70+
setIsLoading(true)
71+
72+
const reader = new FileReader()
73+
reader.onload = (event) => {
74+
const content = event?.target?.result || '{}'
75+
setJsonContent(content as string)
76+
// setJsonContent(JSON.parse(content as string))
77+
setIsLoading(false)
78+
}
79+
if (file?.originFileObj) {
80+
reader.readAsText(file.originFileObj)
81+
}
82+
},
83+
onDrop(e) {
84+
console.log('Dropped files', e.dataTransfer.files)
85+
},
86+
maxCount: 1,
87+
showUploadList: false,
88+
className: 'block w-full',
89+
}
90+
91+
const handleImport = async () => {
92+
//add key & groupKey back
93+
const scopesWithoutKey = JSON.parse(jsonContent || '{}')
94+
const scopes = addKey(scopesWithoutKey)
95+
96+
const createResult = await createResource({
97+
resource: 'carbon-project',
98+
args: {
99+
title: scopes?.info?.title || '○○○○股份有限公司',
100+
content: scopes?.info?.content || '',
101+
status: 'publish',
102+
featured_media: scopes?.info?.imgData?.attachmentId || 0,
103+
meta: {
104+
project_data: JSON.stringify(scopes || {}),
105+
},
106+
},
107+
})
108+
if (createResult?.status === 201 || createResult?.status === 200) {
109+
queryClient.invalidateQueries([
110+
'get_carbon-projects',
111+
])
112+
113+
setShowLink(true)
114+
setTheProjectId(createResult?.data?.id || 0)
115+
} else {
116+
console.log('createResult', createResult)
117+
}
118+
}
119+
120+
const handleTextAreaChange = (e: ChangeEvent<any>) => {
121+
const text = e?.target?.value || ''
122+
setJsonContent(text)
123+
}
124+
125+
return (
126+
<>
127+
<Button icon={<UploadOutlined />} onClick={showJsonUploadModal}>
128+
使用 JSON 檔案上傳
129+
</Button>
130+
<Modal
131+
title="匯入專案 JSON 數據"
132+
centered
133+
open={isJsonUploadModalOpen}
134+
onOk={handleJsonUploadOk}
135+
onCancel={handleJsonUploadCancel}
136+
footer={null}
137+
>
138+
<Input.TextArea
139+
disabled={isLoading}
140+
value={jsonContent}
141+
rows={6}
142+
onChange={handleTextAreaChange}
143+
/>
144+
<Row gutter={24} className="mt-4 json-upload">
145+
<Col span={12}>
146+
<Upload {...props}>
147+
<Button
148+
className="w-full"
149+
icon={isLoading ? <LoadingOutlined /> : <UploadOutlined />}
150+
>
151+
使用 JSON 檔案上傳
152+
</Button>
153+
</Upload>
154+
</Col>
155+
<Col span={12}>
156+
<Button
157+
type="primary"
158+
className="w-full"
159+
onClick={handleImport}
160+
icon={<ImportOutlined />}
161+
>
162+
確認匯入 JSON
163+
</Button>
164+
</Col>
165+
{showLink && (
166+
<Col span={24} className="mt-4">
167+
<Divider plain>已成功創建專案</Divider>
168+
<Link to={`${baseUrl}check`} state={{ id: theProjectId }}>
169+
<Button type="primary" className="w-full">
170+
立即查看專案
171+
</Button>
172+
</Link>
173+
</Col>
174+
)}
175+
</Row>
176+
</Modal>
177+
</>
178+
)
179+
}
180+
181+
export default JsonUpload
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { z } from 'zod'
2+
3+
const ZJsonUpload = z.object({
4+
scopeI: z
5+
.object({
6+
groupKey: z.string(),
7+
groupName: z.string(),
8+
dataSource: z
9+
.object({
10+
key: z.string(),
11+
equipment: z.string(),
12+
gwp: z.string(),
13+
yearlyAmount: z.number().min(0),
14+
ar5: z.number().min(0),
15+
co2e: z.number().min(0),
16+
carbonTonsPerYear: z.number().min(0),
17+
period: z.union([
18+
z.literal('yearly'),
19+
z.literal('monthly'),
20+
z.literal('hourly'),
21+
]),
22+
monthlyAmount: z.number().min(0).array().length(12),
23+
hourlyAmount: z.number().min(0),
24+
unit: z.union([
25+
z.literal('kg'),
26+
z.literal('tons'),
27+
]),
28+
})
29+
.array(),
30+
})
31+
.array(),
32+
scopeII: z.object({}).array(),
33+
info: z.object({
34+
title: z.string(),
35+
content: z.string(),
36+
companyCategory: z.string(),
37+
}),
38+
})

js/src/components/ProjectsImportButton/index.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react'
22
import { UploadOutlined } from '@ant-design/icons'
33
import { Button, message, Upload, UploadProps } from 'antd'
4+
import JsonUpload from '../JsonUpload'
45

56
const props: UploadProps = {
67
name: 'file',
@@ -21,9 +22,9 @@ const props: UploadProps = {
2122
}
2223

2324
const ProjectsImportButton: React.FC = () => (
24-
<Upload {...props}>
25-
<Button icon={<UploadOutlined />}>使用 JSON 檔案上傳</Button>
26-
</Upload>
25+
<>
26+
<JsonUpload />
27+
</>
2728
)
2829

2930
export default ProjectsImportButton

js/src/global.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
overflow-y: auto;
1919
overflow-x: hidden;
2020
}
21+
.json-upload {
22+
.ant-upload {
23+
width: 100%;
24+
}
25+
}
2126

2227
@media print {
2328
html,

js/src/hooks/useMany.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,19 @@ const useMany = (options: {
3030
}),
3131
options.queryOptions || {},
3232
)
33-
const { isSuccess, data } = getResult
33+
const { isSuccess, data, isFetching } = getResult
3434

3535
useEffect(() => {
36+
console.log('changeddddd')
3637
if (data) {
38+
console.log('set data')
39+
3740
setFetchedData(data.data || null)
3841
}
39-
}, [isSuccess])
42+
}, [
43+
isSuccess,
44+
isFetching,
45+
])
4046

4147
return fetchedData
4248
}

js/src/pages/Check/Export/index.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import ClipboardJS from 'clipboard'
1010
import { DownloadOutlined, CopyOutlined } from '@ant-design/icons'
1111
import { flatten } from 'lodash-es'
1212
import { useReactToPrint } from 'react-to-print'
13+
import { getCopyableJson, removeKey } from '@/utils'
1314

1415
new ClipboardJS('.button')
1516

@@ -79,10 +80,11 @@ const Export = () => {
7980
setIsExportModalOpen(true)
8081
}
8182

82-
const jsonString = JSON.stringify(JSON.stringify(scopes || '{}')).replace(
83-
/\\/g,
84-
' ',
85-
)
83+
//TODO scopeII remove key
84+
//remove key
85+
const scopesForDownload = removeKey(scopes)
86+
87+
const jsonString = getCopyableJson(scopesForDownload || '{}')
8688

8789
const download = (text: string) => () => {
8890
const blob = new Blob([text], { type: 'text/plain' })
@@ -130,7 +132,7 @@ const Export = () => {
130132
})}
131133
</div>
132134
<Row className="my-8" gutter={24}>
133-
<Col span={24} lg={{ span: 12 }}>
135+
<Col className="my-2" span={24} lg={{ span: 12 }}>
134136
<Button
135137
type="primary"
136138
size="large"
@@ -140,7 +142,7 @@ const Export = () => {
140142
匯出為 PDF
141143
</Button>
142144
</Col>
143-
<Col span={24} lg={{ span: 12 }}>
145+
<Col className="my-2" span={24} lg={{ span: 12 }}>
144146
<Button
145147
type="default"
146148
size="large"

js/src/pages/Check/components/EditProjectButtons/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const EditProjectButtons: React.FC<{
4747
})
4848
if (deleteResult?.status === 200) {
4949
setIsDeleteProjectModalOpen(false)
50-
navigate('')
50+
navigate(process.env.BASE_URL || '/home/carbon-check-app/')
5151
} else {
5252
console.log('deleteResult', deleteResult)
5353
}

0 commit comments

Comments
 (0)