fixes
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
window.__EVANESCERE_FRONTEND_CONFIG__ = {
|
||||
apiBaseUrl: "http://localhost:8000"
|
||||
apiBaseUrl: "http://192.168.1.44:8080"
|
||||
};
|
||||
|
||||
+34
-5
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
Check,
|
||||
Clapperboard,
|
||||
FolderSync,
|
||||
Play,
|
||||
RefreshCw,
|
||||
Save,
|
||||
@@ -19,6 +20,7 @@ import {
|
||||
patchSettings,
|
||||
renderClip,
|
||||
runVideo,
|
||||
scanWebDav,
|
||||
uploadClip,
|
||||
} from "./api";
|
||||
import type { ClipSuggestion, PipelineSettings, TranscriptSegment, Video } from "./types";
|
||||
@@ -47,7 +49,7 @@ function formatTimeRange(start: number, end: number) {
|
||||
}
|
||||
|
||||
function statusTone(value: string) {
|
||||
if (["done", "stable", "approved", "auto_approved"].includes(value)) return "good";
|
||||
if (["done", "stable", "existing_done", "approved", "auto_approved"].includes(value)) return "good";
|
||||
if (["failed", "error"].includes(value)) return "bad";
|
||||
if (["running", "queued", "observing", "pending"].includes(value)) return "busy";
|
||||
return "neutral";
|
||||
@@ -61,6 +63,7 @@ export function App() {
|
||||
const [clips, setClips] = useState<ClipSuggestion[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [notice, setNotice] = useState<string | null>(null);
|
||||
|
||||
const selectedVideo = useMemo(
|
||||
() => videos.find((video) => video.id === selectedVideoId) ?? null,
|
||||
@@ -124,6 +127,26 @@ export function App() {
|
||||
}
|
||||
}
|
||||
|
||||
async function syncWebDav() {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
setNotice(null);
|
||||
try {
|
||||
const result = await scanWebDav();
|
||||
if (result.baseline_initialized) {
|
||||
setNotice(
|
||||
`Imported ${result.baseline_inserted + result.baseline_marked_existing} existing files as manual-only baseline entries.`,
|
||||
);
|
||||
} else {
|
||||
setNotice(`Observed ${result.observed} files; ${result.newly_stable} newly stable.`);
|
||||
}
|
||||
await refresh();
|
||||
} catch (caught) {
|
||||
setError(caught instanceof Error ? caught.message : "Unknown error");
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function saveSettings() {
|
||||
if (!settings) return;
|
||||
await withRefresh(() => patchSettings(settings));
|
||||
@@ -149,6 +172,7 @@ export function App() {
|
||||
</header>
|
||||
|
||||
{error && <div className="error-strip">{error}</div>}
|
||||
{notice && <div className="notice-strip">{notice}</div>}
|
||||
|
||||
<section className="band controls-band">
|
||||
<div className="section-title">
|
||||
@@ -176,9 +200,15 @@ export function App() {
|
||||
|
||||
<section className="workbench">
|
||||
<aside className="video-list">
|
||||
<div className="section-title">
|
||||
<Clapperboard size={18} />
|
||||
<h2>Videos</h2>
|
||||
<div className="list-header">
|
||||
<div className="section-title">
|
||||
<Clapperboard size={18} />
|
||||
<h2>Videos</h2>
|
||||
</div>
|
||||
<button type="button" className="icon-button" onClick={() => void syncWebDav()} disabled={loading}>
|
||||
<FolderSync size={16} />
|
||||
Sync WebDAV
|
||||
</button>
|
||||
</div>
|
||||
<div className="table-scroll">
|
||||
<table>
|
||||
@@ -301,4 +331,3 @@ function Metric({ label, value }: { label: string; value: string }) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+13
-2
@@ -1,8 +1,15 @@
|
||||
import type { Artifact, ClipSuggestion, PipelineSettings, TranscriptSegment, Video } from "./types";
|
||||
import type {
|
||||
Artifact,
|
||||
ClipSuggestion,
|
||||
PipelineSettings,
|
||||
TranscriptSegment,
|
||||
Video,
|
||||
WebDavScanResult,
|
||||
} from "./types";
|
||||
|
||||
const runtimeApiBase = window.__EVANESCERE_FRONTEND_CONFIG__?.apiBaseUrl;
|
||||
|
||||
export const apiBaseUrl = (runtimeApiBase || "http://localhost:8000").replace(
|
||||
export const apiBaseUrl = (runtimeApiBase || "http://localhost:8080").replace(
|
||||
/\/$/,
|
||||
"",
|
||||
);
|
||||
@@ -37,6 +44,10 @@ export function getVideos(): Promise<Video[]> {
|
||||
return request<Video[]>("/videos");
|
||||
}
|
||||
|
||||
export function scanWebDav(): Promise<WebDavScanResult> {
|
||||
return request<WebDavScanResult>("/webdav/scan", { method: "POST" });
|
||||
}
|
||||
|
||||
export function runVideo(videoId: number) {
|
||||
return request(`/videos/${videoId}/run`, { method: "POST" });
|
||||
}
|
||||
|
||||
+17
-1
@@ -120,6 +120,16 @@ button {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.notice-strip {
|
||||
margin-bottom: 14px;
|
||||
border-left: 4px solid #21756b;
|
||||
background: #e9f3f1;
|
||||
color: #155c54;
|
||||
padding: 10px 12px;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.band {
|
||||
border-top: 1px solid #d8dee6;
|
||||
padding: 16px 0;
|
||||
@@ -190,6 +200,13 @@ button {
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.list-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.table-scroll {
|
||||
margin-top: 12px;
|
||||
overflow: auto;
|
||||
@@ -431,4 +448,3 @@ tr.selected td {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,3 +59,11 @@ export interface Artifact {
|
||||
artifact_metadata: Record<string, unknown>;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface WebDavScanResult {
|
||||
observed: number;
|
||||
newly_stable: number;
|
||||
baseline_initialized: boolean;
|
||||
baseline_inserted: number;
|
||||
baseline_marked_existing: number;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user