feat(panel): drive active game from deployed fleet instances
The shell skin / sidebar nav / dashboard terminology now follow the games actually deployed (game_instances.game, agent-reported) instead of a localStorage-only toggle. syncActiveGameFromFleet() derives: one game -> auto-skin to it; zero/multiple -> 'all' neutral. A manual GameSwitcher pick persists and overrides the heuristic. Wired into DashboardLayout via a watch on the fleet store. No schema change: a license's games are the distinct games of its instances (the normalized source of truth) — deliberately not duplicating into a licenses.game column that would drift (Lesson 20). Build-green (vue-tsc) + boots clean in-browser (0 console errors, theming initializes). Authenticated auto-derive confirms live on next instance deploy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,11 +6,12 @@
|
||||
* Preserves: permission gating, super-admin section, logout, mobile sidebar,
|
||||
* GameSwitcher, agent-health footer, topbar.
|
||||
*/
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref, computed, watch, onMounted } from 'vue'
|
||||
import { RouterView, useRoute, useRouter } from 'vue-router'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { useServerStore } from '@/stores/server'
|
||||
import { useThemeGame } from '@/composables/useThemeGame'
|
||||
import { useFleetStore } from '@/stores/fleet'
|
||||
import { useThemeGame, syncActiveGameFromFleet } from '@/composables/useThemeGame'
|
||||
import { useGameProfile } from '@/config/gameProfiles'
|
||||
import type { NavSection, NavItemDef } from '@/config/gameProfiles'
|
||||
import { safeDate } from '@/utils/formatters'
|
||||
@@ -31,8 +32,18 @@ const route = useRoute()
|
||||
const router = useRouter()
|
||||
const auth = useAuthStore()
|
||||
const server = useServerStore()
|
||||
const fleet = useFleetStore()
|
||||
const { theme, activeGame, setActiveGame, toggleTheme } = useThemeGame()
|
||||
|
||||
// ---- Active game follows the deployed fleet (instances are the source of
|
||||
// truth for which game a license runs). A manual GameSwitcher pick overrides
|
||||
// this; see syncActiveGameFromFleet. ----
|
||||
const deployedGames = computed(() =>
|
||||
fleet.hosts.flatMap((h) => h.instances.map((i) => i.game)),
|
||||
)
|
||||
watch(deployedGames, (games) => syncActiveGameFromFleet(games), { immediate: true })
|
||||
onMounted(() => { if (!fleet.hosts.length) void fleet.fetchFleet() })
|
||||
|
||||
// ---- Mobile sidebar ----
|
||||
const sidebarOpen = ref(false)
|
||||
function closeSidebar() { sidebarOpen.value = false }
|
||||
|
||||
Reference in New Issue
Block a user