chore: merge main into feat/issue-281-documents-page
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2m39s
CI / Backend Unit Tests (pull_request) Failing after 2m50s
CI / Unit & Component Tests (push) Failing after 2m31s
CI / OCR Service Tests (push) Successful in 31s
CI / Backend Unit Tests (push) Failing after 2m52s
CI / OCR Service Tests (pull_request) Successful in 29s
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 2m39s
CI / Backend Unit Tests (pull_request) Failing after 2m50s
CI / Unit & Component Tests (push) Failing after 2m31s
CI / OCR Service Tests (push) Successful in 31s
CI / Backend Unit Tests (push) Failing after 2m52s
CI / OCR Service Tests (pull_request) Successful in 29s
Resolved 9 conflicts: - AuditLogQueryRepository/Service: keep HEAD (findRecentContributorsForDocuments) - ContributorStack: merge main key fix + text-[10px] with HEAD safeColor + aria - DashboardResumeStrip: merge main text-[10px] with HEAD safeColor - +page.server/svelte + tests: keep HEAD (pure dashboard, no isDashboard) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit was merged in pull request #282.
This commit is contained in:
@@ -25,11 +25,11 @@ function safeColor(color: string): string {
|
||||
></span>
|
||||
{:else}
|
||||
<span class="inline-flex items-center">
|
||||
{#each safeContributors as actor, i (i)}
|
||||
{#each safeContributors as actor, i (actor.initials + '-' + actor.color)}
|
||||
<span
|
||||
role="img"
|
||||
aria-label={actor.name ?? actor.initials}
|
||||
class="inline-flex h-[22px] w-[22px] flex-shrink-0 items-center justify-center rounded-full font-sans text-xs font-bold text-white ring-2 ring-white {i > 0 ? '-ml-1.5' : ''}"
|
||||
class="inline-flex h-[22px] w-[22px] flex-shrink-0 items-center justify-center rounded-full font-sans text-[10px] font-bold text-white ring-2 ring-white {i > 0 ? '-ml-1.5' : ''}"
|
||||
style="background-color: {safeColor(actor.color)};"
|
||||
title={actor.name ?? actor.initials}
|
||||
>
|
||||
@@ -40,7 +40,7 @@ function safeColor(color: string): string {
|
||||
<span
|
||||
role="img"
|
||||
aria-label="Weitere Mitwirkende"
|
||||
class="-ml-1.5 inline-flex h-[22px] w-[22px] flex-shrink-0 items-center justify-center rounded-full bg-[#e4e2d7] font-sans text-xs font-bold text-ink-3 ring-2 ring-white"
|
||||
class="-ml-1.5 inline-flex h-[22px] w-[22px] flex-shrink-0 items-center justify-center rounded-full bg-[#e4e2d7] font-sans text-[10px] font-bold text-ink-3 ring-2 ring-white"
|
||||
>
|
||||
…
|
||||
</span>
|
||||
|
||||
@@ -97,7 +97,7 @@ function safeColor(color: string): string {
|
||||
</div>
|
||||
{#each resumeDoc.collaborators.slice(0, 3) as collab (collab.initials + collab.color)}
|
||||
<span
|
||||
class="-ml-1 inline-flex h-6 w-6 items-center justify-center rounded-full font-sans text-xs font-bold text-white ring-2 ring-white"
|
||||
class="-ml-1 inline-flex h-6 w-6 items-center justify-center rounded-full font-sans text-[10px] font-bold text-white ring-2 ring-white"
|
||||
style="background:{safeColor(collab.color)}">{collab.initials}</span
|
||||
>
|
||||
{/each}
|
||||
|
||||
@@ -4455,3 +4455,7 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export type DashboardResumeDTO = components['schemas']['DashboardResumeDTO'];
|
||||
export type DashboardPulseDTO = components['schemas']['DashboardPulseDTO'];
|
||||
export type ActivityFeedItemDTO = components['schemas']['ActivityFeedItemDTO'];
|
||||
|
||||
@@ -15,16 +15,6 @@ const unsaved = createUnsavedWarning();
|
||||
|
||||
const selectedGroupIds = $derived(data.editUser.groups?.map((g: { id: string }) => g.id) ?? []);
|
||||
|
||||
let deleteFormEl = $state<HTMLFormElement | null>(null);
|
||||
|
||||
async function handleDelete() {
|
||||
const confirmed = await confirm({
|
||||
title: m.admin_user_delete_confirm({ username: data.editUser.email }),
|
||||
destructive: true
|
||||
});
|
||||
if (confirmed) deleteFormEl!.requestSubmit();
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
if (form?.success) unsaved.clearOnSuccess();
|
||||
});
|
||||
@@ -51,10 +41,23 @@ $effect(() => {
|
||||
<h2 class="flex-1 font-sans text-sm font-bold text-ink">
|
||||
{m.admin_user_edit_heading({ username: data.editUser.email })}
|
||||
</h2>
|
||||
<form bind:this={deleteFormEl} method="POST" action="?/delete" use:enhance>
|
||||
<form
|
||||
method="POST"
|
||||
action="?/delete"
|
||||
use:enhance={async ({ cancel }) => {
|
||||
const confirmed = await confirm({
|
||||
title: m.admin_user_delete_confirm({ username: data.editUser.email }),
|
||||
destructive: true
|
||||
});
|
||||
if (!confirmed) {
|
||||
cancel();
|
||||
} else {
|
||||
unsaved.clearOnSuccess();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onclick={handleDelete}
|
||||
type="submit"
|
||||
class="rounded-sm border border-red-200 bg-red-50 px-3 py-1 font-sans text-xs font-bold tracking-widest text-red-700 uppercase transition-colors hover:bg-red-100 dark:border-red-900 dark:bg-red-950/30 dark:text-red-400"
|
||||
>
|
||||
{m.btn_delete()}…
|
||||
|
||||
@@ -4,7 +4,17 @@ import { page } from 'vitest/browser';
|
||||
import Page from './+page.svelte';
|
||||
import { createConfirmService, CONFIRM_KEY } from '$lib/services/confirm.svelte.js';
|
||||
|
||||
vi.mock('$app/forms', () => ({ enhance: () => () => {} }));
|
||||
const cancelMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock('$app/forms', () => ({
|
||||
enhance: (form: HTMLFormElement, callback?: (args: { cancel: () => void }) => Promise<void>) => {
|
||||
form.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
if (callback) await callback({ cancel: cancelMock });
|
||||
});
|
||||
return () => {};
|
||||
}
|
||||
}));
|
||||
vi.mock('$app/navigation', () => ({ beforeNavigate: vi.fn(), goto: vi.fn() }));
|
||||
|
||||
import { beforeNavigate, goto } from '$app/navigation';
|
||||
@@ -161,39 +171,39 @@ describe('Admin edit user page – feedback', () => {
|
||||
// ─── Delete confirmation ──────────────────────────────────────────────────────
|
||||
|
||||
describe('Admin edit user page – delete confirmation', () => {
|
||||
it('delete button has type=button (does not submit natively)', async () => {
|
||||
beforeEach(() => cancelMock.mockClear());
|
||||
|
||||
it('delete button has type=submit', async () => {
|
||||
renderPage({ data: baseData, form: null });
|
||||
const deleteForm = document.querySelector<HTMLFormElement>('form[action="?/delete"]')!;
|
||||
const deleteBtn = deleteForm.querySelector('button') as HTMLButtonElement;
|
||||
expect(deleteBtn.type).toBe('button');
|
||||
expect(deleteBtn.type).toBe('submit');
|
||||
});
|
||||
|
||||
it('does not submit delete form when user cancels', async () => {
|
||||
it('calls cancel() and does not submit when user cancels', async () => {
|
||||
const { service } = renderPage({ data: baseData, form: null });
|
||||
const deleteForm = document.querySelector<HTMLFormElement>('form[action="?/delete"]')!;
|
||||
const requestSubmit = vi.spyOn(deleteForm, 'requestSubmit').mockImplementation(() => {});
|
||||
const deleteBtn = deleteForm.querySelector('button') as HTMLButtonElement;
|
||||
|
||||
const deleteBtn = deleteForm.querySelector('button[type="button"]') as HTMLButtonElement;
|
||||
deleteBtn.click();
|
||||
await vi.waitFor(() => expect(service.options).not.toBeNull());
|
||||
service.settle(false);
|
||||
await vi.waitFor(() => expect(service.options).toBeNull());
|
||||
|
||||
expect(requestSubmit).not.toHaveBeenCalled();
|
||||
expect(cancelMock).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('submits delete form when user confirms', async () => {
|
||||
it('does not call cancel() and allows submit when user confirms', async () => {
|
||||
const { service } = renderPage({ data: baseData, form: null });
|
||||
const deleteForm = document.querySelector<HTMLFormElement>('form[action="?/delete"]')!;
|
||||
const requestSubmit = vi.spyOn(deleteForm, 'requestSubmit').mockImplementation(() => {});
|
||||
const deleteBtn = deleteForm.querySelector('button') as HTMLButtonElement;
|
||||
|
||||
const deleteBtn = deleteForm.querySelector('button[type="button"]') as HTMLButtonElement;
|
||||
deleteBtn.click();
|
||||
await vi.waitFor(() => expect(service.options).not.toBeNull());
|
||||
service.settle(true);
|
||||
await vi.waitFor(() => expect(service.options).toBeNull());
|
||||
|
||||
expect(requestSubmit).toHaveBeenCalledOnce();
|
||||
expect(cancelMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user