feat: Added Head/Tail segmented toggle to EventLog with order param wir…
- "frontend/src/api/public-client.ts" - "frontend/src/pages/AdminPipeline.tsx" - "frontend/src/App.css" GSD-Task: S02/T02
This commit is contained in:
parent
cd9dd6d8f9
commit
d00639a2ea
4 changed files with 58 additions and 4 deletions
|
|
@ -2722,6 +2722,40 @@ body {
|
|||
font-weight: 500;
|
||||
}
|
||||
|
||||
.pipeline-events__view-toggle {
|
||||
display: inline-flex;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pipeline-events__view-btn {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
padding: 0.25rem 0.625rem;
|
||||
cursor: pointer;
|
||||
font-family: inherit;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
|
||||
.pipeline-events__view-btn:hover {
|
||||
color: var(--color-text-primary);
|
||||
background: var(--color-accent-subtle);
|
||||
}
|
||||
|
||||
.pipeline-events__view-btn--active {
|
||||
background: var(--color-accent);
|
||||
color: var(--color-bg-page);
|
||||
}
|
||||
|
||||
.pipeline-events__view-btn--active:hover {
|
||||
background: var(--color-accent-hover);
|
||||
color: var(--color-bg-page);
|
||||
}
|
||||
|
||||
.pipeline-events__empty {
|
||||
font-size: 0.85rem;
|
||||
color: var(--color-text-muted);
|
||||
|
|
|
|||
|
|
@ -439,13 +439,14 @@ export async function fetchPipelineVideos(): Promise<PipelineVideoListResponse>
|
|||
|
||||
export async function fetchPipelineEvents(
|
||||
videoId: string,
|
||||
params: { offset?: number; limit?: number; stage?: string; event_type?: string } = {},
|
||||
params: { offset?: number; limit?: number; stage?: string; event_type?: string; order?: "asc" | "desc" } = {},
|
||||
): Promise<PipelineEventListResponse> {
|
||||
const qs = new URLSearchParams();
|
||||
if (params.offset !== undefined) qs.set("offset", String(params.offset));
|
||||
if (params.limit !== undefined) qs.set("limit", String(params.limit));
|
||||
if (params.stage) qs.set("stage", params.stage);
|
||||
if (params.event_type) qs.set("event_type", params.event_type);
|
||||
if (params.order) qs.set("order", params.order);
|
||||
const query = qs.toString();
|
||||
return request<PipelineEventListResponse>(
|
||||
`${BASE}/admin/pipeline/events/${videoId}${query ? `?${query}` : ""}`,
|
||||
|
|
|
|||
|
|
@ -103,13 +103,18 @@ function EventLog({ videoId }: { videoId: string }) {
|
|||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [offset, setOffset] = useState(0);
|
||||
const [viewMode, setViewMode] = useState<"head" | "tail">("tail");
|
||||
const limit = 50;
|
||||
|
||||
const load = useCallback(async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const res = await fetchPipelineEvents(videoId, { offset, limit });
|
||||
const res = await fetchPipelineEvents(videoId, {
|
||||
offset,
|
||||
limit,
|
||||
order: viewMode === "head" ? "asc" : "desc",
|
||||
});
|
||||
setEvents(res.items);
|
||||
setTotal(res.total);
|
||||
} catch (err) {
|
||||
|
|
@ -117,7 +122,7 @@ function EventLog({ videoId }: { videoId: string }) {
|
|||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [videoId, offset]);
|
||||
}, [videoId, offset, viewMode]);
|
||||
|
||||
useEffect(() => {
|
||||
void load();
|
||||
|
|
@ -134,6 +139,20 @@ function EventLog({ videoId }: { videoId: string }) {
|
|||
<div className="pipeline-events">
|
||||
<div className="pipeline-events__header">
|
||||
<span className="pipeline-events__count">{total} event{total !== 1 ? "s" : ""}</span>
|
||||
<div className="pipeline-events__view-toggle">
|
||||
<button
|
||||
className={`pipeline-events__view-btn${viewMode === "head" ? " pipeline-events__view-btn--active" : ""}`}
|
||||
onClick={() => { setViewMode("head"); setOffset(0); }}
|
||||
>
|
||||
Head
|
||||
</button>
|
||||
<button
|
||||
className={`pipeline-events__view-btn${viewMode === "tail" ? " pipeline-events__view-btn--active" : ""}`}
|
||||
onClick={() => { setViewMode("tail"); setOffset(0); }}
|
||||
>
|
||||
Tail
|
||||
</button>
|
||||
</div>
|
||||
<button className="btn btn--small btn--secondary" onClick={() => void load()}>↻ Refresh</button>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/api/client.ts","./src/api/public-client.ts","./src/components/ModeToggle.tsx","./src/components/ReportIssueModal.tsx","./src/components/StatusBadge.tsx","./src/pages/AdminPipeline.tsx","./src/pages/AdminReports.tsx","./src/pages/CreatorDetail.tsx","./src/pages/CreatorsBrowse.tsx","./src/pages/Home.tsx","./src/pages/MomentDetail.tsx","./src/pages/ReviewQueue.tsx","./src/pages/SearchResults.tsx","./src/pages/TechniquePage.tsx","./src/pages/TopicsBrowse.tsx"],"version":"5.6.3"}
|
||||
{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/api/client.ts","./src/api/public-client.ts","./src/components/AdminDropdown.tsx","./src/components/ModeToggle.tsx","./src/components/ReportIssueModal.tsx","./src/components/StatusBadge.tsx","./src/pages/AdminPipeline.tsx","./src/pages/AdminReports.tsx","./src/pages/CreatorDetail.tsx","./src/pages/CreatorsBrowse.tsx","./src/pages/Home.tsx","./src/pages/MomentDetail.tsx","./src/pages/ReviewQueue.tsx","./src/pages/SearchResults.tsx","./src/pages/TechniquePage.tsx","./src/pages/TopicsBrowse.tsx"],"version":"5.6.3"}
|
||||
Loading…
Add table
Reference in a new issue