feat: add date-based OHIP data reporting alongside XML
This commit is contained in:
1 parent
5ecd571e3b
commit
ad2c59256f
259 files changed
+37326
-126
No files matched your search
@@ -0,0 +1,91 @@
|
||||
"""Loopback-only, empty-data UI preview. Never used by the production runtime."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from dataclasses import replace
|
||||
from typing import Mapping
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
from arr_web.app import PortalApplication, SessionLedger
|
||||
from arr_web.contracts import PortalError, Response, failure
|
||||
from arr_web.repository import UnavailablePortalRepository
|
||||
from arr_web.server import serve
|
||||
|
||||
|
||||
class EmptyPreviewRepository(UnavailablePortalRepository):
|
||||
def list_jobs(self, month_key, limit=50, offset=0):
|
||||
return [], 0
|
||||
|
||||
def list_monthly_runs(self, month_key, limit=50, offset=0):
|
||||
return [], 0
|
||||
|
||||
def list_history_month_counts(self):
|
||||
return []
|
||||
|
||||
def list_months(self):
|
||||
return []
|
||||
|
||||
|
||||
class ReadOnlyPreview:
|
||||
"""Render the actual portal with unavailable services and no external state."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._sessions = SessionLedger()
|
||||
self._app = PortalApplication(
|
||||
repository=EmptyPreviewRepository(), sessions=self._sessions
|
||||
)
|
||||
|
||||
def handle(
|
||||
self, method: str, target: str, headers: Mapping[str, str],
|
||||
body: bytes = b"", client_id: str = "direct",
|
||||
) -> Response:
|
||||
if method != "GET":
|
||||
return Response.json(405, failure(PortalError(
|
||||
"PREVIEW_READ_ONLY", "本地预览仅供查看,不能提交业务操作。", 405
|
||||
)), headers={"Allow": "GET"})
|
||||
|
||||
path = urlsplit(target).path
|
||||
if path == "/assets/preview.css":
|
||||
return Response(200, (
|
||||
".local-preview-banner{margin:0 0 20px;padding:12px 16px;"
|
||||
"border:1px solid var(--line);border-radius:12px;"
|
||||
"background:var(--blue-soft);color:var(--ink);font-size:13px}"
|
||||
).encode(), "text/css; charset=utf-8", {"Cache-Control": "no-store"})
|
||||
|
||||
# Internal, transient identity belongs only to this empty preview instance.
|
||||
# No browser cookie, credentials, runtime configuration or real service is used.
|
||||
session_id, _ = self._sessions.issue("")
|
||||
request_headers = {k: v for k, v in headers.items() if k.lower() != "cookie"}
|
||||
request_headers["Cookie"] = f"arr_session={session_id}"
|
||||
try:
|
||||
response = self._app.handle(method, target, request_headers, body, client_id)
|
||||
finally:
|
||||
self._sessions.revoke(session_id)
|
||||
|
||||
if path in {"/", "/index.html"} and response.status == 200:
|
||||
html = response.body.decode("utf-8").replace(
|
||||
"<title>ARR Report</title>", "<title>ARR Report · 本地只读预览</title>"
|
||||
).replace(
|
||||
"</head>", '<link rel="stylesheet" href="/assets/preview.css" /></head>'
|
||||
).replace(
|
||||
'<main class="shell page" id="main-content">',
|
||||
'<main class="shell page" id="main-content">'
|
||||
'<aside class="local-preview-banner" role="note">'
|
||||
'<strong>本地只读预览</strong> · 仅展示页面,未连接业务数据;'
|
||||
'上传和自动下载均未启用。</aside>',
|
||||
)
|
||||
response = replace(response, body=html.encode("utf-8"))
|
||||
return response
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--port", type=int, default=8872)
|
||||
args = parser.parse_args()
|
||||
print(f"Read-only preview: http://127.0.0.1:{args.port}/", flush=True)
|
||||
serve(ReadOnlyPreview(), "127.0.0.1", args.port)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user