feat: add run deletion, session reopen, and feed merging UI
This commit is contained in:
parent
3fa5a1441a
commit
a6af6e4b98
4 changed files with 107 additions and 0 deletions
|
|
@ -88,6 +88,15 @@ export async function stopRun(sessionId: string, runId: string): Promise<Session
|
|||
return res.data
|
||||
}
|
||||
|
||||
export async function deleteRun(sessionId: string, runId: string): Promise<void> {
|
||||
await api.delete(`/sessions/${sessionId}/runs/${runId}`)
|
||||
}
|
||||
|
||||
export async function reopenSession(id: string): Promise<UseCaseSession> {
|
||||
const res = await api.post<UseCaseSession>(`/sessions/${id}/reopen`)
|
||||
return res.data
|
||||
}
|
||||
|
||||
export async function completeSession(id: string): Promise<UseCaseSession> {
|
||||
const res = await api.post<UseCaseSession>(`/sessions/${id}/complete`)
|
||||
return res.data
|
||||
|
|
|
|||
|
|
@ -119,6 +119,40 @@ export const useSessionsStore = defineStore('sessions', () => {
|
|||
}
|
||||
}
|
||||
|
||||
async function deleteRun(sessionId: string, runId: string): Promise<boolean> {
|
||||
try {
|
||||
await api.deleteRun(sessionId, runId)
|
||||
if (currentSession.value?.id === sessionId) {
|
||||
currentSession.value.runs = currentSession.value.runs.filter((r) => r.id !== runId)
|
||||
const sIdx = sessions.value.findIndex((s) => s.id === sessionId)
|
||||
if (sIdx !== -1) {
|
||||
sessions.value[sIdx] = { ...sessions.value[sIdx], runs: [...currentSession.value.runs] }
|
||||
}
|
||||
}
|
||||
return true
|
||||
} catch (e: unknown) {
|
||||
error.value = e instanceof Error ? e.message : 'Failed to delete run'
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async function reopenSession(id: string): Promise<UseCaseSession | null> {
|
||||
try {
|
||||
const session = await api.reopenSession(id)
|
||||
const idx = sessions.value.findIndex((s) => s.id === id)
|
||||
if (idx !== -1) {
|
||||
sessions.value[idx] = session
|
||||
}
|
||||
if (currentSession.value?.id === id) {
|
||||
currentSession.value = session
|
||||
}
|
||||
return session
|
||||
} catch (e: unknown) {
|
||||
error.value = e instanceof Error ? e.message : 'Failed to reopen session'
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
sessions,
|
||||
currentSession,
|
||||
|
|
@ -130,7 +164,9 @@ export const useSessionsStore = defineStore('sessions', () => {
|
|||
deleteSession,
|
||||
startRun,
|
||||
stopRun,
|
||||
deleteRun,
|
||||
completeSession,
|
||||
reopenSession,
|
||||
reAnalyze,
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ export interface CreateSessionRequest {
|
|||
export interface StartRunRequest {
|
||||
feed_name: string
|
||||
label?: string | null
|
||||
merge_feeds?: string[]
|
||||
}
|
||||
|
||||
// ── Use Cases ──
|
||||
|
|
|
|||
|
|
@ -16,12 +16,18 @@ const store = useSessionsStore()
|
|||
const showStartRun = ref(false)
|
||||
const runFeedName = ref('ksudp')
|
||||
const runLabel = ref('')
|
||||
const runMergeEnabled = ref(false)
|
||||
const runMergeFeeds = ref<string[]>([])
|
||||
|
||||
const sessionId = computed(() => props.id ?? (route.params.id as string))
|
||||
const session = computed(() => store.currentSession)
|
||||
|
||||
const feedOptions = ['ksudp', 'telemetry_tool', 'pcars']
|
||||
|
||||
const mergeFeedOptions = computed(() => {
|
||||
return feedOptions.filter((f) => f !== runFeedName.value)
|
||||
})
|
||||
|
||||
const hasActiveRun = computed(() => {
|
||||
return session.value?.runs.some((r) => r.status === 'recording') ?? false
|
||||
})
|
||||
|
|
@ -61,10 +67,13 @@ async function handleStartRun() {
|
|||
const run = await store.startRun(sessionId.value, {
|
||||
feed_name: runFeedName.value,
|
||||
label: runLabel.value || undefined,
|
||||
merge_feeds: runMergeEnabled.value && runMergeFeeds.value.length > 0 ? runMergeFeeds.value : undefined,
|
||||
})
|
||||
if (run) {
|
||||
showStartRun.value = false
|
||||
runLabel.value = ''
|
||||
runMergeEnabled.value = false
|
||||
runMergeFeeds.value = []
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,6 +111,16 @@ async function handleDelete() {
|
|||
router.push('/sessions')
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDeleteRun(runId: string, runLabel: string) {
|
||||
if (confirm(`Delete run "${runLabel || 'Untitled Run'}"?`)) {
|
||||
await store.deleteRun(sessionId.value, runId)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleReopen() {
|
||||
await store.reopenSession(sessionId.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -181,6 +200,18 @@ async function handleDelete() {
|
|||
/>
|
||||
<button class="btn btn-primary btn-sm" @click="handleStartRun">Start</button>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 mt-2">
|
||||
<label class="merge-toggle">
|
||||
<input type="checkbox" v-model="runMergeEnabled" />
|
||||
<span>Merge with additional feeds</span>
|
||||
</label>
|
||||
</div>
|
||||
<div v-if="runMergeEnabled" class="flex gap-2 items-center mt-1">
|
||||
<label v-for="f in mergeFeedOptions" :key="f" class="merge-feed-option">
|
||||
<input type="checkbox" :value="f" v-model="runMergeFeeds" />
|
||||
<span>{{ f }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="session.runs.length === 0" class="text-secondary text-muted">
|
||||
|
|
@ -208,6 +239,12 @@ async function handleDelete() {
|
|||
>
|
||||
■ Stop
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-danger btn-sm"
|
||||
@click="handleDeleteRun(run.id, run.label || '')"
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -279,6 +316,9 @@ async function handleDelete() {
|
|||
<button class="btn btn-secondary" @click="handleReAnalyze">
|
||||
🔄 Re-analyze
|
||||
</button>
|
||||
<button class="btn btn-secondary" @click="handleReopen">
|
||||
↩ Reopen Session
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -385,4 +425,25 @@ async function handleDelete() {
|
|||
flex: 1;
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.merge-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
font-size: 0.85rem;
|
||||
color: var(--color-text-secondary);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.merge-feed-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.3rem;
|
||||
font-size: 0.8rem;
|
||||
color: var(--color-text-secondary);
|
||||
padding: 0.2rem 0.5rem;
|
||||
background: var(--color-background);
|
||||
border-radius: var(--radius-sm);
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue