diff --git a/cope2n-fe/package-lock.json b/cope2n-fe/package-lock.json index 0991e8f..144140f 100644 --- a/cope2n-fe/package-lock.json +++ b/cope2n-fe/package-lock.json @@ -24,6 +24,7 @@ "react": "^18.2.0", "react-chartjs-2": "^5.2.0", "react-dom": "^18.2.0", + "react-json-view-lite": "^1.2.1", "react-router-dom": "^6.6.1", "styled-components": "^5.3.6", "uuid": "^9.0.0" @@ -10192,6 +10193,17 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, + "node_modules/react-json-view-lite": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.2.1.tgz", + "integrity": "sha512-Itc0g86fytOmKZoIoJyGgvNqohWSbh3NXIKNgH6W6FT9PC1ck4xas1tT3Rr/b3UlFXyA9Jjaw9QSXdZy2JwGMQ==", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-refresh": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", diff --git a/cope2n-fe/package.json b/cope2n-fe/package.json index 4054fdc..314d175 100644 --- a/cope2n-fe/package.json +++ b/cope2n-fe/package.json @@ -2,7 +2,7 @@ "name": "sbt-ui", "version": "0.1.0", "scripts": { - "start": "NODE_ENV=development npm run extract && npm run compile && vite --host", + "start": "NODE_ENV=development vite --host", "build": "NODE_ENV=production npm run extract && npm run compile && tsc && vite build", "serve": "vite preview", "extract": "lingui extract --clean", @@ -42,6 +42,7 @@ "react": "^18.2.0", "react-chartjs-2": "^5.2.0", "react-dom": "^18.2.0", + "react-json-view-lite": "^1.2.1", "react-router-dom": "^6.6.1", "styled-components": "^5.3.6", "uuid": "^9.0.0" diff --git a/cope2n-fe/src/components/left-menu/index.tsx b/cope2n-fe/src/components/left-menu/index.tsx index b196d56..4f1bebd 100644 --- a/cope2n-fe/src/components/left-menu/index.tsx +++ b/cope2n-fe/src/components/left-menu/index.tsx @@ -1,4 +1,4 @@ -import { AppstoreOutlined, BarChartOutlined } from '@ant-design/icons'; +import { AppstoreOutlined, BarChartOutlined, RotateRightOutlined } from '@ant-design/icons'; import { t } from '@lingui/macro'; import { Menu, MenuProps } from 'antd'; import React from 'react'; @@ -34,9 +34,9 @@ function LeftMenu() { const generalSubItems = [ getItem(t`Dashboard`, '/dashboard', ), - // getItem(t`Inference`, '/inference', ), // getItem(t`Reviews`, '/reviews', ), getItem(t`Reports`, '/reports', ), + getItem(t`Inference`, '/inference', ), // getItem(t`Users`, '/users', ), ]; diff --git a/cope2n-fe/src/layouts/main-layout.tsx b/cope2n-fe/src/layouts/main-layout.tsx index d78728a..c77c5e0 100644 --- a/cope2n-fe/src/layouts/main-layout.tsx +++ b/cope2n-fe/src/layouts/main-layout.tsx @@ -109,7 +109,7 @@ export const MainLayout = ({ children }: { children: React.ReactNode }) => { @@ -119,7 +119,7 @@ export const MainLayout = ({ children }: { children: React.ReactNode }) => { style={{ height: '100%', overflow: 'auto', - padding: 16, + padding: 32, background: colorBgContainer, }} > diff --git a/cope2n-fe/src/locales/en/messages.json b/cope2n-fe/src/locales/en/messages.json index b0999d4..c5f0236 100644 --- a/cope2n-fe/src/locales/en/messages.json +++ b/cope2n-fe/src/locales/en/messages.json @@ -7,6 +7,7 @@ "Download Report": "Download Report", "Email format is not correct": "Email format is not correct", "English": "English", + "Inference": "Inference", "Language": "Language", "Login": "Login", "Logout": "Logout", diff --git a/cope2n-fe/src/locales/vi/messages.json b/cope2n-fe/src/locales/vi/messages.json index 25d7426..4618c98 100644 --- a/cope2n-fe/src/locales/vi/messages.json +++ b/cope2n-fe/src/locales/vi/messages.json @@ -7,6 +7,7 @@ "Download Report": "", "Email format is not correct": "Định dạng email không hợp lệ", "English": "Tiếng Anh", + "Inference": "", "Language": "Ngôn ngữ", "Login": "Đăng nhập", "Logout": "Đăng xuất", diff --git a/cope2n-fe/src/pages/inference/index.tsx b/cope2n-fe/src/pages/inference/index.tsx index ba314b2..7bd18f1 100644 --- a/cope2n-fe/src/pages/inference/index.tsx +++ b/cope2n-fe/src/pages/inference/index.tsx @@ -1,5 +1,153 @@ -function Inference() { - return
Inference
; -} +import { t } from '@lingui/macro'; +import { Button, message, Upload } from 'antd'; +import { SbtPageHeader } from 'components/page-header'; +import { useState } from 'react'; +import { UploadOutlined } from '@ant-design/icons'; +import type { GetProp, UploadFile, UploadProps } from 'antd'; +import { JsonView, allExpanded, defaultStyles } from 'react-json-view-lite'; +import 'react-json-view-lite/dist/index.css'; +import { baseURL } from "request/api" -export default Inference; +type FileType = Parameters>[0]; + +const InferencePage = () => { + const [invoiceFiles, setInvoiceFiles] = useState([]); + const [imei1Files, setImei1Files] = useState([]); + const [imei2Files, setImei2Files] = useState([]); + const [uploading, setUploading] = useState(false); + const [jsonData, setJsonData] = useState({}); + const [finishedProcessing, setFinishedProcessing] = useState(false); + + const handleUpload = () => { + const formData = new FormData(); + if (invoiceFiles.length > 0) { + formData.append('invoice_file', invoiceFiles[0] as FileType); + } + if (imei1Files.length > 0) { + formData.append('imei_files', imei1Files[0] as FileType); + } + if (imei2Files.length > 0) { + formData.append('imei_files', imei2Files[0] as FileType); + } + formData.append('is_test_request', 'true'); + setUploading(true); + setJsonData({ + "message": "Please wait..." + }) + const token = localStorage.getItem('sbt-token') || ''; + fetch(`${baseURL}/ctel/images/process_sync/`, { + method: 'POST', + body: formData, + headers: { + "Authorization": `${JSON.parse(token)}` + } + }) + .then(async(res) => { + const data = await res.json(); + setJsonData(data); + setFinishedProcessing(true); + return data; + }) + .then(() => { + message.success('Upload successfully.'); + }) + .catch(() => { + message.error('Upload failed.'); + }) + .finally(() => { + setUploading(false); + }); + }; + + return ( + <> + +
+ { + if (finishedProcessing) return; + setInvoiceFiles([]) + }} + beforeUpload={(file) => { + if (finishedProcessing) return; + setInvoiceFiles([file]) + return false; + }} + fileList={invoiceFiles} + > + Invoice File: + +
+
+ { + if (finishedProcessing) return; + setImei1Files([]) + }} + beforeUpload={(file) => { + if (finishedProcessing) return; + setImei1Files([file]) + return false; + }} + fileList={imei1Files} + > + IMEI File 1: + +
+
+ { + if (finishedProcessing) return; + setImei2Files([]) + }} + beforeUpload={(file) => { + if (finishedProcessing) return; + setImei2Files([file]) + return false; + }} + fileList={imei2Files} + > + IMEI File 2: + +
+ {!finishedProcessing && } + {finishedProcessing && } +
+

Result:

+ +
+ + ); +}; + +export default InferencePage; diff --git a/cope2n-fe/src/request/api.ts b/cope2n-fe/src/request/api.ts index dbe3a29..a0945df 100644 --- a/cope2n-fe/src/request/api.ts +++ b/cope2n-fe/src/request/api.ts @@ -11,18 +11,18 @@ const environment = process.env.NODE_ENV; const AXIOS_TIMEOUT_MS = 30 * 60 * 1000; // This config sastified long-live upload file request const EXPIRED_PASSWORD_SIGNAL = 'expired_password'; +export const baseURL = environment === 'development' ? 'http://42.96.42.13:9000/api' : '/api'; + export const API = axios.create({ timeout: AXIOS_TIMEOUT_MS, - baseURL: - environment === 'development' ? 'http://42.96.42.13:9000/api' : '/api', + baseURL: baseURL, maxContentLength: Number.MAX_SAFE_INTEGER, maxBodyLength: Number.MAX_SAFE_INTEGER, }); export const PublicAPI = axios.create({ timeout: AXIOS_TIMEOUT_MS, - baseURL: - environment === 'development' ? 'http://42.96.42.13:9000/api' : '/api', + baseURL: baseURL, }); // interceptor to handle locale header