Compare commits
29 Commits
3f8739d035
...
1a436dba8a
Author | SHA1 | Date | |
---|---|---|---|
1a436dba8a | |||
|
aaf028054c | ||
ab1ec7a59d | |||
a106c96f2a | |||
15a9f31eed | |||
|
7bfb1c46b3 | ||
|
53654197af | ||
|
7767f37c52 | ||
d2e0c96ce2 | |||
fe56fb91a4 | |||
|
590a08c119 | ||
|
7841a775b7 | ||
|
e51994958e | ||
478e09408d | |||
1867259d5e | |||
55c81a2dcf | |||
5fb227b2f2 | |||
|
c7ca48bbd8 | ||
|
a6f6eb5a34 | ||
bd703c6eb5 | |||
|
8b3cde536b | ||
|
87634b3d3f | ||
40cd3189ac | |||
cdfdb0c25b | |||
dbf9a889da | |||
69ac10dec3 | |||
a282e9c505 | |||
669bef9528 | |||
3b6b7f9a30 |
@ -14,7 +14,7 @@ RUN pip install --upgrade pip
|
|||||||
RUN pip install uvicorn gunicorn Celery
|
RUN pip install uvicorn gunicorn Celery
|
||||||
|
|
||||||
# For intergration with sdskvu
|
# For intergration with sdskvu
|
||||||
RUN pip install pip install torch==1.13.1+cu116 torchvision==0.14.1+cu116 torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cu116
|
RUN pip install torch==1.13.1+cu116 torchvision==0.14.1+cu116 torchaudio==0.13.1 --extra-index-url https://download.pytorch.org/whl/cu116
|
||||||
RUN pip install -U openmim==0.3.7 --no-cache-dir
|
RUN pip install -U openmim==0.3.7 --no-cache-dir
|
||||||
RUN mim install mmcv-full==1.7.2
|
RUN mim install mmcv-full==1.7.2
|
||||||
# RUN pip install fastdeploy-gpu-python==1.0.7 -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html --no-cache-dir
|
# RUN pip install fastdeploy-gpu-python==1.0.7 -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html --no-cache-dir
|
||||||
|
@ -245,6 +245,7 @@ FIELDS_BY_SUB = {
|
|||||||
BAD_THRESHOLD = 0.75
|
BAD_THRESHOLD = 0.75
|
||||||
NEED_REVIEW = 1.0
|
NEED_REVIEW = 1.0
|
||||||
|
|
||||||
|
DOC_TYPES = ["imei", "invoice"]
|
||||||
SUB_FOR_BILLING = ["all", "seao"]
|
SUB_FOR_BILLING = ["all", "seao"]
|
||||||
FIELD = ["imei_number", "purchase_date", "retailername", "sold_to_party", "invoice_no"]
|
FIELD = ["imei_number", "purchase_date", "retailername", "sold_to_party", "invoice_no"]
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ class AccuracyViewSet(viewsets.ViewSet):
|
|||||||
description='Which subsidiary to be included',
|
description='Which subsidiary to be included',
|
||||||
type=OpenApiTypes.STR,
|
type=OpenApiTypes.STR,
|
||||||
enum=list(settings.SUBS.keys()),
|
enum=list(settings.SUBS.keys()),
|
||||||
|
required=True
|
||||||
),
|
),
|
||||||
OpenApiParameter(
|
OpenApiParameter(
|
||||||
name='request_id',
|
name='request_id',
|
||||||
@ -112,6 +113,42 @@ class AccuracyViewSet(viewsets.ViewSet):
|
|||||||
type=OpenApiTypes.FLOAT,
|
type=OpenApiTypes.FLOAT,
|
||||||
required=False
|
required=False
|
||||||
),
|
),
|
||||||
|
OpenApiParameter(
|
||||||
|
name='predict_result',
|
||||||
|
location=OpenApiParameter.QUERY,
|
||||||
|
description='Filter by predict result',
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
required=False
|
||||||
|
),
|
||||||
|
OpenApiParameter(
|
||||||
|
name='feedback_result',
|
||||||
|
location=OpenApiParameter.QUERY,
|
||||||
|
description='Filter by feedback result',
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
required=False
|
||||||
|
),
|
||||||
|
OpenApiParameter(
|
||||||
|
name='reviewed_result',
|
||||||
|
location=OpenApiParameter.QUERY,
|
||||||
|
description='Filter by reviewed result',
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
required=False
|
||||||
|
),
|
||||||
|
OpenApiParameter(
|
||||||
|
name='doc_type',
|
||||||
|
location=OpenApiParameter.QUERY,
|
||||||
|
description='Filter by document type',
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
enum=list(settings.DOC_TYPES),
|
||||||
|
required=False
|
||||||
|
),
|
||||||
|
OpenApiParameter(
|
||||||
|
name='bad_reason',
|
||||||
|
location=OpenApiParameter.QUERY,
|
||||||
|
description='Filter by bad reason',
|
||||||
|
type=OpenApiTypes.STR,
|
||||||
|
required=False
|
||||||
|
),
|
||||||
],
|
],
|
||||||
responses=None, tags=['Accuracy']
|
responses=None, tags=['Accuracy']
|
||||||
)
|
)
|
||||||
@ -129,7 +166,11 @@ class AccuracyViewSet(viewsets.ViewSet):
|
|||||||
include_test = request.GET.get('includes_test', False)
|
include_test = request.GET.get('includes_test', False)
|
||||||
subsidiary = request.GET.get("subsidiary", "all")
|
subsidiary = request.GET.get("subsidiary", "all")
|
||||||
max_accuracy = float(request.GET.get("max_accuracy", 100))
|
max_accuracy = float(request.GET.get("max_accuracy", 100))
|
||||||
# subsidiary = map_subsidiary_long_to_short(subsidiary)
|
predict_result = request.GET.get('predict_result', None)
|
||||||
|
feedback_result = request.GET.get('feedback_result', None)
|
||||||
|
reviewed_result = request.GET.get('reviewed_result', None)
|
||||||
|
doc_type = request.GET.get('doc_type', None)
|
||||||
|
bad_reason = request.GET.get('bad_reason', None)
|
||||||
|
|
||||||
base_query = Q(status=200)
|
base_query = Q(status=200)
|
||||||
if start_date_str or end_date_str:
|
if start_date_str or end_date_str:
|
||||||
@ -193,10 +234,28 @@ class AccuracyViewSet(viewsets.ViewSet):
|
|||||||
base_query &= Q(
|
base_query &= Q(
|
||||||
redemption_id__startswith=map_subsidiary_long_to_short(subsidiary))
|
redemption_id__startswith=map_subsidiary_long_to_short(subsidiary))
|
||||||
|
|
||||||
|
if predict_result:
|
||||||
|
base_query &= Q(predict_result__icontains=predict_result)
|
||||||
|
if feedback_result:
|
||||||
|
base_query &= Q(feedback_result__icontains=feedback_result)
|
||||||
|
if reviewed_result:
|
||||||
|
base_query &= Q(reviewed_result__icontains=reviewed_result)
|
||||||
|
if doc_type:
|
||||||
|
if doc_type.lower() == 'invoice':
|
||||||
|
base_query &= Q(doc_type__regex=r'^invoice(,\s*invoice)*$')
|
||||||
|
elif doc_type.lower() == 'imei':
|
||||||
|
base_query &= Q(doc_type__regex=r'^imei(,\s*imei)*$')
|
||||||
|
|
||||||
if isinstance(max_accuracy, float):
|
if isinstance(max_accuracy, float):
|
||||||
base_query &= Q(raw_accuracy__lt=(
|
base_query &= Q(raw_accuracy__lt=(
|
||||||
max_accuracy/100)) | Q(raw_accuracy__isnull=True)
|
max_accuracy/100)) | Q(raw_accuracy__isnull=True)
|
||||||
|
|
||||||
|
if bad_reason:
|
||||||
|
bad_reason_subquery = SubscriptionRequestFile.objects.filter(
|
||||||
|
reason__icontains=bad_reason
|
||||||
|
).values_list('request_id', flat=True)
|
||||||
|
base_query &= Q(id__in=bad_reason_subquery)
|
||||||
|
|
||||||
subscription_requests = SubscriptionRequest.objects.filter(
|
subscription_requests = SubscriptionRequest.objects.filter(
|
||||||
base_query).order_by('created_at')
|
base_query).order_by('created_at')
|
||||||
|
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from tqdm import tqdm
|
||||||
|
from fwd_api.models import SubscriptionRequestFile
|
||||||
|
from fwd_api.models.SemiAutoCorrection import SemiAutoCorrection
|
||||||
|
from fwd_api.exception.exceptions import InvalidException
|
||||||
|
|
||||||
|
# Mapping dictionary for reasons
|
||||||
|
REASON_MAP = {
|
||||||
|
'Invalid image': 'invalid_image',
|
||||||
|
'Missing information': 'missing_information',
|
||||||
|
'Too blurry text': 'too_blurry_text',
|
||||||
|
'Too small text': 'too_small_text',
|
||||||
|
'Handwritten': 'handwritten',
|
||||||
|
'Recheck': 'recheck',
|
||||||
|
}
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = 'Replace the reason field in SubscriptionRequestFile and SemiAutoCorrection based on the provided mapping dictionary'
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
# Process SubscriptionRequestFile instances
|
||||||
|
self.update_reasons(SubscriptionRequestFile, "SubscriptionRequestFile")
|
||||||
|
|
||||||
|
# Process SemiAutoCorrection instances
|
||||||
|
self.update_reasons(SemiAutoCorrection, "SemiAutoCorrection")
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS('All applicable reasons updated successfully!'))
|
||||||
|
|
||||||
|
def update_reasons(self, model, model_name):
|
||||||
|
instances = model.objects.exclude(reason__isnull=True).exclude(reason='').iterator()
|
||||||
|
for instance in tqdm(instances, desc=f"Updating reasons in {model_name}"):
|
||||||
|
try:
|
||||||
|
original_reason = instance.reason
|
||||||
|
new_reason = REASON_MAP.get(original_reason)
|
||||||
|
if new_reason is not None:
|
||||||
|
instance.reason = new_reason
|
||||||
|
instance.save()
|
||||||
|
self.stdout.write(self.style.SUCCESS(f"Updated reason for {model_name} ID {instance.id}: {original_reason} -> {new_reason}"))
|
||||||
|
except Exception as e:
|
||||||
|
self.stdout.write(self.style.ERROR(f"Updated reason failed for {model_name} ID {instance.id} due to {e}"))
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
# Generated by Django 4.1.3 on 2024-11-05 02:48
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('fwd_api', '0194_alter_semiautocorrection_feedback_accuracy_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='subscriptionrequest',
|
||||||
|
name='request_id',
|
||||||
|
field=models.CharField(db_index=True, max_length=200),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='userprofile',
|
||||||
|
name='id',
|
||||||
|
field=models.AutoField(db_index=True, primary_key=True, serialize=False),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='subscriptionrequestfile',
|
||||||
|
index=models.Index(fields=['request', 'index_in_request', 'doc_type'], name='fwd_api_sub_request_890e13_idx'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='subscriptionrequestfile',
|
||||||
|
index=models.Index(fields=['request', 'file_name'], name='fwd_api_sub_request_1a42cd_idx'),
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,26 @@
|
|||||||
|
# Generated by Django 4.1.3 on 2024-11-28 07:10
|
||||||
|
|
||||||
|
import django.contrib.postgres.indexes
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('fwd_api', '0195_alter_subscriptionrequest_request_id_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='subscriptionrequestfile',
|
||||||
|
index=django.contrib.postgres.indexes.GinIndex(fields=['predict_result'], name='idx_gin_predict_result'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='subscriptionrequestfile',
|
||||||
|
index=django.contrib.postgres.indexes.GinIndex(fields=['feedback_result'], name='idx_gin_feedback_result'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='subscriptionrequestfile',
|
||||||
|
index=django.contrib.postgres.indexes.GinIndex(fields=['reviewed_result'], name='idx_gin_reviewed_result'),
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,26 @@
|
|||||||
|
# Generated by Django 4.1.3 on 2024-11-28 09:04
|
||||||
|
|
||||||
|
import django.contrib.postgres.indexes
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('fwd_api', '0196_subscriptionrequestfile_idx_gin_predict_result_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='subscriptionrequest',
|
||||||
|
index=django.contrib.postgres.indexes.GinIndex(fields=['predict_result'], name='idx_gin_rq_predict_result'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='subscriptionrequest',
|
||||||
|
index=django.contrib.postgres.indexes.GinIndex(fields=['feedback_result'], name='idx_gin_rq_feedback_result'),
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='subscriptionrequest',
|
||||||
|
index=django.contrib.postgres.indexes.GinIndex(fields=['reviewed_result'], name='idx_gin_rq_reviewed_result'),
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.1.3 on 2024-11-28 09:40
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('fwd_api', '0197_subscriptionrequest_idx_gin_rq_predict_result_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='subscriptionrequest',
|
||||||
|
name='doc_type',
|
||||||
|
field=models.CharField(db_index=True, max_length=100),
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.1.3 on 2024-12-04 10:18
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('fwd_api', '0198_alter_subscriptionrequest_doc_type'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='subscriptionrequestfile',
|
||||||
|
name='reason',
|
||||||
|
field=models.TextField(blank=True, db_index=True),
|
||||||
|
),
|
||||||
|
]
|
@ -1,5 +1,6 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.contrib.postgres.indexes import GinIndex
|
||||||
|
|
||||||
from fwd_api.models.Subscription import Subscription
|
from fwd_api.models.Subscription import Subscription
|
||||||
|
|
||||||
@ -7,7 +8,7 @@ class SubscriptionRequest(models.Model):
|
|||||||
id = models.AutoField(primary_key=True)
|
id = models.AutoField(primary_key=True)
|
||||||
pages: int = models.IntegerField()
|
pages: int = models.IntegerField()
|
||||||
pages_left: int = models.IntegerField(default=1)
|
pages_left: int = models.IntegerField(default=1)
|
||||||
doc_type: str = models.CharField(max_length=100)
|
doc_type: str = models.CharField(max_length=100, db_index=True)
|
||||||
request_id = models.CharField(max_length=200, db_index=True) # Change to request_id
|
request_id = models.CharField(max_length=200, db_index=True) # Change to request_id
|
||||||
redemption_id = models.CharField(max_length=200, null=True)
|
redemption_id = models.CharField(max_length=200, null=True)
|
||||||
process_type = models.CharField(max_length=200) # driver/id/invoice
|
process_type = models.CharField(max_length=200) # driver/id/invoice
|
||||||
@ -39,3 +40,10 @@ class SubscriptionRequest(models.Model):
|
|||||||
is_reviewed = models.BooleanField(default=False)
|
is_reviewed = models.BooleanField(default=False)
|
||||||
is_required = models.BooleanField(default=True)
|
is_required = models.BooleanField(default=True)
|
||||||
subsidiary = models.CharField(default="", null=True, max_length=200)
|
subsidiary = models.CharField(default="", null=True, max_length=200)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
indexes = [
|
||||||
|
GinIndex(fields=['predict_result'], name='idx_gin_rq_predict_result'),
|
||||||
|
GinIndex(fields=['feedback_result'], name='idx_gin_rq_feedback_result'),
|
||||||
|
GinIndex(fields=['reviewed_result'], name='idx_gin_rq_reviewed_result'),
|
||||||
|
]
|
@ -1,5 +1,5 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.contrib.postgres.indexes import GinIndex
|
||||||
from fwd_api.constant.common import FileCategory
|
from fwd_api.constant.common import FileCategory
|
||||||
from fwd_api.models import SubscriptionRequest
|
from fwd_api.models import SubscriptionRequest
|
||||||
from fwd_api.models.fields.EncryptedCharField import EncryptedCharField
|
from fwd_api.models.fields.EncryptedCharField import EncryptedCharField
|
||||||
@ -23,7 +23,7 @@ class SubscriptionRequestFile(models.Model):
|
|||||||
doc_type = models.CharField(max_length=10, default="")
|
doc_type = models.CharField(max_length=10, default="")
|
||||||
index_in_request = models.IntegerField(default=0) # by doc_type
|
index_in_request = models.IntegerField(default=0) # by doc_type
|
||||||
processing_time = models.FloatField(default=-1) # in milisecond
|
processing_time = models.FloatField(default=-1) # in milisecond
|
||||||
reason = models.TextField(blank=True)
|
reason = models.TextField(blank=True, db_index=True)
|
||||||
counter_measures = models.TextField(blank=True)
|
counter_measures = models.TextField(blank=True)
|
||||||
is_reviewed = models.BooleanField(default=False)
|
is_reviewed = models.BooleanField(default=False)
|
||||||
is_required = models.BooleanField(default=True)
|
is_required = models.BooleanField(default=True)
|
||||||
@ -40,5 +40,8 @@ class SubscriptionRequestFile(models.Model):
|
|||||||
indexes = [
|
indexes = [
|
||||||
models.Index(fields=['request', 'index_in_request', 'doc_type']), # For updating results
|
models.Index(fields=['request', 'index_in_request', 'doc_type']), # For updating results
|
||||||
models.Index(fields=['request', 'file_name']), # for getting image files by AI
|
models.Index(fields=['request', 'file_name']), # for getting image files by AI
|
||||||
|
GinIndex(fields=['predict_result'], name='idx_gin_predict_result'),
|
||||||
|
GinIndex(fields=['feedback_result'], name='idx_gin_feedback_result'),
|
||||||
|
GinIndex(fields=['reviewed_result'], name='idx_gin_reviewed_result'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@
|
|||||||
"prettier-plugin-organize-imports": "^3.2.1",
|
"prettier-plugin-organize-imports": "^3.2.1",
|
||||||
"rollup-plugin-visualizer": "^5.9.0",
|
"rollup-plugin-visualizer": "^5.9.0",
|
||||||
"sass": "^1.57.1",
|
"sass": "^1.57.1",
|
||||||
"typescript": "^4.9.4",
|
"typescript": "^5.6.3",
|
||||||
"vite": "^4.0.3",
|
"vite": "^4.0.3",
|
||||||
"vite-plugin-svgr": "^2.4.0",
|
"vite-plugin-svgr": "^2.4.0",
|
||||||
"vite-tsconfig-paths": "^4.0.3"
|
"vite-tsconfig-paths": "^4.0.3"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { AppstoreOutlined, BarChartOutlined, RotateRightOutlined, FileSearchOutlined } 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';
|
||||||
|
@ -4,7 +4,6 @@ export function GlobalSpin() {
|
|||||||
return (
|
return (
|
||||||
<Spin
|
<Spin
|
||||||
size='large'
|
size='large'
|
||||||
tip='Loading ...'
|
|
||||||
style={{
|
style={{
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
top: '50%',
|
top: '50%',
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
"Remove this image from the evaluation report": "Remove this image from the evaluation report",
|
"Remove this image from the evaluation report": "Remove this image from the evaluation report",
|
||||||
"Report Details": "Report Details",
|
"Report Details": "Report Details",
|
||||||
"Report Filters": "Report Filters",
|
"Report Filters": "Report Filters",
|
||||||
|
"Review Filters": "Review Filters",
|
||||||
"Report Type": "Report Type",
|
"Report Type": "Report Type",
|
||||||
"Reports": "Reports",
|
"Reports": "Reports",
|
||||||
"Retry": "Retry",
|
"Retry": "Retry",
|
||||||
@ -70,5 +71,9 @@
|
|||||||
"You are only allowed to upload {0} file.": "You are only allowed to upload {0} file.",
|
"You are only allowed to upload {0} file.": "You are only allowed to upload {0} file.",
|
||||||
"You have unsaved changes!": "You have unsaved changes!",
|
"You have unsaved changes!": "You have unsaved changes!",
|
||||||
"Your current password has expired. Please change your password to continue.": "Your current password has expired. Please change your password to continue.",
|
"Your current password has expired. Please change your password to continue.": "Your current password has expired. Please change your password to continue.",
|
||||||
"max_accuracy": "Max accuracy"
|
"max_accuracy": "Max accuracy",
|
||||||
|
"docType": "Only type",
|
||||||
|
"Feedback Result": "Feedback Result",
|
||||||
|
"Predict Result": "Predict Result",
|
||||||
|
"Reviewed Result": "Reviewed Result"
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
"Remove this image from the evaluation report": "",
|
"Remove this image from the evaluation report": "",
|
||||||
"Report Details": "",
|
"Report Details": "",
|
||||||
"Report Filters": "",
|
"Report Filters": "",
|
||||||
|
"Review Filters": "",
|
||||||
"Report Type": "",
|
"Report Type": "",
|
||||||
"Reports": "",
|
"Reports": "",
|
||||||
"Retry": "Thử lại",
|
"Retry": "Thử lại",
|
||||||
@ -70,5 +71,9 @@
|
|||||||
"You are only allowed to upload {0} file.": "Bạn chỉ được phép tải lên {0}.",
|
"You are only allowed to upload {0} file.": "Bạn chỉ được phép tải lên {0}.",
|
||||||
"You have unsaved changes!": "Bạn có những thay đổi chưa được lưu!",
|
"You have unsaved changes!": "Bạn có những thay đổi chưa được lưu!",
|
||||||
"Your current password has expired. Please change your password to continue.": "",
|
"Your current password has expired. Please change your password to continue.": "",
|
||||||
"max_accuracy": "Độ chính xác tối đa"
|
"max_accuracy": "Độ chính xác tối đa",
|
||||||
|
"DocType": "Kiểu tài liệu",
|
||||||
|
"Feedback Result": "",
|
||||||
|
"Predict Result": "",
|
||||||
|
"Reviewed Result": ""
|
||||||
}
|
}
|
||||||
|
69
cope2n-fe/src/pages/reviews2/DocumentCompareInfo.tsx
Normal file
69
cope2n-fe/src/pages/reviews2/DocumentCompareInfo.tsx
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Button, Descriptions, Input } from 'antd';
|
||||||
|
import type { DescriptionsProps } from 'antd';
|
||||||
|
import { CopyOutlined } from '@ant-design/icons';
|
||||||
|
import { FEEDBACK_RESULT, PREDICTED_RESULT, REVIEWED_RESULT } from './const';
|
||||||
|
|
||||||
|
const DocumentCompareInfo = ({ key, data, selectedFileDataSource, updateRevisedByFeedback, handleUpdateFileInField, shouldRevised, disabledInput }) => {
|
||||||
|
const items: DescriptionsProps['items'] = [
|
||||||
|
{
|
||||||
|
key: selectedFileDataSource[data]?.[FEEDBACK_RESULT] || '1',
|
||||||
|
label: 'Feedback',
|
||||||
|
children: selectedFileDataSource[data]?.[FEEDBACK_RESULT],
|
||||||
|
labelStyle: { color: '#333', padding: '4px 16px' },
|
||||||
|
contentStyle: { padding: '4px 16px' },
|
||||||
|
span: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: selectedFileDataSource[data]?.[PREDICTED_RESULT] || '2',
|
||||||
|
label: 'Predicted',
|
||||||
|
children: selectedFileDataSource[data]?.[PREDICTED_RESULT],
|
||||||
|
labelStyle: { color: '#333', padding: '4px 16px' },
|
||||||
|
contentStyle: { padding: '4px 16px' },
|
||||||
|
span: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: selectedFileDataSource[data]?.[REVIEWED_RESULT] || '3',
|
||||||
|
label: 'Revised',
|
||||||
|
children: <Input
|
||||||
|
style={{ background: shouldRevised ? 'yellow' : '', padding: '0' }}
|
||||||
|
value={selectedFileDataSource[data]?.[REVIEWED_RESULT]}
|
||||||
|
size='small'
|
||||||
|
onChange={(e) =>
|
||||||
|
handleUpdateFileInField(data, e.target.value)
|
||||||
|
}
|
||||||
|
variant="borderless"
|
||||||
|
disabled={disabledInput === undefined || disabledInput === 0}
|
||||||
|
/>,
|
||||||
|
labelStyle: { color: '#333', padding: '4px 16px' },
|
||||||
|
contentStyle: { padding: '4px 16px' },
|
||||||
|
span: 3
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div style={{ margin: '0 0 8px' }} className='file-input-group' key={key}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
alignItems: 'center',
|
||||||
|
margin: '0 0 4px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p style={{ fontWeight: 'bold', margin: 0 }}>{data}</p>
|
||||||
|
<Button
|
||||||
|
shape='round'
|
||||||
|
type='primary'
|
||||||
|
ghost
|
||||||
|
icon={<CopyOutlined />}
|
||||||
|
size='small'
|
||||||
|
onClick={() => updateRevisedByFeedback(data)}
|
||||||
|
disabled={disabledInput === undefined || disabledInput === 0}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Descriptions bordered items={items} layout="horizontal" size='small' contentStyle={{ height: '13px' }} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DocumentCompareInfo;
|
39
cope2n-fe/src/pages/reviews2/DocumentHeadInfo.tsx
Normal file
39
cope2n-fe/src/pages/reviews2/DocumentHeadInfo.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Descriptions } from 'antd';
|
||||||
|
import type { DescriptionsProps } from 'antd';
|
||||||
|
|
||||||
|
const DocumentHeadInfo = ({ currentRequest }) => {
|
||||||
|
const items: DescriptionsProps['items'] = [
|
||||||
|
{
|
||||||
|
key: '1',
|
||||||
|
label: 'Request ID',
|
||||||
|
children: currentRequest?.RequestID,
|
||||||
|
span: 2,
|
||||||
|
labelStyle: { color: '#333', width: '200px' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '2',
|
||||||
|
label: 'Raw accuracy',
|
||||||
|
children: currentRequest?.raw_accuracy,
|
||||||
|
labelStyle: { color: '#333', width: '200px' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '3',
|
||||||
|
label: 'Redemption ID',
|
||||||
|
children: currentRequest?.RedemptionID,
|
||||||
|
span: 2,
|
||||||
|
labelStyle: { color: '#333', width: '200px' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '4',
|
||||||
|
label: 'Processing time',
|
||||||
|
children: currentRequest?.['Server Processing Time (ms)'],
|
||||||
|
labelStyle: { color: '#333', width: '200px' }
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<Descriptions bordered items={items} size="small" />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DocumentHeadInfo;
|
@ -2,10 +2,16 @@ import { baseURL } from 'request/api';
|
|||||||
import { RecentRequest } from './const';
|
import { RecentRequest } from './const';
|
||||||
|
|
||||||
export const fetchAllRequests = async (
|
export const fetchAllRequests = async (
|
||||||
filterDateRange,
|
filterDateRange: any[],
|
||||||
filterSubsidiaries,
|
filterSubsidiaries: string,
|
||||||
filterReviewState,
|
filterReviewState: string,
|
||||||
filterIncludeTests,
|
filterIncludeTests: string,
|
||||||
|
filterDoctype: string,
|
||||||
|
filterFeedbackResult: string,
|
||||||
|
filterPredictResult: string,
|
||||||
|
filterReviewedResult: string,
|
||||||
|
filterBadReason: string,
|
||||||
|
filterOtherReason: string,
|
||||||
page = 1,
|
page = 1,
|
||||||
page_size = 20,
|
page_size = 20,
|
||||||
max_accuracy = 100,
|
max_accuracy = 100,
|
||||||
@ -25,6 +31,25 @@ export const fetchAllRequests = async (
|
|||||||
if (filterIncludeTests) {
|
if (filterIncludeTests) {
|
||||||
filterStr += `includes_test=${filterIncludeTests}&`;
|
filterStr += `includes_test=${filterIncludeTests}&`;
|
||||||
}
|
}
|
||||||
|
// add 4 more field
|
||||||
|
if (filterDoctype) {
|
||||||
|
filterStr += `doc_type=${filterDoctype}&`;
|
||||||
|
}
|
||||||
|
if (filterFeedbackResult) {
|
||||||
|
filterStr += `feedback_result=${filterFeedbackResult}&`;
|
||||||
|
}
|
||||||
|
if (filterPredictResult) {
|
||||||
|
filterStr += `predict_result=${filterPredictResult}&`;
|
||||||
|
}
|
||||||
|
if (filterReviewedResult) {
|
||||||
|
filterStr += `reviewed_result=${filterReviewedResult}&`;
|
||||||
|
}
|
||||||
|
if (filterBadReason === 'other' && filterOtherReason.trim()) {
|
||||||
|
filterStr += `bad_reason=${filterOtherReason}&`;
|
||||||
|
} else if(filterBadReason !== 'other') {
|
||||||
|
filterStr += `bad_reason=${filterBadReason}&`;
|
||||||
|
}
|
||||||
|
//
|
||||||
if (startDate && endDate) {
|
if (startDate && endDate) {
|
||||||
filterStr += `start_date=${startDate}&end_date=${endDate}&`;
|
filterStr += `start_date=${startDate}&end_date=${endDate}&`;
|
||||||
}
|
}
|
||||||
@ -77,7 +102,7 @@ export const updateRevisedDataByFile = async (
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchRequest = async (id) => {
|
export const fetchRequest = async (id: string) => {
|
||||||
const token = localStorage.getItem('sbt-token') || '';
|
const token = localStorage.getItem('sbt-token') || '';
|
||||||
const response = await fetch(`${baseURL}/ctel/request/${id}/`, {
|
const response = await fetch(`${baseURL}/ctel/request/${id}/`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
@ -87,7 +112,7 @@ export const fetchRequest = async (id) => {
|
|||||||
});
|
});
|
||||||
return await (
|
return await (
|
||||||
await response.json()
|
await response.json()
|
||||||
).subscription_requests[0];
|
).subscription_requests?.[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addRecentRequest = (
|
export const addRecentRequest = (
|
||||||
|
@ -48,6 +48,12 @@ export const SUBSIDIARIES = [
|
|||||||
{ value: 'SEIN', label: 'SEIN' },
|
{ value: 'SEIN', label: 'SEIN' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const DOCTYPE = [
|
||||||
|
{ value: null, label: '--' },
|
||||||
|
{ value: 'imei', label: 'imei' },
|
||||||
|
{ value: 'invoice', label: 'invoice' },
|
||||||
|
];
|
||||||
|
|
||||||
export const SOURCE_KEYS = [
|
export const SOURCE_KEYS = [
|
||||||
'retailername',
|
'retailername',
|
||||||
'sold_to_party',
|
'sold_to_party',
|
||||||
|
@ -3,7 +3,6 @@ import {
|
|||||||
ArrowRightOutlined,
|
ArrowRightOutlined,
|
||||||
CheckCircleOutlined,
|
CheckCircleOutlined,
|
||||||
ClockCircleFilled,
|
ClockCircleFilled,
|
||||||
CopyOutlined,
|
|
||||||
FullscreenExitOutlined,
|
FullscreenExitOutlined,
|
||||||
FullscreenOutlined,
|
FullscreenOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
@ -41,6 +40,7 @@ import {
|
|||||||
} from './api';
|
} from './api';
|
||||||
import {
|
import {
|
||||||
counter_measure_map,
|
counter_measure_map,
|
||||||
|
DOCTYPE,
|
||||||
FEEDBACK_ACCURACY,
|
FEEDBACK_ACCURACY,
|
||||||
FEEDBACK_RESULT,
|
FEEDBACK_RESULT,
|
||||||
PREDICTED_RESULT,
|
PREDICTED_RESULT,
|
||||||
@ -54,6 +54,8 @@ import {
|
|||||||
import FileCard from './FileCard';
|
import FileCard from './FileCard';
|
||||||
import RecentRequest from './RecentRequest';
|
import RecentRequest from './RecentRequest';
|
||||||
import './style.css';
|
import './style.css';
|
||||||
|
import DocumentHeadInfo from './DocumentHeadInfo';
|
||||||
|
import DocumentCompareInfo from './DocumentCompareInfo';
|
||||||
|
|
||||||
const ReviewPage = () => {
|
const ReviewPage = () => {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@ -71,6 +73,13 @@ const ReviewPage = () => {
|
|||||||
const [filterAccuracy, setFilterAccuracy] = useState(100);
|
const [filterAccuracy, setFilterAccuracy] = useState(100);
|
||||||
const [filterReviewState, setFilterReviewState] = useState('all');
|
const [filterReviewState, setFilterReviewState] = useState('all');
|
||||||
const [filterIncludeTests, setFilterIncludesTests] = useState('true');
|
const [filterIncludeTests, setFilterIncludesTests] = useState('true');
|
||||||
|
const [filterDoctype, setFilterDoctype] = useState(null);
|
||||||
|
const [filterFeedbackResult, setFilterFeedbackResult] = useState('');
|
||||||
|
const [filterPredictResult, setFilterPredictResult] = useState('');
|
||||||
|
const [filterReviewedResult, setFilterReviewedResult] = useState('');
|
||||||
|
const [filterBadReason, setFilterBadReason] = useState('other');
|
||||||
|
const [filterOtherReason, setFilterOtherReason] = useState('');
|
||||||
|
|
||||||
// const [requests, setRequests] = useState([]);
|
// const [requests, setRequests] = useState([]);
|
||||||
const [currentRequest, setCurrentRequest] = useState(null);
|
const [currentRequest, setCurrentRequest] = useState(null);
|
||||||
const [currentRequestIndex, setCurrentRequestIndex] = useState(1);
|
const [currentRequestIndex, setCurrentRequestIndex] = useState(1);
|
||||||
@ -109,6 +118,12 @@ const ReviewPage = () => {
|
|||||||
filterSubsidiaries,
|
filterSubsidiaries,
|
||||||
filterReviewState,
|
filterReviewState,
|
||||||
filterIncludeTests,
|
filterIncludeTests,
|
||||||
|
filterDoctype,
|
||||||
|
filterFeedbackResult,
|
||||||
|
filterPredictResult,
|
||||||
|
filterReviewedResult,
|
||||||
|
filterBadReason,
|
||||||
|
filterOtherReason,
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
filterAccuracy,
|
filterAccuracy,
|
||||||
@ -116,7 +131,7 @@ const ReviewPage = () => {
|
|||||||
setTotalPages(data?.page?.total_requests);
|
setTotalPages(data?.page?.total_requests);
|
||||||
setHasNextRequest(1 < data?.page?.total_requests);
|
setHasNextRequest(1 < data?.page?.total_requests);
|
||||||
const firstRequest = fetchRequest(
|
const firstRequest = fetchRequest(
|
||||||
data?.subscription_requests[0].RequestID,
|
data?.subscription_requests?.[0]?.RequestID,
|
||||||
);
|
);
|
||||||
firstRequest.then(async (data) => {
|
firstRequest.then(async (data) => {
|
||||||
if (data) setCurrentRequest(data);
|
if (data) setCurrentRequest(data);
|
||||||
@ -163,7 +178,7 @@ const ReviewPage = () => {
|
|||||||
|
|
||||||
const setAndLoadSelectedFile = async (requestData, index) => {
|
const setAndLoadSelectedFile = async (requestData, index) => {
|
||||||
setSelectedFileId(index);
|
setSelectedFileId(index);
|
||||||
if (!requestData['Files'][index]) {
|
if (!requestData?.['Files'][index]) {
|
||||||
setSelectedFileData('FAILED_TO_LOAD_FILE');
|
setSelectedFileData('FAILED_TO_LOAD_FILE');
|
||||||
setImageLoading(false);
|
setImageLoading(false);
|
||||||
return;
|
return;
|
||||||
@ -218,6 +233,12 @@ const ReviewPage = () => {
|
|||||||
filterSubsidiaries,
|
filterSubsidiaries,
|
||||||
filterReviewState,
|
filterReviewState,
|
||||||
filterIncludeTests,
|
filterIncludeTests,
|
||||||
|
filterDoctype,
|
||||||
|
filterFeedbackResult,
|
||||||
|
filterPredictResult,
|
||||||
|
filterReviewedResult,
|
||||||
|
filterBadReason,
|
||||||
|
filterOtherReason,
|
||||||
requestIndex,
|
requestIndex,
|
||||||
1,
|
1,
|
||||||
filterAccuracy,
|
filterAccuracy,
|
||||||
@ -273,6 +294,12 @@ const ReviewPage = () => {
|
|||||||
filterSubsidiaries,
|
filterSubsidiaries,
|
||||||
filterReviewState,
|
filterReviewState,
|
||||||
filterIncludeTests,
|
filterIncludeTests,
|
||||||
|
filterDoctype,
|
||||||
|
filterFeedbackResult,
|
||||||
|
filterPredictResult,
|
||||||
|
filterReviewedResult,
|
||||||
|
filterBadReason,
|
||||||
|
filterOtherReason,
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
filterAccuracy,
|
filterAccuracy,
|
||||||
@ -474,42 +501,10 @@ const ReviewPage = () => {
|
|||||||
>
|
>
|
||||||
{fullscreen ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
|
{fullscreen ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
{totalRequests && (
|
{totalRequests && (
|
||||||
<div
|
<DocumentHeadInfo currentRequest={currentRequest} />
|
||||||
style={{
|
|
||||||
flexGrow: 1,
|
|
||||||
display: 'grid',
|
|
||||||
gridTemplateColumns: '1fr 1fr 1fr',
|
|
||||||
marginLeft: '16px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div style={{ gridColumn: 'span 2 / span 2' }}>
|
|
||||||
<b>Request ID: </b>
|
|
||||||
{currentRequest?.RequestID}
|
|
||||||
</div>{' '}
|
|
||||||
<div>
|
|
||||||
<b>Created at: </b>
|
|
||||||
{currentRequest?.created_at}
|
|
||||||
</div>{' '}
|
|
||||||
<div>
|
|
||||||
<b>Request time: </b>
|
|
||||||
{currentRequest?.['Client Request Time (ms)']}
|
|
||||||
</div>{' '}
|
|
||||||
<div style={{ gridColumn: 'span 2 / span 2' }}>
|
|
||||||
<b>Redemption ID: </b>
|
|
||||||
{currentRequest?.RedemptionID}
|
|
||||||
</div>{' '}
|
|
||||||
<div>
|
|
||||||
<b>Raw accuracy: </b>
|
|
||||||
{currentRequest?.raw_accuracy}
|
|
||||||
</div>{' '}
|
|
||||||
<div style={{ gridColumn: 'span 2 / span 2' }}>
|
|
||||||
<b>Processing time: </b>
|
|
||||||
{currentRequest?.['Server Processing Time (ms)']}
|
|
||||||
</div>{' '}
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
|
||||||
{totalRequests > 0 && (
|
{totalRequests > 0 && (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@ -561,17 +556,17 @@ const ReviewPage = () => {
|
|||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Viewer
|
{selectedFileData && <Viewer
|
||||||
plugins={[defaultLayoutPluginInstance]}
|
plugins={[defaultLayoutPluginInstance]}
|
||||||
fileUrl={selectedFileData}
|
fileUrl={selectedFileData}
|
||||||
onDocumentLoad={() => setImageLoading(false)}
|
onDocumentLoad={() => setImageLoading(false)}
|
||||||
/>
|
/>}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
overflow: 'auto',
|
overflowY: 'auto',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@ -739,8 +734,7 @@ const ReviewPage = () => {
|
|||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
size='middle'
|
size='middle'
|
||||||
value={`Sub: ${filterSubsidiaries}, Date:${
|
value={`Sub: ${filterSubsidiaries}, Date:${filterDateRange[0]
|
||||||
filterDateRange[0]
|
|
||||||
? filterDateRange[0] + ' to ' + filterDateRange[1]
|
? filterDateRange[0] + ' to ' + filterDateRange[1]
|
||||||
: 'All'
|
: 'All'
|
||||||
}, Reviewed: ${filterReviewState}, Tests: ${filterIncludeTests}`}
|
}, Reviewed: ${filterReviewState}, Tests: ${filterIncludeTests}`}
|
||||||
@ -764,54 +758,21 @@ const ReviewPage = () => {
|
|||||||
let shouldRevised = false;
|
let shouldRevised = false;
|
||||||
try {
|
try {
|
||||||
if (
|
if (
|
||||||
selectedFileDataSource[data]?.[FEEDBACK_ACCURACY].length > 0
|
selectedFileDataSource[data]?.[FEEDBACK_ACCURACY]?.length > 0
|
||||||
) {
|
) {
|
||||||
shouldRevised =
|
shouldRevised =
|
||||||
selectedFileDataSource[data][FEEDBACK_ACCURACY][0] < 1;
|
selectedFileDataSource[data][FEEDBACK_ACCURACY][0] < 1;
|
||||||
}
|
}
|
||||||
} catch (error) { }
|
} catch (error) { }
|
||||||
return (
|
return (
|
||||||
<div style={{ margin: '0 0 8px' }} className='file-input-group'>
|
<DocumentCompareInfo key={data}
|
||||||
<div
|
data={data}
|
||||||
style={{
|
selectedFileDataSource={selectedFileDataSource}
|
||||||
display: 'flex',
|
updateRevisedByFeedback={updateRevisedByFeedback}
|
||||||
justifyContent: 'space-between',
|
handleUpdateFileInField={handleUpdateFileInField}
|
||||||
alignItems: 'center',
|
shouldRevised={shouldRevised}
|
||||||
margin: '0 0 4px',
|
disabledInput = {currentRequest?.Files?.length}
|
||||||
}}
|
|
||||||
>
|
|
||||||
<p style={{ fontWeight: 'bold', margin: 0 }}>{data}</p>
|
|
||||||
<Button
|
|
||||||
shape='round'
|
|
||||||
type='primary'
|
|
||||||
ghost
|
|
||||||
icon={<CopyOutlined />}
|
|
||||||
size='small'
|
|
||||||
onClick={() => updateRevisedByFeedback(data)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<Input
|
|
||||||
addonBefore='Feedback'
|
|
||||||
size='small'
|
|
||||||
readOnly
|
|
||||||
value={selectedFileDataSource[data]?.[FEEDBACK_RESULT]}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
addonBefore='Predicted'
|
|
||||||
readOnly
|
|
||||||
size='small'
|
|
||||||
value={selectedFileDataSource[data]?.[PREDICTED_RESULT]}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
addonBefore='Revised'
|
|
||||||
style={{ background: shouldRevised ? 'yellow' : '' }}
|
|
||||||
size='small'
|
|
||||||
value={selectedFileDataSource[data]?.[REVIEWED_RESULT]}
|
|
||||||
onChange={(e) =>
|
|
||||||
handleUpdateFileInField(data, e.target.value)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<b>{t`Bad image reason:`}</b>
|
<b>{t`Bad image reason:`}</b>
|
||||||
@ -875,7 +836,7 @@ const ReviewPage = () => {
|
|||||||
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||||
<Button
|
<Button
|
||||||
type='primary'
|
type='primary'
|
||||||
color='success'
|
// color='success'
|
||||||
size='middle'
|
size='middle'
|
||||||
style={{
|
style={{
|
||||||
height: '36px',
|
height: '36px',
|
||||||
@ -888,7 +849,7 @@ const ReviewPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Modal
|
<Modal
|
||||||
title={t`Report Filters`}
|
title={t`Review Filters`}
|
||||||
open={isModalOpen}
|
open={isModalOpen}
|
||||||
width={700}
|
width={700}
|
||||||
onOk={() => {
|
onOk={() => {
|
||||||
@ -903,6 +864,16 @@ const ReviewPage = () => {
|
|||||||
style={{
|
style={{
|
||||||
marginTop: 30,
|
marginTop: 30,
|
||||||
}}
|
}}
|
||||||
|
layout="vertical"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
marginLeft: 0,
|
||||||
|
padding: 0,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name='dateRange'
|
name='dateRange'
|
||||||
@ -914,20 +885,54 @@ const ReviewPage = () => {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
style={{
|
style={{
|
||||||
marginBottom: 24,
|
flex: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<DatePicker.RangePicker
|
<DatePicker.RangePicker
|
||||||
onChange={(date, dateString) => {
|
onChange={(date, dateString) => {
|
||||||
setFilterDateRange(dateString);
|
setFilterDateRange(dateString);
|
||||||
}}
|
}}
|
||||||
style={{ width: 200 }}
|
style={{ width: 300 }}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<div style={{
|
||||||
|
flex: 1,
|
||||||
|
}}>
|
||||||
|
<Form.Item
|
||||||
|
name='bad_reason'
|
||||||
|
label={t`Bad image reason`}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
placeholder='Select a reason'
|
||||||
|
style={{ width: 300 }}
|
||||||
|
options={REASON_BAD_QUALITY}
|
||||||
|
value={filterBadReason}
|
||||||
|
defaultValue={filterBadReason}
|
||||||
|
onChange={setFilterBadReason}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
{filterBadReason === 'other' && (
|
||||||
|
<Form.Item
|
||||||
|
name='other_reason'
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
placeholder='Other reason'
|
||||||
|
value={filterOtherReason}
|
||||||
|
style={{ width: 300 }}
|
||||||
|
onChange={(e) => {
|
||||||
|
setFilterOtherReason(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
marginTop: 10,
|
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
marginLeft: 0,
|
marginLeft: 0,
|
||||||
@ -943,10 +948,13 @@ const ReviewPage = () => {
|
|||||||
message: 'Please select a subsidiary',
|
message: 'Please select a subsidiary',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
placeholder='Select a subsidiary'
|
placeholder='Select a subsidiary'
|
||||||
style={{ width: 200 }}
|
style={{ width: 300 }}
|
||||||
options={SUBSIDIARIES}
|
options={SUBSIDIARIES}
|
||||||
value={filterSubsidiaries}
|
value={filterSubsidiaries}
|
||||||
defaultValue={filterSubsidiaries}
|
defaultValue={filterSubsidiaries}
|
||||||
@ -962,8 +970,12 @@ const ReviewPage = () => {
|
|||||||
message: 'Please select max accuracy',
|
message: 'Please select max accuracy',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber
|
||||||
|
style={{ width: 300 }}
|
||||||
min={1}
|
min={1}
|
||||||
max={100}
|
max={100}
|
||||||
defaultValue={filterAccuracy}
|
defaultValue={filterAccuracy}
|
||||||
@ -973,7 +985,7 @@ const ReviewPage = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
marginTop: 10,
|
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
marginLeft: 0,
|
marginLeft: 0,
|
||||||
@ -989,9 +1001,12 @@ const ReviewPage = () => {
|
|||||||
message: 'Please select review status',
|
message: 'Please select review status',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
style={{ width: 200 }}
|
style={{ width: 300 }}
|
||||||
options={[
|
options={[
|
||||||
{ label: 'All', value: 'all' },
|
{ label: 'All', value: 'all' },
|
||||||
{ label: 'Reviewed', value: 'reviewed' },
|
{ label: 'Reviewed', value: 'reviewed' },
|
||||||
@ -1011,10 +1026,10 @@ const ReviewPage = () => {
|
|||||||
message: 'Please select test status',
|
message: 'Please select test status',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
style={{ marginLeft: 16 }}
|
style={{ flex: 1 }}
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
style={{ width: 200 }}
|
style={{ width: 300 }}
|
||||||
options={[
|
options={[
|
||||||
{ label: 'Include tests', value: 'true' },
|
{ label: 'Include tests', value: 'true' },
|
||||||
{ label: 'Exclude tests', value: 'false' },
|
{ label: 'Exclude tests', value: 'false' },
|
||||||
@ -1025,6 +1040,82 @@ const ReviewPage = () => {
|
|||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
|
{/* add 4 more filter fields */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
marginLeft: 0,
|
||||||
|
padding: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
name='doc_type'
|
||||||
|
label={t`Only type`}
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
placeholder='Select a document type'
|
||||||
|
style={{ width: 300 }}
|
||||||
|
options={DOCTYPE}
|
||||||
|
value={filterDoctype}
|
||||||
|
defaultValue={filterDoctype}
|
||||||
|
onChange={setFilterDoctype}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name='feedback_result'
|
||||||
|
label={t`Feedback includes`}
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
style={{ width: 300 }}
|
||||||
|
defaultValue={filterFeedbackResult}
|
||||||
|
onChange={(e) => setFilterFeedbackResult(e.target.value)}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
marginLeft: 0,
|
||||||
|
padding: 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
name='predict_result'
|
||||||
|
label={t`Predict includes`}
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
style={{ width: 300 }}
|
||||||
|
defaultValue={filterPredictResult}
|
||||||
|
onChange={(e) => setFilterPredictResult(e.target.value)}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name='reviewed_result'
|
||||||
|
label={t`Review includes`}
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
style={{ width: 300 }}
|
||||||
|
defaultValue={filterReviewedResult}
|
||||||
|
onChange={(e) => setFilterReviewedResult(e.target.value)}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal
|
<Modal
|
||||||
|
@ -11,7 +11,7 @@ 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://107.120.133.27:9881/api' : '/api';
|
export const baseURL = environment === 'development' ? 'http://107.120.133.27:19001/api' : '/api';
|
||||||
// export const baseURL = '/api';
|
// export const baseURL = '/api';
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user