Ajoute la notion de groupe — collection nommée de repos (membership légère persistée, many-to-many) — pour piloter plusieurs repos en simultané : - DB : migration #5 (tables groups + group_repos, FK ON DELETE CASCADE). - GroupManager (synchrone, EventEmitter) + routes REST /api/v1/groups ; ne persiste que la membership, worktrees/sessions filtrés par repoId côté client. - Protocole : GroupSummary, DTOs, topic WS « groups », events group_update/removed (additifs, PROTOCOL_VERSION inchangé). - Web : store groups, GroupsListView, GroupView (réutilise RepoSection), grille multi-terminaux (TerminalGrid/TerminalCell), action « feature cross-repo » (orchestration client, tolérante aux échecs partiels), routes + i18n EN/FR. - Tests : group-manager.test.ts + extension protocol.test.ts ; acceptance-p5.mjs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
29 lines
1.1 KiB
Vue
29 lines
1.1 KiB
Vue
<template>
|
|
<div class="flex flex-col gap-2">
|
|
<p v-if="sessions.length === 0" class="text-sm text-zinc-500">{{ t('groups.gridEmpty') }}</p>
|
|
<template v-else>
|
|
<p v-if="sessions.length > MAX_CELLS" class="text-xs text-amber-400">
|
|
{{ t('groups.gridCapped', { shown: MAX_CELLS, total: sessions.length }) }}
|
|
</p>
|
|
<!-- une seule socket WS multiplexe tous les terminaux ; cap dur pour préserver GPU/canaux.
|
|
Sur mobile la grille retombe à une colonne (empilement). -->
|
|
<div class="grid grid-cols-1 gap-3 lg:grid-cols-2 2xl:grid-cols-3">
|
|
<TerminalCell v-for="s in shown" :key="s.id" :session="s" class="h-80" />
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
import type { SessionSummary } from '@arboretum/shared';
|
|
import TerminalCell from './TerminalCell.vue';
|
|
|
|
const props = defineProps<{ sessions: SessionSummary[] }>();
|
|
const { t } = useI18n();
|
|
|
|
const MAX_CELLS = 6;
|
|
const shown = computed(() => props.sessions.slice(0, MAX_CELLS));
|
|
</script>
|