Merge pull request #12 from SDSRV-IDP/feature/inference
Add inference page
This commit is contained in:
commit
93aee28494
12
cope2n-fe/package-lock.json
generated
12
cope2n-fe/package-lock.json
generated
@ -24,6 +24,7 @@
|
|||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-chartjs-2": "^5.2.0",
|
"react-chartjs-2": "^5.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-json-view-lite": "^1.2.1",
|
||||||
"react-router-dom": "^6.6.1",
|
"react-router-dom": "^6.6.1",
|
||||||
"styled-components": "^5.3.6",
|
"styled-components": "^5.3.6",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
@ -10192,6 +10193,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
"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": {
|
"node_modules/react-refresh": {
|
||||||
"version": "0.14.0",
|
"version": "0.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"name": "sbt-ui",
|
"name": "sbt-ui",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"scripts": {
|
"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",
|
"build": "NODE_ENV=production npm run extract && npm run compile && tsc && vite build",
|
||||||
"serve": "vite preview",
|
"serve": "vite preview",
|
||||||
"extract": "lingui extract --clean",
|
"extract": "lingui extract --clean",
|
||||||
@ -42,6 +42,7 @@
|
|||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-chartjs-2": "^5.2.0",
|
"react-chartjs-2": "^5.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
"react-json-view-lite": "^1.2.1",
|
||||||
"react-router-dom": "^6.6.1",
|
"react-router-dom": "^6.6.1",
|
||||||
"styled-components": "^5.3.6",
|
"styled-components": "^5.3.6",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
|
@ -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 { t } from '@lingui/macro';
|
||||||
import { Menu, MenuProps } from 'antd';
|
import { Menu, MenuProps } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@ -34,9 +34,9 @@ function LeftMenu() {
|
|||||||
|
|
||||||
const generalSubItems = [
|
const generalSubItems = [
|
||||||
getItem(t`Dashboard`, '/dashboard', <AppstoreOutlined />),
|
getItem(t`Dashboard`, '/dashboard', <AppstoreOutlined />),
|
||||||
// getItem(t`Inference`, '/inference', <RotateRightOutlined />),
|
|
||||||
// getItem(t`Reviews`, '/reviews', <FileSearchOutlined />),
|
// getItem(t`Reviews`, '/reviews', <FileSearchOutlined />),
|
||||||
getItem(t`Reports`, '/reports', <BarChartOutlined />),
|
getItem(t`Reports`, '/reports', <BarChartOutlined />),
|
||||||
|
getItem(t`Inference`, '/inference', <RotateRightOutlined />),
|
||||||
// getItem(t`Users`, '/users', <UsergroupAddOutlined />),
|
// getItem(t`Users`, '/users', <UsergroupAddOutlined />),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ export const MainLayout = ({ children }: { children: React.ReactNode }) => {
|
|||||||
<Layout.Sider
|
<Layout.Sider
|
||||||
style={{
|
style={{
|
||||||
background: colorBgContainer,
|
background: colorBgContainer,
|
||||||
padding: 4,
|
padding: 8,
|
||||||
borderRight: `1px solid ${colorBorder}`,
|
borderRight: `1px solid ${colorBorder}`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -119,7 +119,7 @@ export const MainLayout = ({ children }: { children: React.ReactNode }) => {
|
|||||||
style={{
|
style={{
|
||||||
height: '100%',
|
height: '100%',
|
||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
padding: 16,
|
padding: 32,
|
||||||
background: colorBgContainer,
|
background: colorBgContainer,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
"Download Report": "Download Report",
|
"Download Report": "Download Report",
|
||||||
"Email format is not correct": "Email format is not correct",
|
"Email format is not correct": "Email format is not correct",
|
||||||
"English": "English",
|
"English": "English",
|
||||||
|
"Inference": "Inference",
|
||||||
"Language": "Language",
|
"Language": "Language",
|
||||||
"Login": "Login",
|
"Login": "Login",
|
||||||
"Logout": "Logout",
|
"Logout": "Logout",
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
"Download Report": "",
|
"Download Report": "",
|
||||||
"Email format is not correct": "Định dạng email không hợp lệ",
|
"Email format is not correct": "Định dạng email không hợp lệ",
|
||||||
"English": "Tiếng Anh",
|
"English": "Tiếng Anh",
|
||||||
|
"Inference": "",
|
||||||
"Language": "Ngôn ngữ",
|
"Language": "Ngôn ngữ",
|
||||||
"Login": "Đăng nhập",
|
"Login": "Đăng nhập",
|
||||||
"Logout": "Đăng xuất",
|
"Logout": "Đăng xuất",
|
||||||
|
@ -1,5 +1,153 @@
|
|||||||
function Inference() {
|
import { t } from '@lingui/macro';
|
||||||
return <div>Inference</div>;
|
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<GetProp<UploadProps, 'beforeUpload'>>[0];
|
||||||
|
|
||||||
|
const InferencePage = () => {
|
||||||
|
const [invoiceFiles, setInvoiceFiles] = useState<UploadFile[]>([]);
|
||||||
|
const [imei1Files, setImei1Files] = useState<UploadFile[]>([]);
|
||||||
|
const [imei2Files, setImei2Files] = useState<UploadFile[]>([]);
|
||||||
|
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 (
|
||||||
|
<>
|
||||||
|
<SbtPageHeader
|
||||||
|
title={t`Inference`}
|
||||||
|
/>
|
||||||
|
<div style={{
|
||||||
|
paddingTop: "0.5rem"
|
||||||
|
}}>
|
||||||
|
<Upload
|
||||||
|
onRemove={(file) => {
|
||||||
|
if (finishedProcessing) return;
|
||||||
|
setInvoiceFiles([])
|
||||||
|
}}
|
||||||
|
beforeUpload={(file) => {
|
||||||
|
if (finishedProcessing) return;
|
||||||
|
setInvoiceFiles([file])
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
|
fileList={invoiceFiles}
|
||||||
|
>
|
||||||
|
Invoice File: <Button disabled={finishedProcessing} icon={<UploadOutlined />}>Select Image/PDF</Button>
|
||||||
|
</Upload>
|
||||||
|
</div>
|
||||||
|
<div style={{
|
||||||
|
paddingTop: "0.5rem"
|
||||||
|
}}>
|
||||||
|
<Upload
|
||||||
|
onRemove={(file) => {
|
||||||
|
if (finishedProcessing) return;
|
||||||
|
setImei1Files([])
|
||||||
|
}}
|
||||||
|
beforeUpload={(file) => {
|
||||||
|
if (finishedProcessing) return;
|
||||||
|
setImei1Files([file])
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
|
fileList={imei1Files}
|
||||||
|
>
|
||||||
|
IMEI File 1: <Button disabled={finishedProcessing} icon={<UploadOutlined />}>Select Image</Button>
|
||||||
|
</Upload>
|
||||||
|
</div>
|
||||||
|
<div style={{
|
||||||
|
paddingTop: "0.5rem"
|
||||||
|
}}>
|
||||||
|
<Upload
|
||||||
|
onRemove={(file) => {
|
||||||
|
if (finishedProcessing) return;
|
||||||
|
setImei2Files([])
|
||||||
|
}}
|
||||||
|
beforeUpload={(file) => {
|
||||||
|
if (finishedProcessing) return;
|
||||||
|
setImei2Files([file])
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
|
fileList={imei2Files}
|
||||||
|
>
|
||||||
|
IMEI File 2: <Button disabled={finishedProcessing} icon={<UploadOutlined />}>Select Image</Button>
|
||||||
|
</Upload>
|
||||||
|
</div>
|
||||||
|
{!finishedProcessing && <Button
|
||||||
|
type="primary"
|
||||||
|
onClick={handleUpload}
|
||||||
|
disabled={imei1Files.length === 0 && imei2Files.length === 0}
|
||||||
|
loading={uploading}
|
||||||
|
style={{ marginTop: 16, marginBottom: 24 }}
|
||||||
|
>
|
||||||
|
{uploading ? 'Uploading' : 'Process Data'}
|
||||||
|
</Button>}
|
||||||
|
{finishedProcessing && <Button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
setFinishedProcessing(false);
|
||||||
|
setJsonData({});
|
||||||
|
setInvoiceFiles([]);
|
||||||
|
setImei1Files([]);
|
||||||
|
setImei2Files([]);
|
||||||
|
}}
|
||||||
|
style={{ marginTop: 16, marginBottom: 24 }}
|
||||||
|
>
|
||||||
|
Reset
|
||||||
|
</Button>}
|
||||||
|
<div style={{
|
||||||
|
paddingTop: "0.5rem"
|
||||||
|
}}>
|
||||||
|
<h3>Result:</h3>
|
||||||
|
<JsonView data={jsonData} shouldExpandNode={allExpanded} style={defaultStyles} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InferencePage;
|
||||||
|
@ -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 AXIOS_TIMEOUT_MS = 30 * 60 * 1000; // This config sastified long-live upload file request
|
||||||
const EXPIRED_PASSWORD_SIGNAL = 'expired_password';
|
const EXPIRED_PASSWORD_SIGNAL = 'expired_password';
|
||||||
|
|
||||||
|
export const baseURL = environment === 'development' ? 'http://42.96.42.13:9000/api' : '/api';
|
||||||
|
|
||||||
export const API = axios.create({
|
export const API = axios.create({
|
||||||
timeout: AXIOS_TIMEOUT_MS,
|
timeout: AXIOS_TIMEOUT_MS,
|
||||||
baseURL:
|
baseURL: baseURL,
|
||||||
environment === 'development' ? 'http://42.96.42.13:9000/api' : '/api',
|
|
||||||
maxContentLength: Number.MAX_SAFE_INTEGER,
|
maxContentLength: Number.MAX_SAFE_INTEGER,
|
||||||
maxBodyLength: Number.MAX_SAFE_INTEGER,
|
maxBodyLength: Number.MAX_SAFE_INTEGER,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const PublicAPI = axios.create({
|
export const PublicAPI = axios.create({
|
||||||
timeout: AXIOS_TIMEOUT_MS,
|
timeout: AXIOS_TIMEOUT_MS,
|
||||||
baseURL:
|
baseURL: baseURL,
|
||||||
environment === 'development' ? 'http://42.96.42.13:9000/api' : '/api',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// interceptor to handle locale header
|
// interceptor to handle locale header
|
||||||
|
Loading…
Reference in New Issue
Block a user