Add HTML5 project panel SSE updates
This commit is contained in:
@@ -284,6 +284,7 @@ def render_html5_flowchart(
|
|||||||
normalized_depth = min(max(depth, 1), 3)
|
normalized_depth = min(max(depth, 1), 3)
|
||||||
hx_url = _flowchart_url(project_id, focus, normalized_depth)
|
hx_url = _flowchart_url(project_id, focus, normalized_depth)
|
||||||
oob_attr = ' hx-swap-oob="outerHTML"' if oob else ""
|
oob_attr = ' hx-swap-oob="outerHTML"' if oob else ""
|
||||||
|
live_attr = ' sse-swap="project-flowchart"' if focus is None else ""
|
||||||
if flowchart is None:
|
if flowchart is None:
|
||||||
return f"""
|
return f"""
|
||||||
<div
|
<div
|
||||||
@@ -293,6 +294,7 @@ def render_html5_flowchart(
|
|||||||
hx-trigger="load"
|
hx-trigger="load"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
{oob_attr}
|
{oob_attr}
|
||||||
|
{live_attr}
|
||||||
>
|
>
|
||||||
<div class="panel-title">Карта связей</div>
|
<div class="panel-title">Карта связей</div>
|
||||||
<p class="muted padded">Сервер собирает граф проекта.</p>
|
<p class="muted padded">Сервер собирает граф проекта.</p>
|
||||||
@@ -311,7 +313,7 @@ def render_html5_flowchart(
|
|||||||
class="flowchart-panel"
|
class="flowchart-panel"
|
||||||
data-html5-flowchart
|
data-html5-flowchart
|
||||||
hx-get="{hx_url}"
|
hx-get="{hx_url}"
|
||||||
hx-trigger="every 30s"
|
{live_attr}
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
{oob_attr}
|
{oob_attr}
|
||||||
>
|
>
|
||||||
@@ -336,6 +338,7 @@ def render_html5_project_report(project_id: str, report: dict | None) -> str:
|
|||||||
data-html5-project-report
|
data-html5-project-report
|
||||||
hx-get="/html5/projects/{quote(project_id)}/report"
|
hx-get="/html5/projects/{quote(project_id)}/report"
|
||||||
hx-trigger="load"
|
hx-trigger="load"
|
||||||
|
sse-swap="project-report"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
>
|
>
|
||||||
<div class="panel-title">Отчет проекта</div>
|
<div class="panel-title">Отчет проекта</div>
|
||||||
@@ -357,7 +360,7 @@ def render_html5_project_report(project_id: str, report: dict | None) -> str:
|
|||||||
class="report-panel"
|
class="report-panel"
|
||||||
data-html5-project-report
|
data-html5-project-report
|
||||||
hx-get="/html5/projects/{quote(project_id)}/report"
|
hx-get="/html5/projects/{quote(project_id)}/report"
|
||||||
hx-trigger="every 15s"
|
sse-swap="project-report"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
>
|
>
|
||||||
<div class="panel-title">Отчет проекта</div>
|
<div class="panel-title">Отчет проекта</div>
|
||||||
@@ -424,9 +427,6 @@ def render_html5_object_report(
|
|||||||
<div
|
<div
|
||||||
class="report-panel"
|
class="report-panel"
|
||||||
data-html5-project-report
|
data-html5-project-report
|
||||||
hx-get="/html5/projects/{quote(project_id)}/report"
|
|
||||||
hx-trigger="every 15s"
|
|
||||||
hx-swap="outerHTML"
|
|
||||||
{oob_attr}
|
{oob_attr}
|
||||||
>
|
>
|
||||||
<div class="panel-title">Отчет объекта</div>
|
<div class="panel-title">Отчет объекта</div>
|
||||||
@@ -487,6 +487,7 @@ def render_html5_review(
|
|||||||
oob: bool = False,
|
oob: bool = False,
|
||||||
) -> str:
|
) -> str:
|
||||||
oob_attr = ' hx-swap-oob="outerHTML"' if oob else ""
|
oob_attr = ' hx-swap-oob="outerHTML"' if oob else ""
|
||||||
|
live_attr = ' sse-swap="project-review"' if title == "Review" and not oob else ""
|
||||||
if findings is None:
|
if findings is None:
|
||||||
return f"""
|
return f"""
|
||||||
<div
|
<div
|
||||||
@@ -494,6 +495,7 @@ def render_html5_review(
|
|||||||
data-html5-review
|
data-html5-review
|
||||||
hx-get="/html5/projects/{quote(project_id)}/review"
|
hx-get="/html5/projects/{quote(project_id)}/review"
|
||||||
hx-trigger="load"
|
hx-trigger="load"
|
||||||
|
{live_attr}
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
{oob_attr}
|
{oob_attr}
|
||||||
>
|
>
|
||||||
@@ -510,7 +512,7 @@ def render_html5_review(
|
|||||||
class="review-panel"
|
class="review-panel"
|
||||||
data-html5-review
|
data-html5-review
|
||||||
hx-get="/html5/projects/{quote(project_id)}/review"
|
hx-get="/html5/projects/{quote(project_id)}/review"
|
||||||
hx-trigger="every 20s"
|
{live_attr}
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
{oob_attr}
|
{oob_attr}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import asyncio
|
||||||
import base64
|
import base64
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
@@ -1694,21 +1695,33 @@ async def html5_project_editor(project_id: str, q: str = "") -> Response:
|
|||||||
|
|
||||||
@app.get("/html5/projects/{project_id}/events")
|
@app.get("/html5/projects/{project_id}/events")
|
||||||
async def html5_project_events(project_id: str, once: bool = False) -> StreamingResponse:
|
async def html5_project_events(project_id: str, once: bool = False) -> StreamingResponse:
|
||||||
def stream_status():
|
async def stream_status():
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
snapshot = _project_snapshot_or_404(project_id)
|
snapshot = _project_snapshot_or_404(project_id)
|
||||||
fragment = render_html5_status(project_id, snapshot)
|
fragment = render_html5_status(project_id, snapshot)
|
||||||
|
report = await project_report(project_id)
|
||||||
|
findings = await get_review(project_id)
|
||||||
|
flowchart = await project_flowchart(project_id, focus=None, depth=1, limit=80)
|
||||||
except HTTPException as error:
|
except HTTPException as error:
|
||||||
fragment = f'<span>project: {project_id}</span><span>error: {error.detail}</span>'
|
fragment = f'<span>project: {project_id}</span><span>error: {error.detail}</span>'
|
||||||
|
report = None
|
||||||
|
findings = None
|
||||||
|
flowchart = None
|
||||||
yield _html5_sse_event("status", fragment)
|
yield _html5_sse_event("status", fragment)
|
||||||
yield _html5_sse_event(
|
yield _html5_sse_event(
|
||||||
"authoring-changes",
|
"authoring-changes",
|
||||||
render_html5_authoring_changes(project_id, _authoring_change_summaries(project_id)),
|
render_html5_authoring_changes(project_id, _authoring_change_summaries(project_id)),
|
||||||
)
|
)
|
||||||
|
if report is not None:
|
||||||
|
yield _html5_sse_event("project-report", render_html5_project_report(project_id, report))
|
||||||
|
if findings is not None:
|
||||||
|
yield _html5_sse_event("project-review", render_html5_review(project_id, findings))
|
||||||
|
if flowchart is not None:
|
||||||
|
yield _html5_sse_event("project-flowchart", render_html5_flowchart(project_id, flowchart))
|
||||||
if once:
|
if once:
|
||||||
break
|
break
|
||||||
time.sleep(5)
|
await asyncio.sleep(5)
|
||||||
|
|
||||||
return StreamingResponse(
|
return StreamingResponse(
|
||||||
stream_status(),
|
stream_status(),
|
||||||
|
|||||||
@@ -110,10 +110,13 @@ def test_html5_server_rendered_project_editor(tmp_path: Path):
|
|||||||
assert "data-html5-symbol-results" in editor.text
|
assert "data-html5-symbol-results" in editor.text
|
||||||
assert "data-html5-symbol-detail" in editor.text
|
assert "data-html5-symbol-detail" in editor.text
|
||||||
assert "data-html5-flowchart" in editor.text
|
assert "data-html5-flowchart" in editor.text
|
||||||
|
assert 'sse-swap="project-flowchart"' in editor.text
|
||||||
assert f'hx-get="/html5/projects/{project_id}/flowchart?depth=1"' in editor.text
|
assert f'hx-get="/html5/projects/{project_id}/flowchart?depth=1"' in editor.text
|
||||||
assert "data-html5-project-report" in editor.text
|
assert "data-html5-project-report" in editor.text
|
||||||
|
assert 'sse-swap="project-report"' in editor.text
|
||||||
assert f'hx-get="/html5/projects/{project_id}/report"' in editor.text
|
assert f'hx-get="/html5/projects/{project_id}/report"' in editor.text
|
||||||
assert "data-html5-review" in editor.text
|
assert "data-html5-review" in editor.text
|
||||||
|
assert 'sse-swap="project-review"' in editor.text
|
||||||
assert f'hx-get="/html5/projects/{project_id}/review"' in editor.text
|
assert f'hx-get="/html5/projects/{project_id}/review"' in editor.text
|
||||||
assert "data-html5-authoring-preview" in editor.text
|
assert "data-html5-authoring-preview" in editor.text
|
||||||
assert "data-html5-authoring-preview-form" in editor.text
|
assert "data-html5-authoring-preview-form" in editor.text
|
||||||
@@ -147,7 +150,13 @@ def test_html5_server_rendered_project_editor(tmp_path: Path):
|
|||||||
first_chunk = next(events.iter_text())
|
first_chunk = next(events.iter_text())
|
||||||
assert "event: status" in first_chunk
|
assert "event: status" in first_chunk
|
||||||
assert "event: authoring-changes" in first_chunk
|
assert "event: authoring-changes" in first_chunk
|
||||||
|
assert "event: project-report" in first_chunk
|
||||||
|
assert "event: project-review" in first_chunk
|
||||||
|
assert "event: project-flowchart" in first_chunk
|
||||||
assert "data-html5-authoring-changes" in first_chunk
|
assert "data-html5-authoring-changes" in first_chunk
|
||||||
|
assert "data-html5-project-report" in first_chunk
|
||||||
|
assert "data-html5-review" in first_chunk
|
||||||
|
assert "data-html5-flowchart" in first_chunk
|
||||||
assert "data:" in first_chunk
|
assert "data:" in first_chunk
|
||||||
assert project_id in first_chunk
|
assert project_id in first_chunk
|
||||||
|
|
||||||
@@ -477,6 +486,7 @@ def test_html5_flowchart_fragment(tmp_path: Path):
|
|||||||
assert "depth=2" in flowchart.text
|
assert "depth=2" in flowchart.text
|
||||||
assert 'hx-target="[data-html5-flowchart]"' in flowchart.text
|
assert 'hx-target="[data-html5-flowchart]"' in flowchart.text
|
||||||
assert "data-html5-flowchart-focus" in flowchart.text
|
assert "data-html5-flowchart-focus" in flowchart.text
|
||||||
|
assert 'sse-swap="project-flowchart"' not in flowchart.text
|
||||||
assert 'hx-swap-oob="outerHTML"' not in flowchart.text
|
assert 'hx-swap-oob="outerHTML"' not in flowchart.text
|
||||||
assert "Карта связей" in flowchart.text
|
assert "Карта связей" in flowchart.text
|
||||||
assert "Nodes" in flowchart.text
|
assert "Nodes" in flowchart.text
|
||||||
|
|||||||
Reference in New Issue
Block a user