feat(assistant): add multi-dialog UX, task-aware llm settings, and i18n cleanup
This commit is contained in:
@@ -30,7 +30,7 @@
|
||||
*/
|
||||
function getBreadcrumbs(pathname, maxVisible = 3) {
|
||||
const segments = pathname.split("/").filter(Boolean);
|
||||
const allItems = [{ label: "Home", path: "/" }];
|
||||
const allItems = [{ label: $t.nav?.home || "Home", path: "/" }];
|
||||
|
||||
let currentPath = "";
|
||||
segments.forEach((segment, index) => {
|
||||
@@ -136,7 +136,7 @@
|
||||
|
||||
<nav
|
||||
class="mx-4 md:mx-6"
|
||||
aria-label="Breadcrumb navigation"
|
||||
aria-label={$t.nav?.breadcrumb_nav || "Breadcrumb navigation"}
|
||||
>
|
||||
<div class="inline-flex max-w-full items-center gap-1.5 rounded-xl border border-slate-200/80 bg-white/85 px-2 py-1.5 shadow-sm backdrop-blur">
|
||||
{#each breadcrumbItems as item, index}
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
<span class="inline-flex h-6 w-6 items-center justify-center rounded-md bg-gradient-to-br from-slate-100 to-slate-200 text-slate-700 ring-1 ring-slate-200">
|
||||
<Icon name="layers" size={14} />
|
||||
</span>
|
||||
Menu
|
||||
{$t.nav?.menu || "Menu"}
|
||||
</span>
|
||||
{:else}
|
||||
<span class="text-xs text-gray-500">M</span>
|
||||
@@ -285,7 +285,7 @@
|
||||
<span class="mr-2 inline-flex h-6 w-6 items-center justify-center rounded-md bg-slate-100 text-slate-600">
|
||||
<Icon name="chevronLeft" size={14} />
|
||||
</span>
|
||||
Collapse
|
||||
{$t.nav?.collapse || "Collapse"}
|
||||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
@@ -293,10 +293,10 @@
|
||||
<button
|
||||
class="flex items-center justify-center w-full px-4 py-2 text-sm text-gray-600 hover:bg-gray-100 rounded-lg transition-colors"
|
||||
on:click={handleToggleClick}
|
||||
aria-label="Expand sidebar"
|
||||
aria-label={$t.nav?.expand_sidebar || "Expand sidebar"}
|
||||
>
|
||||
<Icon name="chevronRight" size={16} />
|
||||
<span class="ml-2">Expand</span>
|
||||
<span class="ml-2">{$t.nav?.expand || "Expand"}</span>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
on:keydown={(e) => e.key === 'Escape' && handleClose()}
|
||||
role="button"
|
||||
tabindex="0"
|
||||
aria-label="Close drawer"
|
||||
aria-label={$t.tasks?.close_drawer || "Close drawer"}
|
||||
>
|
||||
<!-- Drawer Panel -->
|
||||
<div
|
||||
@@ -209,7 +209,7 @@
|
||||
style={`right: ${assistantOffset};`}
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label="Task drawer"
|
||||
aria-label={$t.tasks?.drawer || "Task drawer"}
|
||||
>
|
||||
<!-- Header -->
|
||||
<div class="flex items-center justify-between border-b border-slate-200 bg-white px-5 py-3.5">
|
||||
@@ -222,13 +222,13 @@
|
||||
<button
|
||||
class="flex items-center justify-center p-1.5 rounded-md text-slate-500 bg-transparent border-none cursor-pointer transition-all hover:text-slate-100 hover:bg-slate-800"
|
||||
on:click={goBackToList}
|
||||
aria-label="Back to task list"
|
||||
aria-label={$t.tasks?.back_to_list || "Back to task list"}
|
||||
>
|
||||
<Icon name="back" size={16} strokeWidth={2} />
|
||||
</button>
|
||||
{/if}
|
||||
<h2 class="text-sm font-semibold tracking-tight text-slate-900">
|
||||
{activeTaskId ? ($t.tasks?.details_logs || 'Task Details & Logs') : 'Recent Tasks'}
|
||||
{activeTaskId ? ($t.tasks?.details_logs || 'Task Details & Logs') : ($t.tasks?.recent || 'Recent Tasks')}
|
||||
</h2>
|
||||
{#if shortTaskId}
|
||||
<span class="text-xs font-mono text-slate-500 bg-slate-800 px-2 py-0.5 rounded">{shortTaskId}…</span>
|
||||
@@ -249,7 +249,7 @@
|
||||
<button
|
||||
class="p-1.5 rounded-md text-slate-500 bg-transparent border-none cursor-pointer transition-all hover:text-slate-100 hover:bg-slate-800"
|
||||
on:click={handleClose}
|
||||
aria-label="Close drawer"
|
||||
aria-label={$t.tasks?.close_drawer || "Close drawer"}
|
||||
>
|
||||
<Icon name="close" size={18} strokeWidth={2} />
|
||||
</button>
|
||||
@@ -268,19 +268,19 @@
|
||||
{:else if loadingTasks}
|
||||
<div class="flex flex-col items-center justify-center p-12 text-slate-500">
|
||||
<div class="mb-4 h-8 w-8 animate-spin rounded-full border-2 border-slate-200 border-t-blue-500"></div>
|
||||
<p>Loading tasks...</p>
|
||||
<p>{$t.tasks?.loading || 'Loading tasks...'}</p>
|
||||
</div>
|
||||
{:else if recentTasks.length > 0}
|
||||
<div class="p-4">
|
||||
<h3 class="text-sm font-semibold text-slate-100 mb-4 pb-2 border-b border-slate-800">Recent Tasks</h3>
|
||||
<h3 class="text-sm font-semibold text-slate-100 mb-4 pb-2 border-b border-slate-800">{$t.tasks?.recent || 'Recent Tasks'}</h3>
|
||||
{#each recentTasks as task}
|
||||
<button
|
||||
class="flex items-center gap-3 w-full p-3 mb-2 bg-slate-800 border border-slate-700 rounded-lg cursor-pointer transition-all hover:bg-slate-700 hover:border-slate-600 text-left"
|
||||
on:click={() => selectTask(task)}
|
||||
>
|
||||
<span class="font-mono text-xs text-slate-500">{task.id?.substring(0, 8) || 'N/A'}...</span>
|
||||
<span class="flex-1 text-sm text-slate-100 font-medium">{task.plugin_id || 'Unknown'}</span>
|
||||
<span class="text-xs font-semibold uppercase px-2 py-1 rounded-full {task.status?.toLowerCase() === 'running' || task.status?.toLowerCase() === 'pending' ? 'bg-cyan-500/15 text-cyan-400' : task.status?.toLowerCase() === 'completed' || task.status?.toLowerCase() === 'success' ? 'bg-green-500/15 text-green-400' : task.status?.toLowerCase() === 'failed' || task.status?.toLowerCase() === 'error' ? 'bg-red-500/15 text-red-400' : 'bg-slate-500/15 text-slate-400'}">{task.status || 'UNKNOWN'}</span>
|
||||
<span class="font-mono text-xs text-slate-500">{task.id?.substring(0, 8) || ($t.common?.not_available || 'N/A')}...</span>
|
||||
<span class="flex-1 text-sm text-slate-100 font-medium">{task.plugin_id || ($t.common?.unknown || 'Unknown')}</span>
|
||||
<span class="text-xs font-semibold uppercase px-2 py-1 rounded-full {task.status?.toLowerCase() === 'running' || task.status?.toLowerCase() === 'pending' ? 'bg-cyan-500/15 text-cyan-400' : task.status?.toLowerCase() === 'completed' || task.status?.toLowerCase() === 'success' ? 'bg-green-500/15 text-green-400' : task.status?.toLowerCase() === 'failed' || task.status?.toLowerCase() === 'error' ? 'bg-red-500/15 text-red-400' : 'bg-slate-500/15 text-slate-400'}">{task.status || ($t.common?.unknown || 'UNKNOWN')}</span>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
import { auth } from "$lib/auth/store.js";
|
||||
import { toggleAssistantChat } from "$lib/stores/assistantChat.js";
|
||||
import Icon from "$lib/ui/Icon.svelte";
|
||||
import LanguageSwitcher from "$lib/ui/LanguageSwitcher.svelte";
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
@@ -105,7 +106,7 @@
|
||||
<button
|
||||
class="rounded-lg p-2 text-slate-600 transition-colors hover:bg-slate-100 md:hidden"
|
||||
on:click={handleHamburgerClick}
|
||||
aria-label="Toggle menu"
|
||||
aria-label={$t.common?.toggle_menu || "Toggle menu"}
|
||||
>
|
||||
<Icon name="menu" size={22} />
|
||||
</button>
|
||||
@@ -136,6 +137,8 @@
|
||||
|
||||
<!-- Nav Actions -->
|
||||
<div class="flex items-center gap-3 md:gap-4">
|
||||
<LanguageSwitcher />
|
||||
|
||||
<!-- Assistant -->
|
||||
<button
|
||||
class="rounded-lg p-2 text-slate-600 transition-colors hover:bg-slate-100"
|
||||
@@ -154,7 +157,7 @@
|
||||
(e.key === "Enter" || e.key === " ") && handleActivityClick()}
|
||||
role="button"
|
||||
tabindex="0"
|
||||
aria-label="Activity"
|
||||
aria-label={$t.common?.activity || "Activity"}
|
||||
>
|
||||
<Icon name="activity" size={22} />
|
||||
{#if activeCount > 0}
|
||||
@@ -174,7 +177,7 @@
|
||||
(e.key === "Enter" || e.key === " ") && toggleUserMenu(e)}
|
||||
role="button"
|
||||
tabindex="0"
|
||||
aria-label="User menu"
|
||||
aria-label={$t.common?.user_menu || "User menu"}
|
||||
>
|
||||
{#if user}
|
||||
<span
|
||||
@@ -192,7 +195,7 @@
|
||||
: 'hidden'}"
|
||||
>
|
||||
<div class="px-4 py-2 text-sm text-gray-700">
|
||||
<strong>{user?.username || "User"}</strong>
|
||||
<strong>{user?.username || ($t.common?.user || "User")}</strong>
|
||||
</div>
|
||||
<div class="border-t border-gray-200 my-1"></div>
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user