refactor(techdemo): scope card handles to partials
Move board card and lane actions onto their reusable partial templates, register the scoped generated handles directly, and remove hidden shell-level handle anchors and manual handle fields from the rendered view data. req: component/003 req: view/001 req: examples/001
This commit is contained in:
@@ -57,7 +57,7 @@ mod tests {
|
||||
fn techdemo_exports_form_and_interaction_handles() {
|
||||
assert_ne!(
|
||||
ui::control_center::handles::launch_work.id(),
|
||||
ui::control_center::handles::advance_work.id()
|
||||
ui::issue_card::handles::advance_work.id()
|
||||
);
|
||||
assert_eq!(
|
||||
ui::control_center::forms::launch_work.field("title").resource,
|
||||
|
||||
@@ -4,7 +4,7 @@ use axum::routing::get;
|
||||
use axum::Router;
|
||||
use futures_util::{stream, StreamExt};
|
||||
use hemplate::Hemplate;
|
||||
use slhx::{CssClass, CssClasses, Handle, IntoEffect, RenderSlotExt, SafeHtml};
|
||||
use slhx::{CssClass, CssClasses, IntoEffect, RenderSlotExt, SafeHtml};
|
||||
use slhx_axum::{
|
||||
runtime_js, sse, DispatchRejection, EffectResponse, HandlerRegistry, InteractionForm,
|
||||
PageRequest,
|
||||
@@ -102,7 +102,6 @@ struct Shared {
|
||||
struct IssueLane {
|
||||
class: CssClass,
|
||||
lane_id: &'static str,
|
||||
move_handle: Handle<()>,
|
||||
title: &'static str,
|
||||
description: &'static str,
|
||||
cards: Vec<IssueCard>,
|
||||
@@ -116,9 +115,6 @@ struct IssueCard {
|
||||
title: String,
|
||||
stage: &'static str,
|
||||
impact_style: String,
|
||||
spotlight_handle: Handle<()>,
|
||||
advance_handle: Handle<()>,
|
||||
delete_handle: Handle<()>,
|
||||
}
|
||||
|
||||
#[derive(Hemplate)]
|
||||
@@ -304,7 +300,7 @@ fn registry(shared: Arc<Shared>) -> HandlerRegistry {
|
||||
demo_effects(&demo, "Launch accepted · 4 targets updated")
|
||||
}
|
||||
})
|
||||
.register_handle(ui::control_center::handles::advance_work, {
|
||||
.register_handle(ui::issue_card::handles::advance_work, {
|
||||
let shared = shared.clone();
|
||||
move |form| {
|
||||
// req: list/003 req: examples/001
|
||||
@@ -322,7 +318,7 @@ fn registry(shared: Arc<Shared>) -> HandlerRegistry {
|
||||
demo_effects(&demo, "Pipeline advanced")
|
||||
}
|
||||
})
|
||||
.register_handle(ui::control_center::handles::move_to_lane, {
|
||||
.register_handle(ui::issue_lane::handles::move_to_lane, {
|
||||
let shared = shared.clone();
|
||||
move |form| {
|
||||
// req: list/003 req: examples/001
|
||||
@@ -344,7 +340,7 @@ fn registry(shared: Arc<Shared>) -> HandlerRegistry {
|
||||
demo_effects(&demo, "Drag-and-drop move persisted")
|
||||
}
|
||||
})
|
||||
.register_handle(ui::control_center::handles::delete_work, {
|
||||
.register_handle(ui::issue_card::handles::delete_work, {
|
||||
let shared = shared.clone();
|
||||
move |form| {
|
||||
// req: list/003 req: examples/001
|
||||
@@ -363,7 +359,7 @@ fn registry(shared: Arc<Shared>) -> HandlerRegistry {
|
||||
demo_effects(&demo, "Card removed")
|
||||
}
|
||||
})
|
||||
.register_handle(ui::control_center::handles::spotlight_work, {
|
||||
.register_handle(ui::issue_card::handles::spotlight_work, {
|
||||
let shared = shared.clone();
|
||||
move |form| {
|
||||
// req: examples/001
|
||||
@@ -416,7 +412,7 @@ fn update_work(demo: &mut DemoState, id: Option<&str>, update: impl FnOnce(&mut
|
||||
fn demo_effects(demo: &DemoState, notice: &'static str) -> impl IntoEffect {
|
||||
(
|
||||
ui::control_center::slots::hero_metrics.render(&hero_view(demo)),
|
||||
ui::control_center::slots::board.render(&board_view(demo)),
|
||||
ui::control_center::slots::board.html(render_board(demo)),
|
||||
ui::control_center::slots::activity.render(&activity_view(demo)),
|
||||
ui::control_center::slots::inspector.render(&inspector_view(demo)),
|
||||
ui::control_center::slots::notice.text(notice),
|
||||
@@ -491,7 +487,6 @@ fn board_view(demo: &DemoState) -> BoardLanes {
|
||||
.map(|(idx, (lane_id, title, description))| IssueLane {
|
||||
class: ui::control_center::classes::lane,
|
||||
lane_id,
|
||||
move_handle: ui::control_center::handles::move_to_lane,
|
||||
title,
|
||||
description,
|
||||
cards: demo
|
||||
@@ -508,7 +503,8 @@ fn board_view(demo: &DemoState) -> BoardLanes {
|
||||
|
||||
fn render_board(demo: &DemoState) -> SafeHtml {
|
||||
// req: html_safety/002 req: view/001
|
||||
slhx::render_html(&board_view(demo))
|
||||
let html = render_template(&board_view(demo));
|
||||
SafeHtml::trusted(ui::issue_lane::lower_html(ui::issue_card::lower_html(html)))
|
||||
}
|
||||
|
||||
fn issue_card(item: &WorkItem, selected: bool) -> IssueCard {
|
||||
@@ -525,9 +521,6 @@ fn issue_card(item: &WorkItem, selected: bool) -> IssueCard {
|
||||
title: item.title.clone(),
|
||||
stage: item.stage.label(),
|
||||
impact_style: format!("width:{}%", item.impact as usize * 11),
|
||||
spotlight_handle: ui::control_center::handles::spotlight_work,
|
||||
advance_handle: ui::control_center::handles::advance_work,
|
||||
delete_handle: ui::control_center::handles::delete_work,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,8 +65,4 @@
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<button type="button" data-slhx-handle="advance_work" hidden="hidden">Advance</button>
|
||||
<button type="button" data-slhx-handle="delete_work" hidden="hidden">Delete</button>
|
||||
<button type="button" data-slhx-handle="spotlight_work" hidden="hidden">Spotlight</button>
|
||||
<button type="button" data-slhx-handle="move_to_lane" hidden="hidden">Move to lane</button>
|
||||
</main>
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<header><strong>{+ self.title +}</strong><span class="pill">{+ self.stage +}</span></header>
|
||||
<div class="impact"><i +style="self.impact_style"></i></div>
|
||||
<div class="card-actions">
|
||||
<button type="button" +data-hid="self.spotlight_handle" +data-work-id="self.id">Inspect</button>
|
||||
<button type="button" +data-hid="self.advance_handle" +data-work-id="self.id">Advance</button>
|
||||
<button type="button" +data-hid="self.delete_handle" +data-work-id="self.id">Delete</button>
|
||||
<button type="button" data-slhx-handle="spotlight_work" +data-work-id="self.id">Inspect</button>
|
||||
<button type="button" data-slhx-handle="advance_work" +data-work-id="self.id">Advance</button>
|
||||
<button type="button" data-slhx-handle="delete_work" +data-work-id="self.id">Delete</button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<section +class="self.class" +data-lane="self.lane_id" +data-hid="self.move_handle" data-slhx-on="drop">
|
||||
<section +class="self.class" +data-lane="self.lane_id" data-slhx-handle="move_to_lane" data-slhx-on="drop">
|
||||
<h3>{+ self.title +}</h3>
|
||||
<p>{+ self.description +}</p>
|
||||
<template h-for="card in &self.cards">
|
||||
|
||||
@@ -72,7 +72,7 @@ async fn browser_drives_typed_product_end_to_end() -> WebDriverResult<()> {
|
||||
wait_for_text(&driver, &slot_selector(ui::control_center::slots::notice), "Drag-and-drop move persisted").await?;
|
||||
|
||||
driver
|
||||
.find(By::Css(&card_button_selector(ui::control_center::handles::spotlight_work, 2)))
|
||||
.find(By::Css(&card_button_selector(ui::issue_card::handles::spotlight_work, 2)))
|
||||
.await?
|
||||
.click()
|
||||
.await?;
|
||||
@@ -84,7 +84,7 @@ async fn browser_drives_typed_product_end_to_end() -> WebDriverResult<()> {
|
||||
.await?;
|
||||
|
||||
driver
|
||||
.find(By::Css(&card_button_selector(ui::control_center::handles::advance_work, 3)))
|
||||
.find(By::Css(&card_button_selector(ui::issue_card::handles::advance_work, 3)))
|
||||
.await?
|
||||
.click()
|
||||
.await?;
|
||||
|
||||
@@ -116,32 +116,32 @@ fn product_is_e2e_working_over_http() {
|
||||
|
||||
let move_to_lane = post(
|
||||
"/",
|
||||
&format!("__h={}&work_id=4&lane=runtime", ui::control_center::handles::move_to_lane),
|
||||
&format!("__h={}&work_id=4&lane=runtime", ui::issue_lane::handles::move_to_lane),
|
||||
);
|
||||
assert_effect_response(&move_to_lane);
|
||||
let move_to_lane_batch = move_to_lane.batch();
|
||||
assert_card(&move_to_lane_batch, "Design hero moment", "Runtime", "Active", "width:99%");
|
||||
assert_payload_contains(&move_to_lane_batch, "Drag-and-drop move persisted");
|
||||
|
||||
let inspect = post("/", "__h=3112123592&work_id=4");
|
||||
let inspect = post("/", &format!("__h={}&work_id=4", ui::issue_card::handles::spotlight_work));
|
||||
assert_effect_response(&inspect);
|
||||
let inspect_batch = inspect.batch();
|
||||
assert_payload_contains(&inspect_batch, "Design hero moment · lane=Runtime");
|
||||
assert_payload_contains(&inspect_batch, "Inspector focused");
|
||||
|
||||
let advance = post("/", "__h=4085043678&work_id=4");
|
||||
let advance = post("/", &format!("__h={}&work_id=4", ui::issue_card::handles::advance_work));
|
||||
assert_effect_response(&advance);
|
||||
let advance_batch = advance.batch();
|
||||
assert_payload_contains(&advance_batch, "Pipeline advanced");
|
||||
assert_payload_contains(&advance_batch, "<span class=\"pill\">Active</span>");
|
||||
|
||||
let advance_default = post("/", "__h=4085043678&work_id=5");
|
||||
let advance_default = post("/", &format!("__h={}&work_id=5", ui::issue_card::handles::advance_work));
|
||||
assert_effect_response(&advance_default);
|
||||
let advance_default_batch = advance_default.batch();
|
||||
assert_payload_contains(&advance_default_batch, "Default impact");
|
||||
assert_card(&advance_default_batch, "Default impact", "Compiler", "Active", "width:55%");
|
||||
|
||||
let ship_default = post("/", "__h=4085043678&work_id=5");
|
||||
let ship_default = post("/", &format!("__h={}&work_id=5", ui::issue_card::handles::advance_work));
|
||||
assert_effect_response(&ship_default);
|
||||
let ship_default_batch = ship_default.batch();
|
||||
assert_card(&ship_default_batch, "Default impact", "Product", "Shipped", "width:55%");
|
||||
@@ -154,12 +154,12 @@ fn product_is_e2e_working_over_http() {
|
||||
assert_payload_contains(&push_batch, "Simulated push event produced the same EffectBatch shape");
|
||||
assert_emit(&push_batch, "slhx:island-orbit", "activity rows");
|
||||
|
||||
let delete_missing = post("/", "__h=165211725&work_id=999");
|
||||
let delete_missing = post("/", &format!("__h={}&work_id=999", ui::issue_card::handles::delete_work));
|
||||
assert_effect_response(&delete_missing);
|
||||
let delete_missing_batch = delete_missing.batch();
|
||||
assert_payload_not_contains(&delete_missing_batch, "Deleted card #999");
|
||||
|
||||
let delete = post("/", "__h=165211725&work_id=4");
|
||||
let delete = post("/", &format!("__h={}&work_id=4", ui::issue_card::handles::delete_work));
|
||||
assert_effect_response(&delete);
|
||||
let delete_batch = delete.batch();
|
||||
assert_payload_contains(&delete_batch, "Card removed");
|
||||
|
||||
Reference in New Issue
Block a user