update recents and data

This commit is contained in:
phanphan 2024-06-03 13:59:26 +07:00
parent 8b629de7d9
commit 747a564efe
7 changed files with 7694 additions and 193 deletions

View File

@ -5,7 +5,7 @@ import {
} from '@ant-design/icons';
import { Button, Tag } from 'antd';
const FileCard = ({ file, isSelected, onClick, setIsReasonModalOpen }) => {
const FileCard = ({ file, isSelected, onClick }) => {
const fileName = file['File Name'];
const extensionType = fileName.split('.').pop();
let status = true;

View File

@ -0,0 +1,78 @@
// open modal show a list from local storage
import { DeleteOutlined, HistoryOutlined } from '@ant-design/icons';
import { Button, Modal, Tag } from 'antd';
import dayjs from 'dayjs';
import { useState } from 'react';
import { RecentRequest } from './const';
const RecentRequesModal = () => {
const [showModal, setShowModal] = useState(false);
const [listData, setListData] = useState<RecentRequest[]>([]);
const handleShowModal = () => {
const data = localStorage.getItem('recent-request');
if (data) {
setListData(JSON.parse(data));
}
setShowModal(true);
};
const handleCloseModal = () => {
setShowModal(false);
};
return (
<div>
<Button onClick={handleShowModal} icon={<HistoryOutlined />}>Recents </Button>
<Modal
style={{ overflow: 'auto' }}
footer={
<div style={{textAlign: 'left'}}>
{listData.length > 0 ? (
<Button
danger
style={{ marginTop: '16px' }}
icon={<DeleteOutlined />}
onClick={() => {
if (
window.confirm(
'Are you sure you want to remove all recent requests?',
)
) {
localStorage.removeItem('recent-request');
setListData([]);
}
}}
>
{' '}
Remove all
</Button>
) : (
<p>No recent requests</p>
)}
</div>
}
width={600}
height={600}
open={showModal}
title='Recent Requests'
onCancel={handleCloseModal}
>
{listData.map((item, index) => (
<div style={{ marginBottom: '4px' }}>
<a
href={`?request_id=${item.request_id}`}
target='_blank'
key={index}
>
<Tag color='blue'>{dayjs(item.time).format('hh:mm - DD/MM')}</Tag>
<span>{item.request_id}</span>
</a>
</div>
))}
</Modal>
</div>
);
};
export default RecentRequesModal;

View File

@ -1,4 +1,5 @@
import { baseURL } from 'request/api';
import { RecentRequest } from './const';
export const fetchAllRequests = async (
filterDateRange,
@ -7,7 +8,7 @@ export const fetchAllRequests = async (
filterIncludeTests,
page = 1,
page_size = 20,
max_accuracy = 100
max_accuracy = 100,
) => {
const startDate =
filterDateRange && filterDateRange[0] ? filterDateRange[0] : '';
@ -27,7 +28,7 @@ export const fetchAllRequests = async (
if (startDate && endDate) {
filterStr += `start_date=${startDate}&end_date=${endDate}&`;
}
filterStr += `max_accuracy=${max_accuracy}`
filterStr += `max_accuracy=${max_accuracy}`;
const token = localStorage.getItem('sbt-token') || '';
const data = await fetch(`${baseURL}/ctel/request_list/?${filterStr}`, {
method: 'GET',
@ -41,9 +42,7 @@ export const fetchAllRequests = async (
return data;
};
export const updateRevisedData = async (
requestID: any,
) => {
export const updateRevisedData = async (requestID: any) => {
// const requestID = ;
const token = localStorage.getItem('sbt-token') || '';
const result = await fetch(`${baseURL}/ctel/request/${requestID}/`, {
@ -52,7 +51,7 @@ export const updateRevisedData = async (
Authorization: `${JSON.parse(token)}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({"request_file_results": []}),
body: JSON.stringify({ request_file_results: [] }),
}).catch((error) => {
console.log(error);
throw error;
@ -69,14 +68,17 @@ export const updateRevisedDataByFile = async (
) => {
// const requestID = ;
const token = localStorage.getItem('sbt-token') || '';
const result = await fetch(`${baseURL}/ctel/request_image/${requestID}/${fileID}/`, {
method: 'POST',
headers: {
Authorization: `${JSON.parse(token)}`,
'Content-Type': 'application/json',
const result = await fetch(
`${baseURL}/ctel/request_image/${requestID}/${fileID}/`,
{
method: 'POST',
headers: {
Authorization: `${JSON.parse(token)}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(newRevisedData),
},
body: JSON.stringify(newRevisedData),
}).catch((error) => {
).catch((error) => {
console.log(error);
throw error;
});
@ -85,7 +87,6 @@ export const updateRevisedDataByFile = async (
}
};
export const fetchRequest = async (id) => {
const token = localStorage.getItem('sbt-token') || '';
const response = await fetch(`${baseURL}/ctel/request/${id}/`, {
@ -98,3 +99,22 @@ export const fetchRequest = async (id) => {
await response.json()
).subscription_requests[0];
};
export const addRecentRequest = (requestId: string) => {
let data = localStorage.getItem('recent-request');
let requests: RecentRequest[] = [];
if (data) {
requests = JSON.parse(data);
} else {
requests = [];
}
// find and remove element in array that has request_id equal to requestId
requests = requests.filter((request) => request.request_id !== requestId);
requests.unshift({
request_id: requestId,
time: new Date
})
localStorage.setItem('recent-request', JSON.stringify(requests))
};

View File

@ -68,3 +68,8 @@ export const SOURCE_OBJECT_NAMES = [
REVIEWED_ACCURACY,
REVIEWED_RESULT
];
export type RecentRequest = {
request_id: string,
time: Date
}

View File

@ -25,13 +25,15 @@ import {
Spin,
Tag,
} from 'antd';
import { isEmpty } from 'lodash-es';
import { useEffect, useState } from 'react';
import Lightbox from 'react-awesome-lightbox';
import 'react-awesome-lightbox/build/style.css';
import { useHotkeys } from 'react-hotkeys-hook';
import { badQualityReasonSubmit } from 'request';
import { useSearchParams } from 'react-router-dom';
import { getErrorMessage } from 'utils/error-handler';
import {
addRecentRequest,
fetchAllRequests,
fetchRequest,
updateRevisedData,
@ -50,12 +52,11 @@ import {
SUBSIDIARIES,
} from './const';
import FileCard from './FileCard';
import RecentRequest from './RecentRequest';
const ReviewPage = () => {
const [loading, setLoading] = useState(false);
const [fullscreen, setFullscreen] = useState(false);
const [isModalOpen, setIsModalOpen] = useState(false);
const [isReasonModalOpen, setIsReasonModalOpen] = useState(false);
const [selectedFileId, setSelectedFileId] = useState(0);
const [selectedFileData, setSelectedFileData] = useState(null);
const [selectedFileDataSource, setSelectedFileDataSource] = useState({});
@ -82,6 +83,47 @@ const ReviewPage = () => {
const [otherSolution, setOtherSolution] = useState('');
const [imageLoading, setImageLoading] = useState(false);
const defaultLayoutPluginInstance = defaultLayoutPlugin();
let [searchParams, setSearchParams] = useSearchParams();
useEffect(() => {
const request_id = searchParams.get('request_id');
if (request_id) {
setLoading(true);
setTotalPages(1);
setHasNextRequest(false);
const requestData = fetchRequest(request_id);
requestData
.then(async (data) => {
if (data) setCurrentRequest(data);
setAndLoadSelectedFile(data, 0);
})
.finally(() => {
setLoading(false);
});
} else {
setCurrentRequestIndex(1);
fetchAllRequests(
filterDateRange,
filterSubsidiaries,
filterReviewState,
filterIncludeTests,
1,
1,
filterAccuracy,
).then((data) => {
setTotalPages(data?.page?.total_requests);
setHasNextRequest(1 < data?.page?.total_requests);
const firstRequest = fetchRequest(
data?.subscription_requests[0].RequestID,
);
firstRequest.then(async (data) => {
if (data) setCurrentRequest(data);
setAndLoadSelectedFile(data, 0);
});
});
}
}, []);
useEffect(() => {
if (reason) {
setSolution(counter_measure_map[reason]);
@ -95,6 +137,14 @@ const ReviewPage = () => {
SOURCE_OBJECT_NAMES.forEach((name) => {
tempData[k][name] = fileContent[name][k];
});
if (
(isEmpty(tempData[k][REVIEWED_RESULT]) ||
(tempData[k][REVIEWED_RESULT].length == 1 &&
isEmpty(tempData[k][REVIEWED_RESULT][0]))) &&
!isEmpty(tempData[k][PREDICTED_RESULT])
) {
tempData[k][REVIEWED_RESULT] = tempData[k][PREDICTED_RESULT];
}
});
setSelectedFileDataSource(tempData);
@ -137,8 +187,8 @@ const ReviewPage = () => {
setSelectedFileData(fileURL);
} else {
setSelectedFileData('FAILED_TO_LOAD_FILE');
setImageLoading(false);
}
setImageLoading(false);
};
const loadCurrentRequest = (requestIndex) => {
@ -193,6 +243,10 @@ const ReviewPage = () => {
const reloadFilters = () => {
setCurrentRequestIndex(1);
if (searchParams.has('request_id')) {
searchParams.delete('request_id');
setSearchParams(searchParams);
}
fetchAllRequests(
filterDateRange,
filterSubsidiaries,
@ -210,42 +264,20 @@ const ReviewPage = () => {
firstRequest.then(async (data) => {
if (data) setCurrentRequest(data);
setAndLoadSelectedFile(data, 0);
setTimeout(() => {
loadCurrentRequest(1);
}, 500);
// setTimeout(() => {
// loadCurrentRequest(1);
// }, 500);
});
});
};
useEffect(() => {
setCurrentRequestIndex(1);
fetchAllRequests(
filterDateRange,
filterSubsidiaries,
filterReviewState,
filterIncludeTests,
1,
1,
filterAccuracy,
).then((data) => {
setTotalPages(data?.page?.total_requests);
setHasNextRequest(1 < data?.page?.total_requests);
const firstRequest = fetchRequest(
data?.subscription_requests[0].RequestID,
);
firstRequest.then(async (data) => {
if (data) setCurrentRequest(data);
setAndLoadSelectedFile(data, 0);
});
});
}, []);
const handleConfirmReview = async () => {
const isConfirmed = window.confirm(
'Are you sure you want to confirm this request is reviewed?',
);
if (isConfirmed) {
try {
addRecentRequest(currentRequest?.RequestID);
await updateRevisedData(currentRequest?.RequestID);
setCurrentRequest({
...currentRequest,
@ -465,7 +497,6 @@ const ReviewPage = () => {
setAndLoadSelectedFile(currentRequest, index);
setImageLoading(true);
}}
setIsReasonModalOpen={setIsReasonModalOpen}
/>
))}
</div>
@ -496,31 +527,32 @@ const ReviewPage = () => {
overflowX: 'visible',
}}
>
<img
style={{
maxHeight: '100%',
maxWidth: '100%',
height: 'auto',
width: 'auto',
cursor: 'zoom-in',
}}
src={selectedFileData}
alt='file'
onClick={() => setLightBox(true)}
onLoad={() => {
setImageLoading(false);
}}
/>
<Spin spinning={imageLoading}>
<img
style={{
maxHeight: '100%',
maxWidth: '100%',
height: 'auto',
width: 'auto',
cursor: 'zoom-in',
}}
src={selectedFileData}
alt='file'
onClick={() => setLightBox(true)}
onLoad={() => {
setImageLoading(false);
}}
/>
{lightBox && (
<Lightbox
image={selectedFileData}
onClose={() => setLightBox(false)}
></Lightbox>
)}
{lightBox && (
<Lightbox
image={selectedFileData}
onClose={() => setLightBox(false)}
></Lightbox>
)}
</Spin>
</div>
)}
<Spin spinning={imageLoading}></Spin>
<div
style={{
@ -538,6 +570,7 @@ const ReviewPage = () => {
alignItems: 'center',
}}
>
<RecentRequest />
<h3 style={{ margin: '0 8px ' }}>
{totalRequests
? 'No: ' + currentRequestIndex + '/' + totalRequests
@ -630,7 +663,7 @@ const ReviewPage = () => {
shape='default'
size='middle'
disabled={currentRequest && currentRequest['Is Reviewed']}
style={{ minWidth: '120px', alignSelf: 'flex-end' }}
style={{ minWidth: '120px' }}
onClick={handleConfirmReview}
>
Confirm request
@ -940,124 +973,6 @@ const ReviewPage = () => {
</div>
</Form>
</Modal>
<Modal
title={t`Review`}
open={isReasonModalOpen}
width={700}
onOk={async () => {
// call submit api
if (!reason || !solution) {
notification.warning({
message: 'Please select a reason or a solution',
});
} else {
const params = {
request_id: currentRequest?.RequestID,
request_image_id: selectedFileName.replace(/\.[^/.]+$/, ''),
};
let submitReason = reason;
let submitSolution = solution;
if (reason === 'other') {
if (!otherReason) {
notification.warning({
message: 'Please input other reason',
});
return;
}
submitReason = otherReason;
}
if (solution === 'other') {
if (!otherSolution) {
notification.warning({
message: 'Please input other solution',
});
return;
}
submitSolution = otherSolution;
}
const res = await badQualityReasonSubmit(
params,
submitReason,
submitSolution,
);
if (res.message) {
notification.success({ message: 'Update reason success' });
setIsReasonModalOpen(false);
}
}
}}
onCancel={() => {
setIsReasonModalOpen(false);
}}
>
<div style={{ display: 'flex', justifyContent: 'flex-start' }}>
<Form
style={{
marginTop: 30,
}}
>
<Form.Item name='reason' label={t`Reason for bad quality:`}>
<Select
placeholder='Select a reason'
style={{ width: 200 }}
options={REASON_BAD_QUALITY}
onChange={setReason}
value={reason}
/>
</Form.Item>
</Form>
{reason === 'other' && (
<Input
placeholder='Other reason'
value={otherReason}
onChange={(e) => {
setOtherReason(e.target.value);
}}
style={{
width: 200,
marginTop: 30,
marginBottom: 24,
marginLeft: 10,
}}
/>
)}
</div>
<div style={{ display: 'flex', justifyContent: 'flex-start' }}>
<Form>
<Form.Item name='reason' label={t`Solution:`}>
<span style={{ display: 'none' }}>
{counter_measure_map[reason]}
</span>
<Select
placeholder='Select a solution'
style={{ width: 200 }}
options={SOLUTION_BAD_QUALITY}
onChange={setSolution}
value={solution}
// defaultValue={solution}
/>
</Form.Item>
</Form>
{solution === 'other' && (
<Input
placeholder='Other solution'
value={otherSolution}
onChange={(e) => {
setOtherSolution(e.target.value);
}}
style={{
width: 200,
marginBottom: 24,
marginLeft: 10,
}}
/>
)}
</div>
</Modal>
</div>
);
};

7489
cope2n-fe/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

6
node_modules/.package-lock.json generated vendored
View File

@ -1,6 +0,0 @@
{
"name": "sbt-idp",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}