fixed up the featured artist thing

This commit is contained in:
Connor Johnstone
2026-03-24 11:38:07 -04:00
parent 36345b12ee
commit 7c30f288cd
11 changed files with 258 additions and 107 deletions
+105 -68
View File
@@ -240,72 +240,107 @@ pub fn dashboard() -> Html {
.iter()
.any(|t| t.status == "Pending" || t.status == "Running");
// Pre-compute scheduled task rows
let scheduled_rows = {
let mut rows = Vec::new();
if let Some(ref sched) = s.scheduled {
if let Some(ref next) = sched.next_pipeline {
let on_skip = {
let message = message.clone();
let error = error.clone();
let fetch = fetch_status.clone();
Callback::from(move |_: MouseEvent| {
let message = message.clone();
let error = error.clone();
let fetch = fetch.clone();
wasm_bindgen_futures::spawn_local(async move {
match api::skip_scheduled_pipeline().await {
Ok(_) => {
message.set(Some("Next pipeline run skipped".into()));
fetch.emit(());
}
Err(e) => error.set(Some(e.0)),
}
});
})
};
rows.push(html! {
<tr>
<td>{ "Auto Pipeline" }</td>
<td><span class="badge badge-pending">{ "Scheduled" }</span></td>
<td class="text-sm text-muted">{ format!("Next run: {}", format_next_run(next)) }</td>
<td><button class="btn btn-sm btn-danger" onclick={on_skip}>{ "Skip" }</button></td>
</tr>
});
}
if let Some(ref next) = sched.next_monitor {
let on_skip = {
let message = message.clone();
let error = error.clone();
let fetch = fetch_status.clone();
Callback::from(move |_: MouseEvent| {
let message = message.clone();
let error = error.clone();
let fetch = fetch.clone();
wasm_bindgen_futures::spawn_local(async move {
match api::skip_scheduled_monitor().await {
Ok(_) => {
message.set(Some("Next monitor check skipped".into()));
fetch.emit(());
}
Err(e) => error.set(Some(e.0)),
}
});
})
};
rows.push(html! {
<tr>
<td>{ "Monitor Check" }</td>
<td><span class="badge badge-pending">{ "Scheduled" }</span></td>
<td class="text-sm text-muted">{ format!("Next run: {}", format_next_run(next)) }</td>
<td><button class="btn btn-sm btn-danger" onclick={on_skip}>{ "Skip" }</button></td>
</tr>
});
}
}
rows
// Skip callbacks for scheduler
let on_skip_pipeline = {
let message = message.clone();
let error = error.clone();
let fetch = fetch_status.clone();
Callback::from(move |_: MouseEvent| {
let message = message.clone();
let error = error.clone();
let fetch = fetch.clone();
wasm_bindgen_futures::spawn_local(async move {
match api::skip_scheduled_pipeline().await {
Ok(_) => {
message.set(Some("Next pipeline run skipped".into()));
fetch.emit(());
}
Err(e) => error.set(Some(e.0)),
}
});
})
};
let on_skip_monitor = {
let message = message.clone();
let error = error.clone();
let fetch = fetch_status.clone();
Callback::from(move |_: MouseEvent| {
let message = message.clone();
let error = error.clone();
let fetch = fetch.clone();
wasm_bindgen_futures::spawn_local(async move {
match api::skip_scheduled_monitor().await {
Ok(_) => {
message.set(Some("Next monitor check skipped".into()));
fetch.emit(());
}
Err(e) => error.set(Some(e.0)),
}
});
})
};
let scheduled_jobs_html = {
let next_pipeline = s.scheduled.as_ref().and_then(|sc| sc.next_pipeline.as_ref());
let next_monitor = s.scheduled.as_ref().and_then(|sc| sc.next_monitor.as_ref());
let pipeline_next_str = next_pipeline.map(|n| format_next_run(n)).unwrap_or_default();
let monitor_next_str = next_monitor.map(|n| format_next_run(n)).unwrap_or_default();
let pipeline_last = s.scheduler.as_ref()
.and_then(|sc| sc.get("pipeline"))
.and_then(|j| j.get("last_result"))
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string();
let monitor_last = s.scheduler.as_ref()
.and_then(|sc| sc.get("monitor"))
.and_then(|j| j.get("last_result"))
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string();
html! {
<div class="card">
<h3>{ "Scheduled Jobs" }</h3>
<table>
<thead>
<tr><th>{ "Job" }</th><th>{ "Status" }</th><th>{ "Next Run" }</th><th>{ "Last Result" }</th><th></th></tr>
</thead>
<tbody>
<tr>
<td>{ "Auto Pipeline" }</td>
<td>{ if next_pipeline.is_some() {
html! { <span class="badge badge-pending">{ "Scheduled" }</span> }
} else {
html! { <span class="text-muted text-sm">{ "Idle" }</span> }
}}</td>
<td class="text-sm text-muted">{ pipeline_next_str }</td>
<td class="text-sm text-muted">{ pipeline_last }</td>
<td>{ if next_pipeline.is_some() {
html! { <button class="btn btn-sm btn-danger" onclick={on_skip_pipeline}>{ "Skip" }</button> }
} else {
html! {}
}}</td>
</tr>
<tr>
<td>{ "Monitor Check" }</td>
<td>{ if next_monitor.is_some() {
html! { <span class="badge badge-pending">{ "Scheduled" }</span> }
} else {
html! { <span class="text-muted text-sm">{ "Idle" }</span> }
}}</td>
<td class="text-sm text-muted">{ monitor_next_str }</td>
<td class="text-sm text-muted">{ monitor_last }</td>
<td>{ if next_monitor.is_some() {
html! { <button class="btn btn-sm btn-danger" onclick={on_skip_monitor}>{ "Skip" }</button> }
} else {
html! {}
}}</td>
</tr>
</tbody>
</table>
</div>
}
};
let has_scheduled = !scheduled_rows.is_empty();
html! {
<div>
@@ -394,8 +429,11 @@ pub fn dashboard() -> Html {
}
}
// Background Tasks (always show if there are tasks or scheduled items)
if !s.tasks.is_empty() || has_scheduled {
// Scheduled Jobs (always visible)
{ scheduled_jobs_html }
// Background Tasks (one-off tasks like MB import)
if !s.tasks.is_empty() {
<div class="card">
<h3>{ "Background Tasks" }</h3>
<table class="tasks-table">
@@ -403,7 +441,6 @@ pub fn dashboard() -> Html {
<tr><th>{ "Type" }</th><th>{ "Status" }</th><th>{ "Progress" }</th><th>{ "Result" }</th></tr>
</thead>
<tbody>
{ for scheduled_rows.into_iter() }
{ for s.tasks.iter().map(|t| {
let progress_html = if let Some(ref p) = t.progress {
if p.total > 0 {