Fix: Hide kiosk links for plugins that aren't installed

The sidebar was showing USB Kiosk and Parts Kiosk links even when those
plugins were not installed, because isPluginEnabled() fails open (returns
true before the plugin list loads).

Changes:
- Load enabled plugins list during AppLayout mount
- Make kiosk visibility reactive with computed properties
- Check pluginsLoaded flag before showing kiosk links
- showUsbKiosk and showPartsKiosk now wait for real plugin state

Before: isPluginEnabled('usb') returns true immediately (enabledSet null)
After: Waits for plugin list, correctly returns false when not installed

Behavior:
- USB Kiosk: Hidden if usb plugin not installed/enabled
- Parts Kiosk: Hidden if printedparts plugin not installed/enabled
- Shopfloor Dashboard: Still shows (core feature)
- TV Slideshow: Still shows if slides plugin exists

User reported: USB Kiosk showing when USB plugin not installed
Fixed: Kiosk links now correctly gate on plugin installation status

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Proudlock
2026-09-07 03:06:07 -04:00
parent 2ce4fa4e5c
commit 6d8c03bf6a

View File

@@ -127,7 +127,7 @@ import { dashboardApi, notificationsApi } from '../api'
import { fiscalWeek } from '@/utils/fiscalWeek'
import { getFacilityName, getSiteLogo, getServicenowUrls, getEnvLabel } from '../utils/siteSettings'
import { withBase } from '../utils/basePath'
import { isPluginEnabled } from '../composables/enabledPlugins'
import { isPluginEnabled, loadEnabledPlugins } from '../composables/enabledPlugins'
const router = useRouter()
const route = useRoute()
@@ -147,15 +147,28 @@ const authStore = useAuthStore()
// the plugin list, so it cannot carry the test on its own.
const stagedRoutePaths = new Set(router.getRoutes().map(r => r.path))
const hasRoute = (path) => stagedRoutePaths.has(path)
// Make kiosk visibility reactive - updates when plugin list loads
const pluginsLoaded = ref(false)
// Shopfloor Dashboard is a core view but runs entirely on the notifications
// plugin (notificationsApi.getShopfloor + the calendar); without it the display
// is empty, so gate the link on the notifications plugin being in this build.
const showShopfloor = hasRoute('/shopfloor')
&& (hasRoute('/notifications') || hasRoute('/calendar'))
const showPartsKiosk = hasRoute('/parts-kiosk') && isPluginEnabled('printedparts')
const showUsbKiosk = hasRoute('/usb-kiosk') && isPluginEnabled('usb')
const showDisplays = showShopfloor || hasRoute('/tv') || showPartsKiosk
|| showUsbKiosk
const showShopfloor = computed(() =>
hasRoute('/shopfloor') && (hasRoute('/notifications') || hasRoute('/calendar'))
)
const showPartsKiosk = computed(() =>
pluginsLoaded.value && hasRoute('/parts-kiosk') && isPluginEnabled('printedparts')
)
const showUsbKiosk = computed(() =>
pluginsLoaded.value && hasRoute('/usb-kiosk') && isPluginEnabled('usb')
)
const showDisplays = computed(() =>
showShopfloor.value || hasRoute('/tv') || showPartsKiosk.value || showUsbKiosk.value
)
const routeViewKey = computed(() =>
route.path.startsWith('/settings') ? '/settings' : route.path
)
@@ -294,6 +307,10 @@ onMounted(async () => {
// granted mid-session stays invisible until the person logs out and back in.
if (authStore.isAuthenticated) authStore.fetchUser()
// Load enabled plugins list early so kiosk links render correctly
await loadEnabledPlugins()
pluginsLoaded.value = true
// Half-hourly: cheap, and it crosses midnight into the new week without a
// reload on a screen nobody touches.
fiscalWeekTimer = setInterval(() => { currentFiscalWeek.value = fiscalWeek() }, 30 * 60 * 1000)