You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by ar...@apache.org on 2026/04/14 15:46:59 UTC
(tooling-trusted-releases) 02/04: #776 - Add 50k limit to vote comment and add nav link to jump back to form
This is an automated email from the ASF dual-hosted git repository.
arm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-releases.git
commit bd5510006c7c3529b26165b32d684a3ad6c4e419
Author: Alastair McFarlane <ar...@apache.org>
AuthorDate: Tue Apr 14 10:46:04 2026 +0100
#776 - Add 50k limit to vote comment and add nav link to jump back to form
---
atr/form.py | 21 ++++++++++++++-------
atr/get/vote.py | 2 +-
atr/shared/vote.py | 2 +-
3 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/atr/form.py b/atr/form.py
index 18c31277..57317323 100644
--- a/atr/form.py
+++ b/atr/form.py
@@ -138,16 +138,17 @@ def flash_error_summary(errors: list[pydantic_core.ErrorDetails], flash_data: di
div = htm.Block(htm.div, classes=".atr-initial")
div.text(f"Please fix the following {util.plural(len(errors), 'issue', include_count=False)}:")
with div.block(htm.ul, classes=".mt-2.mb-0") as ul:
- for i, flash_datum in enumerate(flash_data.values()):
+ for i, (field_name, flash_datum) in enumerate(flash_data.items()):
if i > 9:
ul.li["And more, not shown here..."]
break
if "msg" in flash_datum:
label = flash_datum["label"]
+ jump = htm.a(href=f"#{field_name}", class_="ms-1 text-decoration-none small")["\u2193"]
if label == "*":
- ul.li[flash_datum["msg"]]
+ ul.li[flash_datum["msg"], " ", jump]
else:
- ul.li[htm.strong[label], ": ", flash_datum["msg"]]
+ ul.li[htm.strong[label], ": ", flash_datum["msg"], " ", jump]
summary = div.collect()
return markupsafe.Markup(summary)
@@ -164,7 +165,13 @@ def json_suitable(field_value: Any) -> Any:
def label(
- description: str, documentation: str | None = None, *, default: Any = ..., widget: Widget | None = None, **kwargs
+ description: str,
+ documentation: str | None = None,
+ *,
+ default: Any = ...,
+ widget: Widget | None = None,
+ max_length: int | None = None,
+ **kwargs,
) -> Any:
extra: dict[str, Any] = {}
if widget is not None:
@@ -173,7 +180,7 @@ def label(
extra["documentation"] = documentation
if len(kwargs) > 0:
extra.update(kwargs)
- return pydantic.Field(default, description=description, json_schema_extra=extra)
+ return pydantic.Field(default, description=description, json_schema_extra=extra, max_length=max_length)
def name_and_label(form_cls: type[Form], i: int, loc: tuple[str | int, ...]) -> tuple[str, str]:
@@ -938,7 +945,7 @@ def _render_widget( # noqa: C901
checkbox_label = htpy.label(for_=checkbox_id, class_="form-check-label")[label]
checkboxes.append(htpy.div(class_="form-check")[checkbox_input, checkbox_label])
elements.extend(checkboxes)
- widget = htm.div[checkboxes]
+ widget = htm.div(id=field_name)[checkboxes]
case Widget.CUSTOM:
if custom and (field_name in custom):
@@ -997,7 +1004,7 @@ def _render_widget( # noqa: C901
radio_label = htpy.label(for_=radio_id, class_="form-check-label")[label]
radios.append(htpy.div(class_="form-check")[radio_input, radio_label])
elements.extend(radios)
- widget = htm.div[radios]
+ widget = htm.div(id=field_name)[radios]
case Widget.SELECT:
# Check for dynamic choices from defaults or field_value
diff --git a/atr/get/vote.py b/atr/get/vote.py
index be0a98be..5d4c4bc1 100644
--- a/atr/get/vote.py
+++ b/atr/get/vote.py
@@ -574,7 +574,7 @@ async def _render_vote_authenticated(
page.p["Your vote will be sent to ", htpy.code[mailing_list], "."]
# Build the vote widget
- vote_widget = htpy.div(class_="btn-group", role="group")[
+ vote_widget = htpy.div(id="decision", class_="btn-group", role="group")[
htpy.input(type="radio", class_="btn-check", name="decision", id="decision_0", value="+1", autocomplete="off"),
htpy.label(class_="btn btn-outline-success", for_="decision_0")[f"+1 ({potency})"],
htpy.input(type="radio", class_="btn-check", name="decision", id="decision_1", value="0", autocomplete="off"),
diff --git a/atr/shared/vote.py b/atr/shared/vote.py
index e634293b..660dd898 100644
--- a/atr/shared/vote.py
+++ b/atr/shared/vote.py
@@ -24,7 +24,7 @@ import atr.storage as storage
class CastVoteForm(form.Form):
decision: Literal["+1", "0", "-1"] = form.label("Your vote", widget=form.Widget.CUSTOM)
- comment: str = form.label("Comment (optional)", widget=form.Widget.TEXTAREA)
+ comment: str = form.label("Comment (optional)", widget=form.Widget.TEXTAREA, max_length=50_000)
async def is_binding(
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org