Backend: - Expose end_session_endpoint from OIDC provider metadata in /auth/oidc/config - Add getEndSessionEndpoint() to OidcTokenExchanger Frontend: - On OIDC logout, redirect to provider's end_session_endpoint to clear SSO session - Strip /api/v1 prefix from OpenAPI paths to match client baseUrl convention - Add schema-types.ts with convenience type re-exports from generated schema - Fix all type imports to use schema-types instead of raw generated schema - Fix optional field access (processors, children, duration) with proper typing - Fix AgentInstance.state → status field name Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
108 lines
3.2 KiB
TypeScript
108 lines
3.2 KiB
TypeScript
import { create } from 'zustand';
|
|
import type { SearchRequest } from '../../api/schema-types';
|
|
|
|
function todayMidnight(): string {
|
|
const d = new Date();
|
|
d.setHours(0, 0, 0, 0);
|
|
// Format as datetime-local value: YYYY-MM-DDTHH:mm
|
|
const pad = (n: number) => n.toString().padStart(2, '0');
|
|
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T00:00`;
|
|
}
|
|
|
|
interface ExecutionSearchState {
|
|
status: string[];
|
|
timeFrom: string;
|
|
timeTo: string;
|
|
durationMin: number | null;
|
|
durationMax: number | null;
|
|
text: string;
|
|
routeId: string;
|
|
agentId: string;
|
|
processorType: string;
|
|
live: boolean;
|
|
offset: number;
|
|
limit: number;
|
|
|
|
toggleLive: () => void;
|
|
setStatus: (statuses: string[]) => void;
|
|
toggleStatus: (s: string) => void;
|
|
setTimeFrom: (v: string) => void;
|
|
setTimeTo: (v: string) => void;
|
|
setDurationMin: (v: number | null) => void;
|
|
setDurationMax: (v: number | null) => void;
|
|
setText: (v: string) => void;
|
|
setRouteId: (v: string) => void;
|
|
setAgentId: (v: string) => void;
|
|
setProcessorType: (v: string) => void;
|
|
setOffset: (v: number) => void;
|
|
clearAll: () => void;
|
|
toSearchRequest: () => SearchRequest;
|
|
}
|
|
|
|
export const useExecutionSearch = create<ExecutionSearchState>((set, get) => ({
|
|
status: ['COMPLETED', 'FAILED'],
|
|
timeFrom: todayMidnight(),
|
|
timeTo: '',
|
|
durationMin: null,
|
|
durationMax: null,
|
|
text: '',
|
|
routeId: '',
|
|
agentId: '',
|
|
processorType: '',
|
|
live: true,
|
|
offset: 0,
|
|
limit: 25,
|
|
|
|
toggleLive: () => set((state) => ({ live: !state.live })),
|
|
setStatus: (statuses) => set({ status: statuses, offset: 0 }),
|
|
toggleStatus: (s) =>
|
|
set((state) => ({
|
|
status: state.status.includes(s)
|
|
? state.status.filter((x) => x !== s)
|
|
: [...state.status, s],
|
|
offset: 0,
|
|
})),
|
|
setTimeFrom: (v) => set({ timeFrom: v, offset: 0 }),
|
|
setTimeTo: (v) => set({ timeTo: v, offset: 0 }),
|
|
setDurationMin: (v) => set({ durationMin: v, offset: 0 }),
|
|
setDurationMax: (v) => set({ durationMax: v, offset: 0 }),
|
|
setText: (v) => set({ text: v, offset: 0 }),
|
|
setRouteId: (v) => set({ routeId: v, offset: 0 }),
|
|
setAgentId: (v) => set({ agentId: v, offset: 0 }),
|
|
setProcessorType: (v) => set({ processorType: v, offset: 0 }),
|
|
setOffset: (v) => set({ offset: v }),
|
|
clearAll: () =>
|
|
set({
|
|
status: ['COMPLETED', 'FAILED', 'RUNNING'],
|
|
timeFrom: todayMidnight(),
|
|
timeTo: '',
|
|
durationMin: null,
|
|
durationMax: null,
|
|
text: '',
|
|
routeId: '',
|
|
agentId: '',
|
|
processorType: '',
|
|
offset: 0,
|
|
}),
|
|
|
|
toSearchRequest: (): SearchRequest => {
|
|
const s = get();
|
|
const statusStr = s.status.length > 0 && s.status.length < 3
|
|
? s.status.join(',')
|
|
: undefined;
|
|
return {
|
|
status: statusStr ?? undefined,
|
|
timeFrom: s.timeFrom ? new Date(s.timeFrom).toISOString() : undefined,
|
|
timeTo: s.timeTo ? new Date(s.timeTo).toISOString() : undefined,
|
|
durationMin: s.durationMin ?? undefined,
|
|
durationMax: s.durationMax ?? undefined,
|
|
text: s.text || undefined,
|
|
routeId: s.routeId || undefined,
|
|
agentId: s.agentId || undefined,
|
|
processorType: s.processorType || undefined,
|
|
offset: s.offset,
|
|
limit: s.limit,
|
|
};
|
|
},
|
|
}));
|