Extract HTML5 operation helpers
CI / python (push) Has been cancelled
CI / rust (push) Has been cancelled

This commit is contained in:
2026-05-17 12:36:56 +03:00
parent 8683b136b3
commit 940d7e884b
3 changed files with 97 additions and 24 deletions
@@ -124,6 +124,40 @@ def render_html5_operation_detail(job: object | None) -> str:
""" """
def filter_html5_operation_jobs(
jobs: Iterable[object],
*,
project_id: str = "",
status: str = "",
kind: str = "",
limit: int = 50,
) -> list[object]:
normalized_project = project_id.strip().casefold()
normalized_status = status.strip().casefold()
normalized_kind = kind.strip().casefold()
filtered = []
for job in jobs:
payload = getattr(job, "payload", {}) or {}
if normalized_project and str(payload.get("project_id") or "").casefold() != normalized_project:
continue
if normalized_status and _operation_value(getattr(job, "status", "")).casefold() != normalized_status:
continue
if normalized_kind and _operation_value(getattr(job, "kind", "")).casefold() != normalized_kind:
continue
filtered.append(job)
return sorted(filtered, key=lambda job: getattr(job, "updated_at", ""), reverse=True)[:limit]
def latest_html5_import_job(jobs: Iterable[object], project_id: str) -> object | None:
import_jobs = [
job
for job in jobs
if (getattr(job, "payload", {}) or {}).get("project_id") == project_id
and _operation_value(getattr(job, "kind", "")) == "SERVER_IMPORT"
]
return max(import_jobs, key=lambda job: getattr(job, "updated_at", "")) if import_jobs else None
def _operation_row(job: object) -> str: def _operation_row(job: object) -> str:
job_id = str(getattr(job, "job_id", "")) job_id = str(getattr(job, "job_id", ""))
kind = str(getattr(job, "kind", "")) kind = str(getattr(job, "kind", ""))
@@ -183,3 +217,7 @@ def _operation_filter_query(*, project_id: str, status: str, kind: str) -> str:
if kind: if kind:
params.append(f"kind={quote(kind)}") params.append(f"kind={quote(kind)}")
return f"?{'&'.join(params)}" if params else "" return f"?{'&'.join(params)}" if params else ""
def _operation_value(value: object) -> str:
return str(getattr(value, "value", value))
+9 -24
View File
@@ -77,6 +77,8 @@ from api_server.html5_editor import (
render_html5_symbols, render_html5_symbols,
) )
from api_server.html5_operations import ( from api_server.html5_operations import (
filter_html5_operation_jobs,
latest_html5_import_job,
render_html5_operation_detail, render_html5_operation_detail,
render_html5_operation_rows, render_html5_operation_rows,
render_html5_operation_summary, render_html5_operation_summary,
@@ -8333,33 +8335,16 @@ def _current_import_source(project_id: str) -> ImportSourceKind:
def _html5_operation_jobs(project_id: str = "", status: str = "", kind: str = "") -> list[OperationJob]: def _html5_operation_jobs(project_id: str = "", status: str = "", kind: str = "") -> list[OperationJob]:
normalized_project = project_id.strip().casefold() return filter_html5_operation_jobs(
normalized_status = status.strip().casefold() _operations.jobs.values(),
normalized_kind = kind.strip().casefold() project_id=project_id,
jobs = [] status=status,
for job in _operations.jobs.values(): kind=kind,
payload = job.payload or {} )
if normalized_project and str(payload.get("project_id") or "").casefold() != normalized_project:
continue
if normalized_status and _operation_value(getattr(job, "status", "")).casefold() != normalized_status:
continue
if normalized_kind and _operation_value(getattr(job, "kind", "")).casefold() != normalized_kind:
continue
jobs.append(job)
return sorted(jobs, key=lambda job: job.updated_at, reverse=True)[:50]
def _html5_latest_import_job(project_id: str) -> OperationJob | None: def _html5_latest_import_job(project_id: str) -> OperationJob | None:
jobs = [ return latest_html5_import_job(_operations.jobs.values(), project_id)
job
for job in _operations.jobs.values()
if job.payload.get("project_id") == project_id and _operation_value(getattr(job, "kind", "")) == "SERVER_IMPORT"
]
return max(jobs, key=lambda job: job.updated_at) if jobs else None
def _operation_value(value: object) -> str:
return str(getattr(value, "value", value))
def _project_summaries() -> list[ProjectSummaryResponse]: def _project_summaries() -> list[ProjectSummaryResponse]:
+50
View File
@@ -1,6 +1,7 @@
from pathlib import Path from pathlib import Path
import re import re
import time import time
from types import SimpleNamespace
from uuid import uuid4 from uuid import uuid4
import zipfile import zipfile
@@ -13,6 +14,7 @@ from api_server.html5_forms import (
html5_metadata_payload, html5_metadata_payload,
html5_metadata_request_payload, html5_metadata_request_payload,
) )
from api_server.html5_operations import filter_html5_operation_jobs, latest_html5_import_job
from api_server.html5_sse import html5_sse_comment, html5_sse_event, html5_sse_if_changed from api_server.html5_sse import html5_sse_comment, html5_sse_event, html5_sse_if_changed
from api_server.main import app from api_server.main import app
from one_c_normalizer import ConfigurationRoot, MetadataGroup, MetadataObject, Module, NormalizedProject from one_c_normalizer import ConfigurationRoot, MetadataGroup, MetadataObject, Module, NormalizedProject
@@ -120,6 +122,54 @@ def test_html5_form_helpers_normalize_metadata_payloads():
assert "_raw_attributes" not in html5_metadata_request_payload(payload) assert "_raw_attributes" not in html5_metadata_request_payload(payload)
def test_html5_operation_helpers_filter_sort_and_find_latest_import_job():
jobs = [
SimpleNamespace(
job_id="old",
kind="SERVER_IMPORT",
status="SUCCEEDED",
payload={"project_id": "demo"},
updated_at=10,
),
SimpleNamespace(
job_id="new",
kind="SERVER_IMPORT",
status="RUNNING",
payload={"project_id": "demo"},
updated_at=30,
),
SimpleNamespace(
job_id="other-kind",
kind="REINDEX",
status="RUNNING",
payload={"project_id": "demo"},
updated_at=40,
),
SimpleNamespace(
job_id="other-project",
kind="SERVER_IMPORT",
status="RUNNING",
payload={"project_id": "other"},
updated_at=50,
),
]
filtered = filter_html5_operation_jobs(
jobs,
project_id=" DEMO ",
status="running",
kind="server_import",
)
assert [job.job_id for job in filtered] == ["new"]
assert [job.job_id for job in filter_html5_operation_jobs(jobs, project_id="demo")] == [
"other-kind",
"new",
"old",
]
assert latest_html5_import_job(jobs, "demo").job_id == "new"
def test_cors_allows_lan_panel_origin(): def test_cors_allows_lan_panel_origin():
client = TestClient(app) client = TestClient(app)
response = client.options( response = client.options(