Fix UI bug with SkipReason count
This commit is contained in:
parent
a6d491d3c2
commit
f5056130e5
4 changed files with 27 additions and 10 deletions
|
|
@ -13,7 +13,7 @@ tokio = { version = "1", features = ["full"] }
|
|||
# Web framework
|
||||
axum = { version = "0.8", features = ["ws"] }
|
||||
tower = "0.5"
|
||||
tower-http = { version = "0.6", features = ["fs", "cors"] }
|
||||
tower-http = { version = "0.6", features = ["fs", "cors", "set-header"] }
|
||||
|
||||
# HTTP client
|
||||
reqwest = { version = "0.12", features = ["json", "stream"] }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@
|
|||
import ResultsView from './lib/components/ResultsView.svelte';
|
||||
import SettingsPanel from './lib/components/SettingsPanel.svelte';
|
||||
|
||||
// LocalStorage keys
|
||||
// Configuration constants
|
||||
const POLL_INTERVAL_MS = 500; // Progress polling interval during job execution
|
||||
const STORAGE_KEY_PERSON = 'immich-timelapse-selected-person';
|
||||
|
||||
// Load persisted state from localStorage
|
||||
|
|
@ -182,7 +183,7 @@
|
|||
|
||||
function startPolling() {
|
||||
if (pollInterval) return; // Already polling
|
||||
pollInterval = setInterval(pollProgress, 500);
|
||||
pollInterval = setInterval(pollProgress, POLL_INTERVAL_MS);
|
||||
}
|
||||
|
||||
function stopPolling() {
|
||||
|
|
|
|||
|
|
@ -41,19 +41,24 @@
|
|||
// Skip statistics from the backend - dynamically handle any keys
|
||||
let skipStats = $derived(progress.skip_stats || {});
|
||||
|
||||
// Calculate total from all numeric values in skip_stats
|
||||
// Use the backend-provided total if available, otherwise calculate from individual counts
|
||||
// Note: We exclude 'total' from manual calculation to avoid double-counting
|
||||
let skipTotal = $derived(
|
||||
Object.values(skipStats).reduce((sum, val) => sum + (typeof val === 'number' ? val : 0), 0)
|
||||
typeof skipStats.total === 'number'
|
||||
? skipStats.total
|
||||
: Object.entries(skipStats)
|
||||
.filter(([key, _]) => key !== 'total')
|
||||
.reduce((sum, [_, val]) => sum + (typeof val === 'number' ? val : 0), 0)
|
||||
);
|
||||
|
||||
// Calculate kept (successful) count: completed - skipped
|
||||
let keptCount = $derived(Math.max(0, progress.completed - skipTotal));
|
||||
|
||||
// Dynamically build skip reasons from whatever the backend sends
|
||||
// Filter to only show non-zero counts
|
||||
// Filter to only show non-zero counts, exclude the 'total' field
|
||||
let skipReasons = $derived(
|
||||
Object.entries(skipStats)
|
||||
.filter(([_, count]) => typeof count === 'number' && count > 0)
|
||||
.filter(([key, count]) => key !== 'total' && typeof count === 'number' && count > 0)
|
||||
.map(([key, count]) => ({ label: formatLabel(key), count }))
|
||||
.sort((a, b) => b.count - a.count) // Sort by count descending
|
||||
);
|
||||
|
|
@ -98,7 +103,7 @@
|
|||
{#if (jobStatus === 'running' || jobStatus === 'completed' || jobStatus === 'cancelled') && progress.completed > 0}
|
||||
<div class="skip-stats">
|
||||
<div class="skip-header">
|
||||
<span class="skip-label">Discarded:Kept</span>
|
||||
<span class="skip-label">Discarded : Kept</span>
|
||||
<span class="skip-totals">
|
||||
<span class="skipped-count">{skipTotal}</span>
|
||||
<span class="separator">:</span>
|
||||
|
|
|
|||
|
|
@ -15,12 +15,15 @@ mod processing;
|
|||
|
||||
use crate::web::state::AppState;
|
||||
use axum::{
|
||||
http::header,
|
||||
response::{Html, IntoResponse},
|
||||
routing::{delete, get, post, put},
|
||||
Router,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use tower::ServiceBuilder;
|
||||
use tower_http::services::ServeDir;
|
||||
use tower_http::set_header::SetResponseHeaderLayer;
|
||||
|
||||
// Re-export handler functions for use in router
|
||||
use config::{get_config, update_config};
|
||||
|
|
@ -89,8 +92,16 @@ pub fn create_router(state: AppState) -> Router {
|
|||
)
|
||||
.route("/api/config", get(get_config))
|
||||
.route("/api/config", put(update_config))
|
||||
// Serve output files (video, images)
|
||||
.nest_service("/output", ServeDir::new(output_dir))
|
||||
// Serve output files (video, images) with cache headers
|
||||
.nest_service(
|
||||
"/output",
|
||||
ServiceBuilder::new()
|
||||
.layer(SetResponseHeaderLayer::if_not_present(
|
||||
header::CACHE_CONTROL,
|
||||
header::HeaderValue::from_static("public, max-age=86400"),
|
||||
))
|
||||
.service(ServeDir::new(output_dir)),
|
||||
)
|
||||
// Serve frontend static files (fallback to index.html for SPA routing)
|
||||
.fallback_service(ServeDir::new("frontend/dist").fallback(get(serve_index)))
|
||||
.with_state(state)
|
||||
|
|
|
|||
Loading…
Reference in a new issue