Add HTML5 project creation form
This commit is contained in:
@@ -10,9 +10,6 @@ from sir import NodeKind, SirSnapshot
|
|||||||
|
|
||||||
def render_html5_index(projects: Iterable[object]) -> str:
|
def render_html5_index(projects: Iterable[object]) -> str:
|
||||||
project_list = list(projects)
|
project_list = list(projects)
|
||||||
project_rows = "\n".join(_project_row(project) for project in project_list)
|
|
||||||
if not project_rows:
|
|
||||||
project_rows = '<tr><td colspan="4" class="muted">Проекты пока не настроены</td></tr>'
|
|
||||||
return _page(
|
return _page(
|
||||||
"SFERA HTML5",
|
"SFERA HTML5",
|
||||||
f"""
|
f"""
|
||||||
@@ -33,12 +30,13 @@ def render_html5_index(projects: Iterable[object]) -> str:
|
|||||||
<h2>Проекты</h2>
|
<h2>Проекты</h2>
|
||||||
<a class="button" href="/docs">API docs</a>
|
<a class="button" href="/docs">API docs</a>
|
||||||
</div>
|
</div>
|
||||||
|
{render_html5_project_create_form()}
|
||||||
<div class="table-wrap">
|
<div class="table-wrap">
|
||||||
<table data-html5-projects>
|
<table data-html5-projects>
|
||||||
<thead>
|
<thead>
|
||||||
<tr><th>Проект</th><th>Статус</th><th>Snapshot</th><th></th></tr>
|
<tr><th>Проект</th><th>Статус</th><th>Snapshot</th><th></th></tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>{project_rows}</tbody>
|
<tbody data-html5-projects-body>{render_html5_project_rows(project_list)}</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -47,6 +45,31 @@ def render_html5_index(projects: Iterable[object]) -> str:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def render_html5_project_create_form() -> str:
|
||||||
|
return """
|
||||||
|
<form
|
||||||
|
class="create-project"
|
||||||
|
method="post"
|
||||||
|
action="/html5/projects"
|
||||||
|
data-html5-project-create
|
||||||
|
hx-post="/html5/projects"
|
||||||
|
hx-target="[data-html5-projects-body]"
|
||||||
|
hx-swap="innerHTML"
|
||||||
|
>
|
||||||
|
<input name="project_id" placeholder="project_id" required />
|
||||||
|
<input name="name" placeholder="Название проекта" />
|
||||||
|
<button type="submit">Создать</button>
|
||||||
|
</form>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def render_html5_project_rows(projects: Iterable[object]) -> str:
|
||||||
|
project_rows = "\n".join(_project_row(project) for project in projects)
|
||||||
|
if not project_rows:
|
||||||
|
return '<tr><td colspan="4" class="muted">Проекты пока не настроены</td></tr>'
|
||||||
|
return project_rows
|
||||||
|
|
||||||
|
|
||||||
def render_html5_editor(
|
def render_html5_editor(
|
||||||
*,
|
*,
|
||||||
project_id: str,
|
project_id: str,
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ from api_server.html5 import (
|
|||||||
render_html5_editor,
|
render_html5_editor,
|
||||||
render_html5_index,
|
render_html5_index,
|
||||||
render_html5_project_setup,
|
render_html5_project_setup,
|
||||||
|
render_html5_project_rows,
|
||||||
render_html5_setup_summary,
|
render_html5_setup_summary,
|
||||||
render_html5_source,
|
render_html5_source,
|
||||||
render_html5_status,
|
render_html5_status,
|
||||||
@@ -1584,6 +1585,19 @@ async def html5_index() -> Response:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/html5/projects")
|
||||||
|
async def html5_create_project(request: Request) -> Response:
|
||||||
|
form = await _html5_form_data(request)
|
||||||
|
project_id = _form_value(form, "project_id")
|
||||||
|
if not project_id:
|
||||||
|
raise HTTPException(status_code=400, detail="project_id is required.")
|
||||||
|
await create_project(ProjectCreateRequest(project_id=project_id, name=_form_value(form, "name")))
|
||||||
|
return Response(
|
||||||
|
render_html5_project_rows(_project_summaries()),
|
||||||
|
media_type="text/html; charset=utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/html5/projects/{project_id}/editor")
|
@app.get("/html5/projects/{project_id}/editor")
|
||||||
async def html5_project_editor(project_id: str, q: str = "") -> Response:
|
async def html5_project_editor(project_id: str, q: str = "") -> Response:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -142,6 +142,29 @@ def test_html5_server_rendered_project_editor(tmp_path: Path):
|
|||||||
assert "<html" not in source.text
|
assert "<html" not in source.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_html5_project_index_creates_project_with_fragment():
|
||||||
|
client = TestClient(app)
|
||||||
|
project_id = f"html5-created-{uuid4()}"
|
||||||
|
|
||||||
|
index = client.get("/html5")
|
||||||
|
assert index.status_code == 200
|
||||||
|
assert 'data-html5-project-create' in index.text
|
||||||
|
assert 'data-html5-projects-body' in index.text
|
||||||
|
assert 'hx-post="/html5/projects"' in index.text
|
||||||
|
|
||||||
|
created = client.post("/html5/projects", data={"project_id": project_id, "name": "HTML5 Created"})
|
||||||
|
assert created.status_code == 200
|
||||||
|
assert "text/html" in created.headers["content-type"]
|
||||||
|
assert f'data-html5-project="{project_id}"' in created.text
|
||||||
|
assert "HTML5 Created" in created.text
|
||||||
|
assert f"/html5/projects/{project_id}/setup" in created.text
|
||||||
|
assert "<html" not in created.text
|
||||||
|
|
||||||
|
setup = client.get(f"/html5/projects/{project_id}/setup")
|
||||||
|
assert setup.status_code == 200
|
||||||
|
assert "HTML5 Created" in setup.text
|
||||||
|
|
||||||
|
|
||||||
def test_html5_project_setup_renders_server_fragments():
|
def test_html5_project_setup_renders_server_fragments():
|
||||||
client = TestClient(app)
|
client = TestClient(app)
|
||||||
project_id = f"html5-setup-{uuid4()}"
|
project_id = f"html5-setup-{uuid4()}"
|
||||||
|
|||||||
Reference in New Issue
Block a user