P3-C: badges de session live sur le dashboard (résolus depuis le store sessions)

Les badges busy/waiting/idle des sessions affichées dans les cartes worktree
sont désormais résolus depuis le store des sessions (mis à jour en temps réel),
au lieu de l'instantané embarqué dans le worktree — pour que « quelle session
attend une réponse » reste live sans attendre un worktree_update.
This commit is contained in:
2026-06-12 18:48:07 +02:00
parent fae288f511
commit d7eb9c1b3a
2 changed files with 13 additions and 4 deletions

View File

@@ -21,7 +21,7 @@
:to="{ name: 'session', params: { id: s.id } }" :to="{ name: 'session', params: { id: s.id } }"
class="flex items-center gap-1 rounded bg-zinc-800/60 px-1.5 py-0.5 transition-colors hover:bg-zinc-800" class="flex items-center gap-1 rounded bg-zinc-800/60 px-1.5 py-0.5 transition-colors hover:bg-zinc-800"
> >
<SessionStateBadge :session="s" /> <SessionStateBadge :session="liveSession(s)" />
<span class="font-mono text-[11px] text-zinc-400">{{ s.command }}</span> <span class="font-mono text-[11px] text-zinc-400">{{ s.command }}</span>
</RouterLink> </RouterLink>
<span v-if="worktree.sessions.length === 0" class="text-xs text-zinc-600">{{ t('worktrees.noSession') }}</span> <span v-if="worktree.sessions.length === 0" class="text-xs text-zinc-600">{{ t('worktrees.noSession') }}</span>
@@ -43,14 +43,22 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import type { WorktreeSummary } from '@arboretum/shared'; import type { SessionSummary, WorktreeSummary } from '@arboretum/shared';
import { useWorktreesStore } from '../stores/worktrees'; import { useWorktreesStore } from '../stores/worktrees';
import { useSessionsStore } from '../stores/sessions';
import { ApiError } from '../lib/api'; import { ApiError } from '../lib/api';
import SessionStateBadge from './SessionStateBadge.vue'; import SessionStateBadge from './SessionStateBadge.vue';
const props = defineProps<{ worktree: WorktreeSummary }>(); const props = defineProps<{ worktree: WorktreeSummary }>();
const { t } = useI18n(); const { t } = useI18n();
const store = useWorktreesStore(); const store = useWorktreesStore();
const sessions = useSessionsStore();
// L'état embarqué dans le worktree est un instantané ; on privilégie la version live du store
// des sessions (mise à jour en continu) pour que busy/waiting/idle reste temps réel.
function liveSession(s: SessionSummary): SessionSummary {
return sessions.sessions.find((x) => x.id === s.id) ?? s;
}
const confirming = ref(false); const confirming = ref(false);
const forceNeeded = ref(false); const forceNeeded = ref(false);

View File

@@ -55,8 +55,9 @@ const addError = ref<string | null>(null);
onMounted(() => { onMounted(() => {
void store.fetchAll(); void store.fetchAll();
store.startRealtime(); store.startRealtime();
// les sessions alimentent la corrélation worktree↔session (cwd) côté serveur ; on suit aussi // les sessions alimentent la corrélation worktree↔session (cwd) côté serveur ; on charge et on
// leurs mises à jour temps réel pour que les badges d'état se rafraîchissent. // suit leurs mises à jour temps réel pour que les badges d'état (busy/waiting/idle) restent live.
void sessions.fetchSessions();
sessions.startRealtime(); sessions.startRealtime();
}); });