82 lines
2.7 KiB
Svelte
82 lines
2.7 KiB
Svelte
<script lang="ts">
|
|
import * as DropdownMenu from '$lib/components/ui/dropdown-menu/index.js';
|
|
import LayoutGridIcon from '@lucide/svelte/icons/layout-grid';
|
|
import { workspaceAppsStore, type WorkspaceApp } from '$lib/stores/workspace-apps.svelte';
|
|
|
|
// Abrir la app seleccionada:
|
|
// - Mismo origin (es esta misma app): si trae `active_system`, cambio de sistema local
|
|
// recargando la página actual con ese parámetro (sin rebotar al Workspace). Si no, ir al dashboard.
|
|
// - Otro origin: navegar a su entrada (login_url); su propio login resuelve el SSO vía Workspace
|
|
// y aterriza en la app.
|
|
function openApp(app: WorkspaceApp) {
|
|
let target: URL;
|
|
try {
|
|
target = new URL(app.url);
|
|
} catch {
|
|
window.location.assign(app.url);
|
|
return;
|
|
}
|
|
|
|
if (target.origin !== window.location.origin) {
|
|
window.location.assign(app.url);
|
|
return;
|
|
}
|
|
|
|
const system = target.searchParams.get('active_system');
|
|
if (system) {
|
|
const current = new URL(window.location.href);
|
|
current.searchParams.set('active_system', system);
|
|
window.location.assign(current.pathname + current.search);
|
|
} else {
|
|
window.location.assign('/dashboard');
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<DropdownMenu.Root>
|
|
<DropdownMenu.Trigger>
|
|
{#snippet child({ props })}
|
|
<button
|
|
{...props}
|
|
class="inline-flex size-10 shrink-0 select-none items-center justify-center rounded-md
|
|
text-sidebar-foreground/70 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground
|
|
transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring
|
|
data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
|
title="Aplicaciones"
|
|
aria-label="Abrir selector de aplicaciones"
|
|
>
|
|
<LayoutGridIcon class="size-5" />
|
|
</button>
|
|
{/snippet}
|
|
</DropdownMenu.Trigger>
|
|
|
|
<DropdownMenu.Content
|
|
class="w-64 rounded-xl p-3"
|
|
align="end"
|
|
side="bottom"
|
|
sideOffset={8}
|
|
>
|
|
<p class="mb-3 px-1 text-xs font-medium text-muted-foreground">Tus aplicaciones</p>
|
|
<div class="grid grid-cols-2 gap-2">
|
|
{#each workspaceAppsStore.apps as app (app.id)}
|
|
<button
|
|
onclick={() => openApp(app)}
|
|
class="flex flex-col items-center gap-1.5 rounded-lg p-3 text-center transition-colors hover:bg-accent"
|
|
>
|
|
<div class="flex size-10 items-center justify-center overflow-hidden rounded-xl bg-primary/10 text-primary">
|
|
{#if app.iconUrl}
|
|
<img src={app.iconUrl} alt={app.name} class="size-full object-cover" />
|
|
{:else}
|
|
<LayoutGridIcon class="size-5" />
|
|
{/if}
|
|
</div>
|
|
<span class="text-sm font-medium leading-tight">{app.name}</span>
|
|
{#if app.slug}
|
|
<span class="text-xs text-muted-foreground">{app.slug}</span>
|
|
{/if}
|
|
</button>
|
|
{/each}
|
|
</div>
|
|
</DropdownMenu.Content>
|
|
</DropdownMenu.Root>
|