git-ents.gitmain
⌘K
foforge
commit 4790a9c
roots: complete issue assignees from a members datalist

Assisted-by: Claude:claude-fable-5

Joseph D. Carpinelli · 1 month ago

Reviews

No reviews of this commit yet — record a verdict below.

Start a review

verdict

crates/cli/ents-web/tests/router.rs @@ -2310,6 +2310,26 @@ ); } +/// The issues page carries a `datalist#members` of enrolled usernames so +/// the assignees field completes by member id in place. +#[tokio::test] +async fn issue_forms_carry_a_members_datalist() { + let dir = seed_repo(&[("README.md", "# hi\n")]); + let state = build_state_at( + FixtureIdentity { + name: "local-user", + key: Keypair::from_seed(1), + }, + dir.path().to_owned(), + ); + let router = ents_web::router(state); + let body = get_body(&router, "/issues").await; + assert!( + body.contains("datalist id=\"members\""), + "the assignees field has a members datalist to complete from: {body}" + ); +} + /// A show page for an id with no ref at all is a real 404, not a 500 -- /// `ents_forge::Error::NotFound` keeps its status through the `Forge` /// box (the box exists for variant-size hygiene only).
crates/cli/ents-web/src/pages/issues.rs @@ -81,6 +81,7 @@ } h2 { "Open an Issue" } (new_form(&session)) + (super::members_datalist(&state)) } }, )) @@ -151,6 +152,7 @@ details { summary { "Edit" } (edit_form(&session, &issue)) + (super::members_datalist(&state)) } h2 { "Discussion" } (crate::pages::comments::thread_section(&state, &session, &thread, &return_to)) @@ -351,7 +353,7 @@ input type="text" name="state" value="open" list="issue-states"; } (state_datalist()) - label { "assignees" input type="text" name="assignees" placeholder="alice, bob"; } + label { "assignees" input type="text" name="assignees" placeholder="alice, bob" list="members"; } label { "labels" input type="text" name="labels" placeholder="bug, gate"; } label { "body" textarea name="body" {} } button type="submit" { "Open Issue" } @@ -373,7 +375,7 @@ (state_datalist()) label { "assignees" - input type="text" name="assignees" value=(join_members(&issue.assignees)); + input type="text" name="assignees" value=(join_members(&issue.assignees)) list="members"; } label { "labels" input type="text" name="labels" value=(issue.labels.join(", ")); } button type="submit" { "Save" }
crates/cli/ents-web/src/pages/mod.rs @@ -407,6 +407,29 @@ } } +/// A `<datalist id="members">` of every enrolled username +/// (`refs/meta/member/*`), for forms whose text field names a member -- +/// an issue's assignees completes by id in place; richer matching (by +/// key, fuzzy) stays with the palette. Best-effort: a ref-store read +/// failure renders an empty datalist rather than failing the page the +/// form sits on. +pub(crate) fn members_datalist<O>(state: &AppState<O>) -> Markup { + let mut names = Vec::new(); + if let Ok(entries) = state.refs.iter_prefix("refs/meta/member/") { + for (name, _tip) in entries.flatten() { + let path = name.as_bstr().to_string(); + if let Some(username) = path.strip_prefix("refs/meta/member/") { + names.push(username.to_owned()); + } + } + } + html! { + datalist id="members" { + @for name in &names { option value=(name) {} } + } + } +} + /// The one-level breadcrumb trail every `/{id}` child page renders above /// its own content -- "parent \u{203a} here", reusing the `.crumbs` markup /// pattern [`super::files`]'s own multi-level path trail already renders