diff --git a/kaplancloudapp/models.py b/kaplancloudapp/models.py
index d5159e5..80aa881 100644
--- a/kaplancloudapp/models.py
+++ b/kaplancloudapp/models.py
@@ -456,7 +456,7 @@ def get_absolute_url(self):
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
if self.status == 1:
- NewProjectReportThread(self).run()
+ NewProjectReportThread(self).start()
class Segment(models.Model):
diff --git a/kaplancloudapp/static/project.js b/kaplancloudapp/static/project.js
index 1ad19ae..ca73b79 100644
--- a/kaplancloudapp/static/project.js
+++ b/kaplancloudapp/static/project.js
@@ -1,3 +1,10 @@
+const REPORT_STATUS_LABELS = {
+ 0: 'Blank',
+ 1: 'Ready for Processing',
+ 2: 'Processing',
+ 3: 'Complete',
+};
+
window.onload = function() {
const assignLinguistForm = document.getElementById('assign-linguist-form').children[0];
const checkboxMain = document.getElementById('checkbox-main');
@@ -5,6 +12,14 @@ window.onload = function() {
let filesList = [];
+ document.querySelectorAll('#reports-body tr').forEach(row => {
+ const status = parseInt(row.dataset.status, 10);
+ if (status < 3) {
+ const uuid = row.id.replace(/^report-/, '');
+ checkReport(uuid);
+ }
+ });
+
checkboxMain.onclick = function() {
[...document.getElementsByClassName('checkbox')].forEach((item, i) => {
item.checked = checkboxMain.checked;
@@ -139,6 +154,7 @@ function analyzeFiles(fileUuids)
)
.then(response => response.json())
.then(data => {
+ addReportRow(data['uuid']);
checkReport(data['uuid']);
})
.catch(error => {
@@ -146,6 +162,39 @@ function analyzeFiles(fileUuids)
})
}
+function addReportRow(reportUuid)
+{
+ const tbody = document.getElementById('reports-body');
+ const row = document.createElement('tr');
+ row.id = 'report-' + reportUuid;
+ row.dataset.status = '1';
+ row.className = 'hover:bg-base-200/30 transition-colors';
+ const href = '/report/' + reportUuid;
+ row.innerHTML = `
+
Just now |
+ ${REPORT_STATUS_LABELS[1]} |
+
+
+
+
+ |
+ `;
+ tbody.prepend(row);
+}
+
+function setReportStatus(reportUuid, status)
+{
+ const row = document.getElementById('report-' + reportUuid);
+ if (!row) return;
+ row.dataset.status = String(status);
+ const badge = row.querySelector('.report-status');
+ if (badge && REPORT_STATUS_LABELS[status] !== undefined) {
+ badge.textContent = REPORT_STATUS_LABELS[status];
+ }
+}
+
function checkReport(reportUuid)
{
var url = new URL(window.location.origin + '/report/' + reportUuid);
@@ -156,14 +205,11 @@ function checkReport(reportUuid)
.then(response => response.json())
.then(data =>
{
- if (data['status'] == 1 || data['status'] == 2)
+ setReportStatus(reportUuid, data['status']);
+ if (data['status'] < 3)
{
setTimeout(checkReport, 5000, reportUuid);
}
- else
- {
- document.getElementById('report-toast').classList.add('show')
- }
}
)
}
diff --git a/kaplancloudapp/templates/project.html b/kaplancloudapp/templates/project.html
index ed20e5b..547aefe 100644
--- a/kaplancloudapp/templates/project.html
+++ b/kaplancloudapp/templates/project.html
@@ -6,8 +6,6 @@
.modal-overlay { display: none; position: fixed; inset: 0; z-index: 50; align-items: center; justify-content: center; background: rgb(0 0 0 / 0.5); }
.modal-overlay.show { display: flex; }
#context-menu { display: none; }
- #report-toast { display: none; }
- #report-toast.show { display: flex; }
{% endblock %}
@@ -121,17 +119,36 @@ Reference
{# ── Reports section ── #}
Reports
- {% if reports %}
-
- {% else %}
- No reports yet.
- {% endif %}
+
+
+
+
+ | Created |
+ Status |
+ |
+
+
+
+ {% for report in reports %}
+
+ |
+ {{ report.created_at }}
+ |
+
+ {{ report.get_status_display }}
+ |
+
+
+
+
+ |
+
+ {% endfor %}
+
+
+
@@ -199,13 +216,5 @@ Import Package
{% endif %}
-{# ── Report toast ── #}
-
-
-
Your report is ready. Please refresh this page to see it listed.
-
-
{% csrf_token %}
{% endblock %}
diff --git a/kaplancloudapp/templates/report.html b/kaplancloudapp/templates/report.html
index db57ec3..afd2ab6 100644
--- a/kaplancloudapp/templates/report.html
+++ b/kaplancloudapp/templates/report.html
@@ -2,11 +2,13 @@
{% block title %}Report | {{ project.name }} | Kaplan Cloud{% endblock %}
{% block navbar_center %}
-
- - Projects
- - {{ project.name }}
- - Report — {{ report.created_at|date:"N j, Y, P" }}
-
+
{% endblock %}
{% block div %}
diff --git a/kaplancloudapp/tests.py b/kaplancloudapp/tests.py
index 4e6dc45..55ede07 100644
--- a/kaplancloudapp/tests.py
+++ b/kaplancloudapp/tests.py
@@ -442,14 +442,14 @@ def test_ordering_newest_first(self):
@patch("kaplancloudapp.models.NewProjectReportThread")
def test_save_with_status_1_triggers_thread(self, mock_thread):
- mock_thread.return_value.run = MagicMock()
+ mock_thread.return_value.start = MagicMock()
report = ProjectReport.objects.create(
project=self.project, content={"s": "processing"}
)
report.status = 1
report.save()
mock_thread.assert_called_once()
- mock_thread.return_value.run.assert_called_once()
+ mock_thread.return_value.start.assert_called_once()
# ===========================================================================
diff --git a/kaplancloudapp/thread_classes.py b/kaplancloudapp/thread_classes.py
index 33fd841..0c1e554 100644
--- a/kaplancloudapp/thread_classes.py
+++ b/kaplancloudapp/thread_classes.py
@@ -5,6 +5,7 @@
import regex
from django.apps import apps
+from django.db import connection
from kaplan import open_bilingualfile
from kaplan.kdb import KDB
from kaplan.kxliff import KXLIFF
@@ -257,32 +258,20 @@ def __init__(self, projectreport_instance, **kwargs):
super(NewProjectReportThread, self).__init__(**kwargs)
def run(self):
- instance = self.projectreport_instance
-
- for project_file in instance.project_files.all():
- if project_file.status == 1:
- project_file.status = 2
- project_file.save()
-
- SegmentModel = apps.get_model("kaplancloudapp", "Segment")
-
- entries = []
-
- project_report = {}
- project_total = {
- "Repetitions": 0,
- "100": 0, # TODO
- "95": 0,
- "85": 0,
- "75": 0,
- "50": 0,
- "New": 0,
- "Total": 0,
- }
-
- sm = difflib.SequenceMatcher()
- for project_file in instance.project_files.all():
- file_report = {
+ try:
+ instance = self.projectreport_instance
+
+ for project_file in instance.project_files.all():
+ if project_file.status == 1:
+ project_file.status = 2
+ project_file.save()
+
+ SegmentModel = apps.get_model("kaplancloudapp", "Segment")
+
+ entries = []
+
+ project_report = {}
+ project_total = {
"Repetitions": 0,
"100": 0, # TODO
"95": 0,
@@ -293,66 +282,83 @@ def run(self):
"Total": 0,
}
- for segment in SegmentModel.objects.filter(file=project_file):
- source_segment = etree.fromstring(
- "" + segment.source + ""
- )
- source_entry, _ = KDB.segment_to_entry(source_segment)
- word_count = len(source_entry.split())
- char_count = len(source_entry)
+ sm = difflib.SequenceMatcher()
+ for project_file in instance.project_files.all():
+ file_report = {
+ "Repetitions": 0,
+ "100": 0, # TODO
+ "95": 0,
+ "85": 0,
+ "75": 0,
+ "50": 0,
+ "New": 0,
+ "Total": 0,
+ }
+
+ for segment in SegmentModel.objects.filter(file=project_file):
+ source_segment = etree.fromstring(
+ "" + segment.source + ""
+ )
+ source_entry, _ = KDB.segment_to_entry(source_segment)
+ word_count = len(source_entry.split())
+ char_count = len(source_entry)
- if source_entry in entries:
- file_report["Repetitions"] += word_count
- # elif entry in project_tm_entries TODO
- else:
- sm.set_seq2(source_entry)
-
- highest_match = 0.0
- for entry in filter(
- lambda x: len(x) >= char_count / 2 and len(x) <= char_count * 2,
- entries,
- ):
- sm.set_seq1(entry)
- highest_match = max(sm.ratio(), highest_match)
- if highest_match >= 0.95:
- break
-
- if highest_match >= 0.95:
- file_report["95"] += word_count
- elif highest_match >= 0.85:
- file_report["85"] += word_count
- elif highest_match >= 0.75:
- file_report["75"] += word_count
- elif highest_match >= 0.5:
- file_report["50"] += word_count
+ if source_entry in entries:
+ file_report["Repetitions"] += word_count
+ # elif entry in project_tm_entries TODO
else:
- file_report["New"] += word_count
+ sm.set_seq2(source_entry)
+
+ highest_match = 0.0
+ for entry in filter(
+ lambda x: (
+ len(x) >= char_count / 2 and len(x) <= char_count * 2
+ ),
+ entries,
+ ):
+ sm.set_seq1(entry)
+ highest_match = max(sm.ratio(), highest_match)
+ if highest_match >= 0.95:
+ break
- entries.append(source_entry)
+ if highest_match >= 0.95:
+ file_report["95"] += word_count
+ elif highest_match >= 0.85:
+ file_report["85"] += word_count
+ elif highest_match >= 0.75:
+ file_report["75"] += word_count
+ elif highest_match >= 0.5:
+ file_report["50"] += word_count
+ else:
+ file_report["New"] += word_count
+
+ entries.append(source_entry)
- file_report["Total"] += word_count
+ file_report["Total"] += word_count
- project_total["Repetitions"] += file_report["Repetitions"]
- project_total["100"] += file_report["100"]
- project_total["95"] += file_report["95"]
- project_total["85"] += file_report["85"]
- project_total["75"] += file_report["75"]
- project_total["50"] += file_report["50"]
- project_total["New"] += file_report["New"]
- project_total["Total"] += file_report["Total"]
+ project_total["Repetitions"] += file_report["Repetitions"]
+ project_total["100"] += file_report["100"]
+ project_total["95"] += file_report["95"]
+ project_total["85"] += file_report["85"]
+ project_total["75"] += file_report["75"]
+ project_total["50"] += file_report["50"]
+ project_total["New"] += file_report["New"]
+ project_total["Total"] += file_report["Total"]
- project_report[project_file.name] = file_report
+ project_report[project_file.name] = file_report
- project_report["Total"] = project_total
+ project_report["Total"] = project_total
- instance.content = project_report
- instance.status = 3
- instance.save()
+ instance.content = project_report
+ instance.status = 3
+ instance.save()
- for project_file in instance.project_files.all():
- if project_file.status == 2:
- project_file.status = 3
- project_file.save()
+ for project_file in instance.project_files.all():
+ if project_file.status == 2:
+ project_file.status = 3
+ project_file.save()
+ finally:
+ connection.close()
class TMImportThread(threading.Thread):
diff --git a/kaplancloudapp/views.py b/kaplancloudapp/views.py
index c2b7dbc..4e451f9 100644
--- a/kaplancloudapp/views.py
+++ b/kaplancloudapp/views.py
@@ -402,7 +402,7 @@ def project(request, uuid):
"form": form,
"form1": form1,
"project": project,
- "reports": ProjectReport.objects.filter(project=project).filter(status=3),
+ "reports": ProjectReport.objects.filter(project=project),
},
)