diff --git a/ka-note/VERSION b/ka-note/VERSION index 168b04a..b3350ea 100644 --- a/ka-note/VERSION +++ b/ka-note/VERSION @@ -1 +1 @@ -1.1.103 \ No newline at end of file +1.1.104 \ No newline at end of file diff --git a/ka-note/client/src/lib/components/RenderedMarkdown.svelte b/ka-note/client/src/lib/components/RenderedMarkdown.svelte index 096bc88..c850ef2 100644 --- a/ka-note/client/src/lib/components/RenderedMarkdown.svelte +++ b/ka-note/client/src/lib/components/RenderedMarkdown.svelte @@ -4,6 +4,9 @@ import { refClick } from '$lib/actions/refClick'; import { ratingIndicator } from '$lib/actions/ratingIndicator'; import { linkMenu } from '$lib/actions/linkMenu'; + import { findContextByAbbreviation, findContextByMentionName } from '$lib/db/repositories'; + import { scopeSettings } from '$lib/stores/scopeContext'; + import type { PersonSubType } from '@ka-note/shared'; interface Props { text: string; @@ -12,11 +15,42 @@ let { text, class: className = '' }: Props = $props(); let html = $state(''); + let containerEl: HTMLDivElement | undefined; async function resolveAndRender(md: string) { if (!md) { html = ''; return; } const resolved = await resolveImageUrls(md); html = renderMarkdown(resolved); + // After DOM update, colorize assignment chips based on personSubType + await Promise.resolve(); // let Svelte flush {@html html} + if (!containerEl) return; + function applySubtypeColor(chip: HTMLElement, subType: PersonSubType | undefined) { + const color = $scopeSettings.personSubTypeColors[subType ?? 'contact'] ?? $scopeSettings.personSubTypeColors.contact; + chip.className = chip.className + .replace(/\bbg-person-ref\b/, 'bg-white/10') + .replace(/border-\[#6272a4\]/, '') + .replace(/\bborder-transparent\b/, '') + .replace(/text-white/, ''); + chip.style.borderColor = color; + chip.style.color = color; + } + + const assignmentChips = containerEl.querySelectorAll('[data-assignment]'); + const personChips = containerEl.querySelectorAll('[data-person]'); + await Promise.all([ + ...Array.from(assignmentChips).map(async chip => { + const ctx = await findContextByAbbreviation(chip.dataset.assignment!); + if (!ctx) return; + const subType = (ctx.meta as Record | null)?.personSubType as PersonSubType | undefined; + applySubtypeColor(chip, subType); + }), + ...Array.from(personChips).map(async chip => { + const ctx = await findContextByMentionName(chip.dataset.person!, 'person'); + if (!ctx) return; + const subType = (ctx.meta as Record | null)?.personSubType as PersonSubType | undefined; + applySubtypeColor(chip, subType); + }), + ]); } $effect(() => { @@ -24,4 +58,4 @@ }); -
{@html html}
+
{@html html}
diff --git a/ka-note/client/src/lib/stores/scopeContext.ts b/ka-note/client/src/lib/stores/scopeContext.ts index e3796aa..72bc26c 100644 --- a/ka-note/client/src/lib/stores/scopeContext.ts +++ b/ka-note/client/src/lib/stores/scopeContext.ts @@ -7,6 +7,14 @@ export const currentScope = writable(null); // --- Persisted settings --- +export interface PersonSubTypeColors { + contact: string; + employee: string; + colleague: string; + family: string; + acquaintance: string; +} + export interface ScopeSettings { businessColor: string; privateColor: string; @@ -14,6 +22,7 @@ export interface ScopeSettings { businessIcon: string; privateIcon: string; maxTitleLength: number; + personSubTypeColors: PersonSubTypeColors; } const SETTINGS_KEY = 'ka-scope-settings'; @@ -25,6 +34,13 @@ const defaults: ScopeSettings = { businessIcon: '🏭', privateIcon: '🏠', maxTitleLength: 22, + personSubTypeColors: { + contact: '#888888', + employee: '#4a9eff', + colleague: '#00b894', + family: '#e84393', + acquaintance: '#a29bfe', + }, }; function loadSettings(): ScopeSettings { diff --git a/ka-note/client/src/routes/settings/+page.svelte b/ka-note/client/src/routes/settings/+page.svelte index 9ccf7b1..209a958 100644 --- a/ka-note/client/src/routes/settings/+page.svelte +++ b/ka-note/client/src/routes/settings/+page.svelte @@ -9,7 +9,11 @@ const API_BASE = import.meta.env.VITE_API_URL ?? ''; - let settings = $state({ ...$scopeSettings }); + const defaultSubTypeColors = { contact: '#888888', employee: '#4a9eff', colleague: '#00b894', family: '#e84393', acquaintance: '#a29bfe' }; + let settings = $state({ + ...$scopeSettings, + personSubTypeColors: { ...defaultSubTypeColors, ...$scopeSettings.personSubTypeColors }, + }); // --- API Keys --- interface ApiKey { @@ -111,6 +115,13 @@ businessIcon: '🏭', privateIcon: '🏠', maxTitleLength: 22, + personSubTypeColors: { + contact: '#888888', + employee: '#4a9eff', + colleague: '#00b894', + family: '#e84393', + acquaintance: '#a29bfe', + }, }); settings = { ...$scopeSettings }; } @@ -206,6 +217,31 @@ + +
+

Personen-Typ Farben

+

Farbe der @Mention- und →Kürzel-Chips je nach Personen-Typ.

+
+ {#each [['contact', 'Kontakt'], ['employee', 'Mitarbeiter'], ['colleague', 'Kollege'], ['family', 'Familie'], ['acquaintance', 'Bekannte']] as [key, label]} +
+ {label} + { + settings.personSubTypeColors = { ...settings.personSubTypeColors, [key]: e.currentTarget.value }; + save(); + }} + class="h-8 w-16 cursor-pointer rounded border border-border bg-transparent" + /> + {settings.personSubTypeColors?.[key as keyof typeof settings.personSubTypeColors] ?? '#888888'} +
+ {/each} +
+ +
+

Browser-Authentifizierung