diff --git a/webui/src/routes/import/-ui/import-page.module.css b/webui/src/routes/import/-ui/import-page.module.css
index db15a907..209d6d52 100644
--- a/webui/src/routes/import/-ui/import-page.module.css
+++ b/webui/src/routes/import/-ui/import-page.module.css
@@ -63,6 +63,11 @@
color: #fff;
}
+.importPageRefreshBtnRefreshing {
+ opacity: 0.72;
+ cursor: progress;
+}
+
.importPageStagingBar {
display: flex;
align-items: center;
@@ -88,6 +93,11 @@
white-space: nowrap;
}
+.importStagingRefreshAt {
+ white-space: nowrap;
+ color: rgba(255, 255, 255, 0.4);
+}
+
/* Tab Bar */
.importPageTabBar {
display: flex;
diff --git a/webui/src/routes/import/-ui/import-page.tsx b/webui/src/routes/import/-ui/import-page.tsx
index b92bb8a8..9180903e 100644
--- a/webui/src/routes/import/-ui/import-page.tsx
+++ b/webui/src/routes/import/-ui/import-page.tsx
@@ -1,9 +1,9 @@
import { Link, Outlet } from '@tanstack/react-router';
+import { Show } from '@/components/primitives';
import { useReactPageShell } from '@/platform/shell/route-controllers';
import type { ImportQueueEntry } from '../-import.types';
-import styles from './import-page.module.css';
import {
getQueueProgressPercent,
@@ -11,12 +11,16 @@ import {
getStagingStatsText,
} from '../-import.helpers';
import { useImportQueueWorkflow } from '../-import.store';
+import styles from './import-page.module.css';
import { fallbackImage, RefreshIcon, useImportStaging } from './import-shared';
export function ImportPage() {
useReactPageShell('import');
const { refreshStaging, stagingFiles, stagingPath, stagingQuery } = useImportStaging();
+ const isRefreshing = stagingQuery.isRefetching;
+ const lastRefreshedAt =
+ stagingQuery.dataUpdatedAt > 0 ? formatShortTime(stagingQuery.dataUpdatedAt) : null;
return (
@@ -26,6 +30,8 @@ export function ImportPage() {
fileCountText={getStagingStatsText(stagingFiles)}
loading={stagingQuery.isLoading}
stagingPath={stagingPath}
+ refreshing={isRefreshing}
+ lastRefreshedAt={lastRefreshedAt}
onRefresh={refreshStaging}
/>
@@ -38,17 +44,29 @@ export function ImportPage() {
);
}
+function formatShortTime(timestamp: number) {
+ return new Date(timestamp).toLocaleTimeString([], {
+ hour: '2-digit',
+ minute: '2-digit',
+ second: '2-digit',
+ });
+}
+
function ImportHeader({
error,
fileCountText,
loading,
stagingPath,
+ refreshing,
+ lastRefreshedAt,
onRefresh,
}: {
error: unknown;
fileCountText: string;
loading: boolean;
stagingPath: string;
+ refreshing: boolean;
+ lastRefreshedAt: string | null;
onRefresh: () => void;
}) {
return (
@@ -60,18 +78,27 @@ function ImportHeader({
{error ? 'Import folder: error' : `Import: ${stagingPath}`}
+
+
+ {lastRefreshedAt ? `Last refreshed: ${lastRefreshedAt}` : null}
+
+
{loading ? 'loading...' : fileCountText}
@@ -129,9 +156,7 @@ function ImportQueueItem({ entry }: { entry: ImportQueueEntry }) {
onError={fallbackImage}
/>
) : (
-
- A
-
+
A
)}
{entry.label}
diff --git a/webui/src/routes/import/-ui/import-shared.tsx b/webui/src/routes/import/-ui/import-shared.tsx
index b025f2a4..dfa5bdda 100644
--- a/webui/src/routes/import/-ui/import-shared.tsx
+++ b/webui/src/routes/import/-ui/import-shared.tsx
@@ -19,9 +19,9 @@ export function useImportStaging() {
});
return {
- refreshStaging: () => {
+ refreshStaging: async () => {
clearFinishedJobs();
- void invalidateImportStagingQueries(queryClient);
+ await invalidateImportStagingQueries(queryClient);
},
stagingFiles: stagingQuery.data?.files ?? [],
stagingPath: stagingQuery.data?.staging_path || 'Not configured',