Merge pull request #12 from SDSRV-IDP/feature/inference

Add inference page
This commit is contained in:
Vũ Khánh Dư 2024-02-01 17:10:23 +07:00 committed by GitHub Enterprise
commit 93aee28494
8 changed files with 176 additions and 13 deletions

View File

@ -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",

View File

@ -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"

View File

@ -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 />),
]; ];

View File

@ -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,
}} }}
> >

View File

@ -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",

View File

@ -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",

View File

@ -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;

View File

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