person colors

This commit is contained in:
beo3000 2026-02-28 16:53:25 +01:00
parent 828631467c
commit 1752e3c27c
4 changed files with 89 additions and 3 deletions

View File

@ -1 +1 @@
1.1.103
1.1.104

View File

@ -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<HTMLElement>('[data-assignment]');
const personChips = containerEl.querySelectorAll<HTMLElement>('[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<string, unknown> | 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<string, unknown> | null)?.personSubType as PersonSubType | undefined;
applySubtypeColor(chip, subType);
}),
]);
}
$effect(() => {
@ -24,4 +58,4 @@
});
</script>
<div class="markdown-content {className}" use:refClick use:ratingIndicator use:linkMenu>{@html html}</div>
<div bind:this={containerEl} class="markdown-content {className}" use:refClick use:ratingIndicator use:linkMenu>{@html html}</div>

View File

@ -7,6 +7,14 @@ export const currentScope = writable<Scope>(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 {

View File

@ -9,7 +9,11 @@
const API_BASE = import.meta.env.VITE_API_URL ?? '';
let settings = $state<ScopeSettings>({ ...$scopeSettings });
const defaultSubTypeColors = { contact: '#888888', employee: '#4a9eff', colleague: '#00b894', family: '#e84393', acquaintance: '#a29bfe' };
let settings = $state<ScopeSettings>({
...$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 @@
</div>
</section>
<!-- Person Subtype Colors -->
<section class="space-y-4">
<h2 class="text-sm font-semibold uppercase text-muted">Personen-Typ Farben</h2>
<p class="text-xs text-muted">Farbe der @Mention- und →Kürzel-Chips je nach Personen-Typ.</p>
<div class="rounded border border-border bg-card-bg p-4 space-y-3">
{#each [['contact', 'Kontakt'], ['employee', 'Mitarbeiter'], ['colleague', 'Kollege'], ['family', 'Familie'], ['acquaintance', 'Bekannte']] as [key, label]}
<div class="flex items-center gap-4">
<span class="text-sm w-28" style="color: {settings.personSubTypeColors?.[key as keyof typeof settings.personSubTypeColors] ?? '#888'}">{label}</span>
<input type="color"
value={settings.personSubTypeColors?.[key as keyof typeof settings.personSubTypeColors] ?? '#888888'}
oninput={(e) => {
settings.personSubTypeColors = { ...settings.personSubTypeColors, [key]: e.currentTarget.value };
save();
}}
class="h-8 w-16 cursor-pointer rounded border border-border bg-transparent"
/>
<span class="text-xs text-muted font-mono">{settings.personSubTypeColors?.[key as keyof typeof settings.personSubTypeColors] ?? '#888888'}</span>
</div>
{/each}
</div>
<button class="text-xs text-muted hover:text-white underline" onclick={reset}>
Auf Standard zurücksetzen
</button>
</section>
<!-- Browser API Key -->
<section class="space-y-4">
<h2 class="text-sm font-semibold uppercase text-muted">Browser-Authentifizierung</h2>