refactor(techdemo): shorten generated resource paths
Import scoped generated modules at the page boundary so handlers and tests read as local slots/forms/handles/classes without hiding ownership or adding framework machinery. req: component/003 req: dx/006
This commit is contained in:
@@ -3,7 +3,9 @@ pub mod ui {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ui;
|
||||
use super::ui::control_center::{forms, handles, slots};
|
||||
use super::ui::issue_card::handles as card_handles;
|
||||
use super::ui::issue_lane::events as lane_events;
|
||||
use hemplate::Hemplate;
|
||||
use slhx::{Effect, IntoEffect, Payload, RenderSlotExt};
|
||||
use slhx_test::inspect;
|
||||
@@ -28,14 +30,14 @@ mod tests {
|
||||
fn techdemo_uses_generated_slots_for_multi_target_updates() {
|
||||
fn update() -> impl IntoEffect {
|
||||
(
|
||||
ui::control_center::slots::hero_metrics.render(&FastMetric { label: "fast" }),
|
||||
ui::control_center::slots::notice.text("typed"),
|
||||
slots::hero_metrics.render(&FastMetric { label: "fast" }),
|
||||
slots::notice.text("typed"),
|
||||
)
|
||||
}
|
||||
|
||||
let batch = inspect(update());
|
||||
assert!(batch.has_slot(ui::control_center::slots::hero_metrics));
|
||||
assert!(batch.has_slot(ui::control_center::slots::notice));
|
||||
assert!(batch.has_slot(slots::hero_metrics));
|
||||
assert!(batch.has_slot(slots::notice));
|
||||
}
|
||||
|
||||
// req: examples/001 req: form/001 req: form/004 req: form/006 req: derive_handler/003
|
||||
@@ -43,34 +45,31 @@ mod tests {
|
||||
fn techdemo_form_handler_is_checked_against_hemplate_form() {
|
||||
#[slhx::handler]
|
||||
fn launch_work(_form: slhx::Form<LaunchWork>) -> impl IntoEffect {
|
||||
ui::control_center::slots::notice.text("queued")
|
||||
slots::notice.text("queued")
|
||||
}
|
||||
|
||||
let batch = inspect(launch_work(LaunchWork::FORM));
|
||||
|
||||
assert!(batch.has_slot(ui::control_center::slots::notice));
|
||||
assert!(batch.has_slot(slots::notice));
|
||||
assert!(matches!(batch.ops(), [Effect::Put { payload: Payload::Text(_), .. }]));
|
||||
}
|
||||
|
||||
// req: examples/001 req: form/002 req: codegen/003
|
||||
#[test]
|
||||
fn techdemo_exports_form_and_interaction_handles() {
|
||||
assert_ne!(
|
||||
ui::control_center::handles::launch_work.id(),
|
||||
ui::issue_card::handles::advance_work.id()
|
||||
);
|
||||
assert_ne!(handles::launch_work.id(), card_handles::advance_work.id());
|
||||
assert_eq!(
|
||||
ui::control_center::forms::launch_work.field("title").resource,
|
||||
ui::control_center::forms::launch_work.id()
|
||||
forms::launch_work.field("title").resource,
|
||||
forms::launch_work.id()
|
||||
);
|
||||
}
|
||||
|
||||
// req: codegen/006
|
||||
#[test]
|
||||
fn techdemo_exports_generated_event_constants() {
|
||||
assert_eq!(ui::issue_lane::events::drop.as_str(), "drop");
|
||||
assert_eq!(lane_events::drop.as_str(), "drop");
|
||||
assert!(matches!(
|
||||
slhx::event(ui::issue_lane::events::drop, "card-1"),
|
||||
slhx::event(lane_events::drop, "card-1"),
|
||||
Effect::Emit { name, payload } if name == "drop" && payload == "card-1"
|
||||
));
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@ use slhx_axum::{
|
||||
PageRequest,
|
||||
};
|
||||
use slhx_techdemo::ui;
|
||||
use slhx_techdemo::ui::control_center::{classes, forms, handles, slots};
|
||||
use slhx_techdemo::ui::issue_card::handles as card_handles;
|
||||
use slhx_techdemo::ui::issue_lane::handles as lane_handles;
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
use std::convert::Infallible;
|
||||
use std::net::SocketAddr;
|
||||
@@ -266,13 +269,13 @@ async fn interact(
|
||||
// req: push/001 req: push/003 req: examples/001
|
||||
async fn events(Query(params): Query<BTreeMap<String, String>>) -> impl IntoResponse {
|
||||
if params.contains_key("once") {
|
||||
let effect = ui::control_center::slots::live_feed.render(&LiveFeed { tick: 1 });
|
||||
let effect = slots::live_feed.render(&LiveFeed { tick: 1 });
|
||||
return sse(stream::iter([Ok::<_, Infallible>(effect.into_batch(ui::BUILD_FINGERPRINT))]).boxed());
|
||||
}
|
||||
|
||||
let batches = stream::unfold(1_u64, |tick| async move {
|
||||
tokio::time::sleep(Duration::from_secs(4)).await;
|
||||
let effect = ui::control_center::slots::live_feed.render(&LiveFeed { tick });
|
||||
let effect = slots::live_feed.render(&LiveFeed { tick });
|
||||
Some((Ok::<_, Infallible>(effect.into_batch(ui::BUILD_FINGERPRINT)), tick + 1))
|
||||
})
|
||||
.boxed();
|
||||
@@ -281,7 +284,7 @@ async fn events(Query(params): Query<BTreeMap<String, String>>) -> impl IntoResp
|
||||
|
||||
fn registry(shared: Arc<Shared>) -> HandlerRegistry {
|
||||
HandlerRegistry::new(ui::BUILD_FINGERPRINT)
|
||||
.register_handle(ui::control_center::handles::launch_work, {
|
||||
.register_handle(handles::launch_work, {
|
||||
let shared = shared.clone();
|
||||
move |form| {
|
||||
// req: form/002 req: examples/001
|
||||
@@ -300,7 +303,7 @@ fn registry(shared: Arc<Shared>) -> HandlerRegistry {
|
||||
demo_effects(&demo, "Launch accepted · 4 targets updated")
|
||||
}
|
||||
})
|
||||
.register_handle(ui::issue_card::handles::advance_work, {
|
||||
.register_handle(card_handles::advance_work, {
|
||||
let shared = shared.clone();
|
||||
move |form| {
|
||||
// req: list/003 req: examples/001
|
||||
@@ -318,7 +321,7 @@ fn registry(shared: Arc<Shared>) -> HandlerRegistry {
|
||||
demo_effects(&demo, "Pipeline advanced")
|
||||
}
|
||||
})
|
||||
.register_handle(ui::issue_lane::handles::move_to_lane, {
|
||||
.register_handle(lane_handles::move_to_lane, {
|
||||
let shared = shared.clone();
|
||||
move |form| {
|
||||
// req: list/003 req: examples/001
|
||||
@@ -340,7 +343,7 @@ fn registry(shared: Arc<Shared>) -> HandlerRegistry {
|
||||
demo_effects(&demo, "Drag-and-drop move persisted")
|
||||
}
|
||||
})
|
||||
.register_handle(ui::issue_card::handles::delete_work, {
|
||||
.register_handle(card_handles::delete_work, {
|
||||
let shared = shared.clone();
|
||||
move |form| {
|
||||
// req: list/003 req: examples/001
|
||||
@@ -359,7 +362,7 @@ fn registry(shared: Arc<Shared>) -> HandlerRegistry {
|
||||
demo_effects(&demo, "Card removed")
|
||||
}
|
||||
})
|
||||
.register_handle(ui::issue_card::handles::spotlight_work, {
|
||||
.register_handle(card_handles::spotlight_work, {
|
||||
let shared = shared.clone();
|
||||
move |form| {
|
||||
// req: examples/001
|
||||
@@ -374,23 +377,23 @@ fn registry(shared: Arc<Shared>) -> HandlerRegistry {
|
||||
demo_effects(&demo, "Inspector focused")
|
||||
}
|
||||
})
|
||||
.register_handle(ui::control_center::handles::simulate_push, {
|
||||
.register_handle(handles::simulate_push, {
|
||||
let shared = shared.clone();
|
||||
move |_| {
|
||||
// req: push/003 req: examples/001
|
||||
let mut demo = shared.demo.lock().unwrap();
|
||||
demo.log("Simulated push event produced the same EffectBatch shape");
|
||||
(
|
||||
ui::control_center::slots::live_feed.render(&LiveFeed {
|
||||
slots::live_feed.render(&LiveFeed {
|
||||
tick: demo.activity.len() as u64,
|
||||
}),
|
||||
ui::control_center::slots::activity.render(&activity_view(&demo)),
|
||||
ui::control_center::slots::notice.text("Push simulated · no client app code"),
|
||||
slots::activity.render(&activity_view(&demo)),
|
||||
slots::notice.text("Push simulated · no client app code"),
|
||||
slhx::event("slhx:island-orbit", island_snapshot(&demo)),
|
||||
)
|
||||
}
|
||||
})
|
||||
.register_handle(ui::control_center::handles::reset_demo, {
|
||||
.register_handle(handles::reset_demo, {
|
||||
let shared = shared.clone();
|
||||
move |_| {
|
||||
// req: examples/001
|
||||
@@ -411,12 +414,12 @@ 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.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),
|
||||
ui::control_center::forms::launch_work.clear("title"),
|
||||
slots::hero_metrics.render(&hero_view(demo)),
|
||||
slots::board.html(render_board(demo)),
|
||||
slots::activity.render(&activity_view(demo)),
|
||||
slots::inspector.render(&inspector_view(demo)),
|
||||
slots::notice.text(notice),
|
||||
forms::launch_work.clear("title"),
|
||||
slhx::event("slhx:island-orbit", island_snapshot(demo)),
|
||||
)
|
||||
}
|
||||
@@ -485,7 +488,7 @@ fn board_view(demo: &DemoState) -> BoardLanes {
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, (lane_id, title, description))| IssueLane {
|
||||
class: ui::control_center::classes::lane,
|
||||
class: classes::lane,
|
||||
lane_id,
|
||||
title,
|
||||
description,
|
||||
@@ -510,11 +513,11 @@ fn issue_card(item: &WorkItem, selected: bool) -> IssueCard {
|
||||
IssueCard {
|
||||
class: if selected {
|
||||
CssClasses::from([
|
||||
ui::control_center::classes::work_card,
|
||||
ui::control_center::classes::is_selected,
|
||||
classes::work_card,
|
||||
classes::is_selected,
|
||||
])
|
||||
} else {
|
||||
CssClasses::from(ui::control_center::classes::work_card)
|
||||
CssClasses::from(classes::work_card)
|
||||
},
|
||||
id: item.id,
|
||||
title: item.title.clone(),
|
||||
@@ -584,7 +587,7 @@ fn architecture_activity() -> SafeHtml {
|
||||
|
||||
fn render_control_center(page: ControlCenter) -> String {
|
||||
// req: html_safety/002 req: view/001 req: component/003
|
||||
ui::control_center::render_html(&page).into_string()
|
||||
ui::render_html(&page).into_string()
|
||||
}
|
||||
|
||||
fn render_template(template: &impl Hemplate) -> String {
|
||||
@@ -666,9 +669,9 @@ mod tests {
|
||||
#[test]
|
||||
fn generated_css_class_flows_through_hemplate_dynamic_attribute() {
|
||||
let board = render_board(&DemoState::default());
|
||||
assert_eq!(ui::control_center::classes::lane.as_str(), "lane");
|
||||
assert_eq!(ui::control_center::classes::work_card.as_str(), "work-card");
|
||||
assert_eq!(ui::control_center::classes::is_selected.as_str(), "is-selected");
|
||||
assert_eq!(classes::lane.as_str(), "lane");
|
||||
assert_eq!(classes::work_card.as_str(), "work-card");
|
||||
assert_eq!(classes::is_selected.as_str(), "is-selected");
|
||||
|
||||
let document = Html::parse_fragment(board.as_str());
|
||||
assert_eq!(document.select(&selector(".lanes > section.lane")).count(), 3);
|
||||
|
||||
Reference in New Issue
Block a user