feat(domains): Inline-Edit + Favicon in Settings + Filter IN Suchmaske
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 1m17s

Domain-Admin-Seite bekommt jetzt ein Favicon-Icon vor jedem Eintrag,
einen Pencil-Button zum Inline-Editieren von Domain und Anzeigename,
und Save/Cancel-Buttons. Beim Ändern des Domain-Namens wird das Favicon
zurückgesetzt und beim Speichern frisch nachgeladen (den Filter-Dropdown-
Icons reicht der neue favicon_path automatisch zu).

Der Filter-Button auf der Hauptseite sitzt jetzt IM weißen Suchfeld-
Container (neuer .search-box-Wrapper mit Border) statt daneben, analog
zum Referenz-Screenshot von rezeptwelt.de. Neue inline-Prop an
SearchFilter schaltet eigenen Border/Background ab und setzt stattdessen
einen vertikalen Divider nach rechts.

- Neuer PATCH /api/domains/[id] mit zod-Schema.
- Repository: updateDomain(id, patch) + getDomainById(id).
  domain-Change nullt favicon_path → Caller lädt neu.
- Tests für updateDomain-Fälle und getDomainById.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-18 08:28:02 +02:00
parent 6c2b24d060
commit 15c15c8494
6 changed files with 312 additions and 28 deletions

View File

@@ -1,6 +1,13 @@
import { describe, it, expect } from 'vitest';
import { openInMemoryForTest } from '../../src/lib/server/db';
import { addDomain, listDomains, removeDomain } from '../../src/lib/server/domains/repository';
import {
addDomain,
listDomains,
removeDomain,
setDomainFavicon,
updateDomain,
getDomainById
} from '../../src/lib/server/domains/repository';
import { isDomainAllowed } from '../../src/lib/server/domains/whitelist';
describe('allowed domains', () => {
@@ -32,4 +39,35 @@ describe('allowed domains', () => {
removeDomain(db, d.id);
expect(listDomains(db)).toEqual([]);
});
it('updateDomain changes label without touching favicon', () => {
const db = openInMemoryForTest();
const d = addDomain(db, 'chefkoch.de', 'Chefkoch');
setDomainFavicon(db, d.id, 'favicon-abc.png');
const updated = updateDomain(db, d.id, { display_name: 'Chefkoch.de' });
expect(updated?.domain).toBe('chefkoch.de');
expect(updated?.display_name).toBe('Chefkoch.de');
expect(updated?.favicon_path).toBe('favicon-abc.png');
});
it('updateDomain resets favicon when the domain itself changes', () => {
const db = openInMemoryForTest();
const d = addDomain(db, 'chefkoch.de');
setDomainFavicon(db, d.id, 'favicon-abc.png');
const updated = updateDomain(db, d.id, { domain: 'rezeptwelt.de' });
expect(updated?.domain).toBe('rezeptwelt.de');
expect(updated?.favicon_path).toBe(null);
});
it('updateDomain returns null for missing id', () => {
const db = openInMemoryForTest();
expect(updateDomain(db, 999, { domain: 'x.com' })).toBe(null);
});
it('getDomainById fetches single row', () => {
const db = openInMemoryForTest();
const d = addDomain(db, 'chefkoch.de');
expect(getDomainById(db, d.id)?.domain).toBe('chefkoch.de');
expect(getDomainById(db, 999)).toBe(null);
});
});