mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-09 03:20:56 +00:00
## What Makes the run-detail stage sidebar (shown on the Overview and Stages tabs) collapsible with a slide animation. - A toggle button slides the panel between full width (`w-56`) and an icon-only rail (`w-12`), animating `width` over 300ms with the same easing as the Ask Fabro panel. - When collapsed, **stage status icons stay visible** — green check / red X / spinning teal for running — so run progress is still scannable at a glance. Workflow links (Graph Source, Run Logs, etc.) collapse to icons too so they remain reachable. - Labels and durations become `sr-only` with `title` tooltips for hover. - The open/closed choice persists to `localStorage` (`fabro:stage-sidebar-collapsed`), carrying across the Overview and Stages tabs and reloads. ## Layout - The collapse toggle is inline with the `STAGES` heading row (or `WORKFLOW` when a run has no stages yet), so it doesn't push the stage list down. - The stage sidebar's top padding on the Stages tab was reduced (`pt-6` → `pt-3`) so the heading aligns with the adjacent content column and sits closer to the tab nav. ## Notes Self-contained in `StageSidebar` — `run-overview.tsx` and `run-stages.tsx` render it inside flex layouts that already track its width, so the slide works in both with no parent changes (aside from the padding tweak). Verified: `tsc` typecheck passes; `stage-sidebar` lib tests pass (10/10). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: fabro-sh-0530[bot] <281434857+fabro-sh-0530[bot]@users.noreply.github.com> Co-authored-by: Fabro <noreply@fabro.sh>
79 lines
2.1 KiB
Rust
79 lines
2.1 KiB
Rust
use std::any::{TypeId, type_name};
|
|
|
|
use fabro_api::types::{
|
|
LogDestination as ApiLogDestination, ObjectStoreSettings as ApiObjectStoreSettings,
|
|
ServerNamespace as ApiServerNamespace, ServerSettings as ApiServerSettings,
|
|
};
|
|
use fabro_config::ServerSettingsBuilder;
|
|
use fabro_types::ServerSettings;
|
|
use fabro_types::settings::ServerNamespace;
|
|
use fabro_types::settings::server::{LogDestination, ObjectStoreSettings};
|
|
|
|
#[test]
|
|
fn server_settings_family_reuses_domain_types() {
|
|
assert_same_type::<ApiServerSettings, ServerSettings>();
|
|
assert_same_type::<ApiServerNamespace, ServerNamespace>();
|
|
assert_same_type::<ApiObjectStoreSettings, ObjectStoreSettings>();
|
|
assert_same_type::<ApiLogDestination, LogDestination>();
|
|
}
|
|
|
|
#[test]
|
|
fn server_settings_json_matches_openapi_shape() {
|
|
let settings = ServerSettingsBuilder::from_toml(
|
|
r#"
|
|
_version = 1
|
|
|
|
[server.listen]
|
|
type = "tcp"
|
|
address = "127.0.0.1:32276"
|
|
|
|
[server.api]
|
|
url = "https://api.fabro.example.com"
|
|
|
|
[server.web]
|
|
enabled = true
|
|
url = "https://fabro.example.com"
|
|
|
|
[server.auth]
|
|
methods = ["dev-token", "github"]
|
|
|
|
[server.auth.github]
|
|
allowed_usernames = ["alice"]
|
|
|
|
[server.storage]
|
|
root = "/srv/fabro"
|
|
|
|
[server.logging]
|
|
destination = "stdout"
|
|
|
|
[server.integrations.github]
|
|
enabled = true
|
|
strategy = "app"
|
|
app_id = "12345"
|
|
client_id = "Iv1.abcdef"
|
|
slug = "fabro-dev"
|
|
"#,
|
|
)
|
|
.expect("settings should resolve");
|
|
|
|
let json = serde_json::to_value(&settings).expect("server settings should serialize");
|
|
assert_eq!(json["server"]["listen"]["type"], "tcp");
|
|
assert_eq!(json["server"]["listen"]["address"], "127.0.0.1:32276");
|
|
assert_eq!(json["server"]["storage"]["root"], "/srv/fabro");
|
|
assert_eq!(json["server"]["logging"]["destination"], "stdout");
|
|
assert!(json.get("features").is_none());
|
|
|
|
let round_trip: ApiServerSettings =
|
|
serde_json::from_value(json).expect("server settings should deserialize");
|
|
assert_eq!(round_trip, settings);
|
|
}
|
|
|
|
fn assert_same_type<T: 'static, U: 'static>() {
|
|
assert_eq!(
|
|
TypeId::of::<T>(),
|
|
TypeId::of::<U>(),
|
|
"{} should be the same type as {}",
|
|
type_name::<T>(),
|
|
type_name::<U>()
|
|
);
|
|
}
|