feat(dashboard): Classic Split — 2-col layout, remove DashboardMentions widget
Some checks failed
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Some checks failed
CI / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Restructures the dashboard to a lg:grid-cols-[1fr_300px] split: - Left column: DashboardRecentDocuments (with stats footnote) - Right column: DropZone (canWrite) + DashboardNeedsMetadata (flex-1) Adds showRightColumn guard (canWrite || incompleteDocs.length > 0) so read-only users with a complete archive never see an empty 300px ghost column. DashboardMentions is removed from the page; the file is kept. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,6 @@ import SearchFilterBar from './SearchFilterBar.svelte';
|
|||||||
import DropZone from './DropZone.svelte';
|
import DropZone from './DropZone.svelte';
|
||||||
import DocumentList from './DocumentList.svelte';
|
import DocumentList from './DocumentList.svelte';
|
||||||
import DashboardResumeStrip from '$lib/components/DashboardResumeStrip.svelte';
|
import DashboardResumeStrip from '$lib/components/DashboardResumeStrip.svelte';
|
||||||
import DashboardMentions from '$lib/components/DashboardMentions.svelte';
|
|
||||||
import DashboardNeedsMetadata from '$lib/components/DashboardNeedsMetadata.svelte';
|
import DashboardNeedsMetadata from '$lib/components/DashboardNeedsMetadata.svelte';
|
||||||
import DashboardRecentDocuments from '$lib/components/DashboardRecentDocuments.svelte';
|
import DashboardRecentDocuments from '$lib/components/DashboardRecentDocuments.svelte';
|
||||||
import { m } from '$lib/paraglide/messages.js';
|
import { m } from '$lib/paraglide/messages.js';
|
||||||
@@ -69,6 +68,11 @@ $effect(() => {
|
|||||||
tagNames = data.filters?.tags || [];
|
tagNames = data.filters?.tags || [];
|
||||||
if (hasAdvancedFilters(data.filters)) showAdvanced = true;
|
if (hasAdvancedFilters(data.filters)) showAdvanced = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Right column is only rendered when there is something to show.
|
||||||
|
// Omitting it prevents an empty 300px ghost column for read-only users
|
||||||
|
// with a complete archive.
|
||||||
|
const showRightColumn = $derived(data.canWrite || (data.incompleteDocs?.length ?? 0) > 0);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@@ -94,20 +98,24 @@ $effect(() => {
|
|||||||
{#if data.isDashboard}
|
{#if data.isDashboard}
|
||||||
<DashboardResumeStrip />
|
<DashboardResumeStrip />
|
||||||
|
|
||||||
{#if data.canWrite}
|
<!-- Classic Split: left column (recent docs) + right column (upload + metadata queue) -->
|
||||||
<div class="mt-4">
|
<!-- No items-start — CSS Grid stretch default makes both columns equal height -->
|
||||||
<DropZone />
|
<div class="mt-4 grid grid-cols-1 gap-4 {showRightColumn ? 'lg:grid-cols-[1fr_300px]' : ''}">
|
||||||
</div>
|
<DashboardRecentDocuments recentDocs={data.recentDocs ?? []} stats={data.stats} />
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div
|
{#if showRightColumn}
|
||||||
class="mt-6 grid gap-4 {(data.mentions?.length ?? 0) > 0 && (data.incompleteDocs?.length ?? 0) > 0 ? 'lg:grid-cols-2' : ''}"
|
<div data-testid="dashboard-right-column" class="flex h-full flex-col gap-4">
|
||||||
>
|
{#if data.canWrite}
|
||||||
<DashboardMentions mentions={data.mentions ?? []} />
|
<DropZone />
|
||||||
<DashboardNeedsMetadata incompleteDocs={data.incompleteDocs ?? []} />
|
{/if}
|
||||||
</div>
|
<!-- flex-1 + min-h-0 fills remaining height after DropZone.
|
||||||
<div class="mt-4">
|
min-h-0 overrides the default min-height:auto that prevents flex
|
||||||
<DashboardRecentDocuments recentDocs={data.recentDocs ?? []} />
|
children from shrinking below their content size. -->
|
||||||
|
<div class="flex min-h-0 flex-1 flex-col">
|
||||||
|
<DashboardNeedsMetadata incompleteDocs={data.incompleteDocs ?? []} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<DocumentList documents={data.documents ?? []} canWrite={data.canWrite} error={data.error} />
|
<DocumentList documents={data.documents ?? []} canWrite={data.canWrite} error={data.error} />
|
||||||
|
|||||||
@@ -21,8 +21,12 @@ const emptyData = {
|
|||||||
user: undefined,
|
user: undefined,
|
||||||
canWrite: true,
|
canWrite: true,
|
||||||
canAnnotate: false,
|
canAnnotate: false,
|
||||||
|
isDashboard: false,
|
||||||
filters: { q: '', from: '', to: '', senderId: '', receiverId: '', tags: [] },
|
filters: { q: '', from: '', to: '', senderId: '', receiverId: '', tags: [] },
|
||||||
documents: [],
|
documents: [],
|
||||||
|
incompleteDocs: [],
|
||||||
|
recentDocs: [],
|
||||||
|
stats: null,
|
||||||
incompleteCount: 0,
|
incompleteCount: 0,
|
||||||
initialValues: { senderName: '', receiverName: '' },
|
initialValues: { senderName: '', receiverName: '' },
|
||||||
error: null
|
error: null
|
||||||
@@ -189,6 +193,42 @@ describe('Home page – search input keystroke preservation', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ─── Dashboard mode ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
describe('Home page – dashboard mode', () => {
|
||||||
|
const dashboardData = {
|
||||||
|
...emptyData,
|
||||||
|
isDashboard: true,
|
||||||
|
canWrite: false,
|
||||||
|
incompleteDocs: [],
|
||||||
|
recentDocs: []
|
||||||
|
};
|
||||||
|
|
||||||
|
it('hides the right column when canWrite is false and incompleteDocs is empty', async () => {
|
||||||
|
render(Page, { data: dashboardData });
|
||||||
|
const rightCol = page.getByTestId('dashboard-right-column');
|
||||||
|
await expect.element(rightCol).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows the right column when canWrite is true', async () => {
|
||||||
|
render(Page, { data: { ...dashboardData, canWrite: true } });
|
||||||
|
const rightCol = page.getByTestId('dashboard-right-column');
|
||||||
|
await expect.element(rightCol).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows the right column when incompleteDocs is non-empty', async () => {
|
||||||
|
render(Page, {
|
||||||
|
data: {
|
||||||
|
...dashboardData,
|
||||||
|
canWrite: false,
|
||||||
|
incompleteDocs: [{ id: 'd1', title: 'Taufschein' }]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const rightCol = page.getByTestId('dashboard-right-column');
|
||||||
|
await expect.element(rightCol).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// ─── Error state ──────────────────────────────────────────────────────────────
|
// ─── Error state ──────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
describe('Home page – error state', () => {
|
describe('Home page – error state', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user