ui optimierungen
This commit is contained in:
parent
b24915783d
commit
53b20cf492
|
|
@ -1 +1 @@
|
|||
1.1.49
|
||||
1.1.52
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { page } from "$app/stores";
|
||||
import { page } from "$app/state";
|
||||
import { goto } from "$app/navigation";
|
||||
|
||||
interface Props {
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
}
|
||||
let { onsidebaropen }: Props = $props();
|
||||
|
||||
const currentPath = $derived($page.url.pathname);
|
||||
const currentPath = $derived(page.url.pathname);
|
||||
|
||||
interface Tab {
|
||||
id: string;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/state';
|
||||
import { liveQuery } from 'dexie';
|
||||
import { db } from '$lib/db/schema';
|
||||
import { collapsedTopicIds } from '$lib/stores/agenda';
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
journalScope = s;
|
||||
localStorage.setItem(SCOPE_KEY, s);
|
||||
}
|
||||
const initialDate = $derived($page.url.searchParams.get('date') ?? undefined);
|
||||
const initialDate = $derived(page.url.searchParams.get('date') ?? undefined);
|
||||
let compact = $state(false);
|
||||
|
||||
// Rating modal state
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
import LinkTitle from './LinkTitle.svelte';
|
||||
import { get } from 'svelte/store';
|
||||
import { currentScope, scopeSettings } from '$lib/stores/scopeContext';
|
||||
import { normalizeTitleAndBody } from '$lib/utils/titleUtils';
|
||||
import { normalizeTitleAndBody, extractTitleAndBody } from '$lib/utils/titleUtils';
|
||||
import { useUnsavedGuard } from '$lib/utils/unsavedGuard.svelte';
|
||||
|
||||
interface Props {
|
||||
|
|
@ -27,7 +27,6 @@
|
|||
const isDailyLog = $derived(contextId === 'daily-log');
|
||||
|
||||
// --- Daily-log journal mode ---
|
||||
let entryTitle = $state('');
|
||||
let entryText = $state('');
|
||||
let entryEditor: MarkdownEditor;
|
||||
let selectedDate = $state(initialDate ?? today());
|
||||
|
|
@ -35,7 +34,7 @@
|
|||
let wiedervorlageChecked = $state(true);
|
||||
let meetingPickerOpen = $state(false);
|
||||
|
||||
useUnsavedGuard(() => entryTitle.trim() !== '' || entryText.trim() !== '' || editingId !== null);
|
||||
useUnsavedGuard(() => entryText.trim() !== '' || editingId !== null);
|
||||
|
||||
// All meeting contexts for the link dropdown
|
||||
const meetingContexts = liveQuery(() =>
|
||||
|
|
@ -83,9 +82,12 @@
|
|||
|
||||
|
||||
async function handleAddEntry() {
|
||||
let title = entryTitle.trim();
|
||||
let body = entryText.trim();
|
||||
if (!title) return;
|
||||
const raw = entryText.trim();
|
||||
if (!raw) return;
|
||||
const { maxTitleLength } = get(scopeSettings);
|
||||
const extracted = extractTitleAndBody(raw, maxTitleLength);
|
||||
let title = extracted.title;
|
||||
let body = extracted.body;
|
||||
|
||||
// If title is a URL, try to fetch its page title
|
||||
if (/^https?:\/\//i.test(title)) {
|
||||
|
|
@ -103,14 +105,11 @@
|
|||
await createHistoryEntry(topic.id, selectedDate, body, null, false, isPrivate);
|
||||
}
|
||||
} else {
|
||||
const { maxTitleLength } = get(scopeSettings);
|
||||
const { title: shortTitle, body: fullBody } = normalizeTitleAndBody(title, body, maxTitleLength);
|
||||
const text = fullBody ? `${shortTitle}\n\n${fullBody}` : shortTitle;
|
||||
const text = body ? `${title}\n\n${body}` : title;
|
||||
await getOrCreateJournalTopic();
|
||||
await createHistoryEntry(JOURNAL_TOPIC_ID, selectedDate, text, null, wiedervorlageChecked, isPrivate);
|
||||
}
|
||||
|
||||
entryTitle = '';
|
||||
entryText = '';
|
||||
entryEditor?.clear();
|
||||
selectedLinkedContextId = '';
|
||||
|
|
@ -118,10 +117,6 @@
|
|||
wiedervorlageChecked = true;
|
||||
}
|
||||
|
||||
function handleTitleKeypress(e: KeyboardEvent) {
|
||||
if (e.key === 'Enter') handleAddEntry();
|
||||
}
|
||||
|
||||
let confirmDeleteId = $state<string | null>(null);
|
||||
|
||||
// --- Edit mode ---
|
||||
|
|
@ -160,9 +155,13 @@
|
|||
confirmDeleteId = null;
|
||||
}
|
||||
|
||||
function formatTime(isoString: string): string {
|
||||
function formatTime(entry: { sortOrder: number; updatedAt: string }): string {
|
||||
try {
|
||||
return new Date(isoString).toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' });
|
||||
// sortOrder >= 1e12 means it was set as Date.now() (ms timestamp) → use as creation time
|
||||
const ts = entry.sortOrder >= 1_000_000_000_000
|
||||
? new Date(entry.sortOrder)
|
||||
: new Date(entry.updatedAt);
|
||||
return ts.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' });
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
|
|
@ -238,52 +237,15 @@
|
|||
{/if}
|
||||
|
||||
<div class="mb-8 flex flex-col gap-2.5 rounded-lg border border-border bg-sidebar p-4">
|
||||
<div class="relative flex items-center gap-2">
|
||||
<input
|
||||
type="text"
|
||||
class="flex-1 rounded border border-[#444] bg-bg px-2.5 py-2 font-mono text-white"
|
||||
placeholder="Titel / Was ist passiert?"
|
||||
bind:value={entryTitle}
|
||||
onkeypress={handleTitleKeypress}
|
||||
use:mention
|
||||
/>
|
||||
<!-- Meeting picker icon button -->
|
||||
<button
|
||||
type="button"
|
||||
class="flex items-center gap-1 rounded border px-2 py-2 text-sm transition-colors {journalScope === 'private' ? 'hidden' : selectedLinkedContextId ? 'border-accent bg-accent/20 text-accent' : 'border-[#444] bg-bg text-muted hover:text-white'}"
|
||||
onclick={() => meetingPickerOpen = !meetingPickerOpen}
|
||||
title="Jour-fix verknüpfen"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"/>
|
||||
<line x1="16" y1="2" x2="16" y2="6"/>
|
||||
<line x1="8" y1="2" x2="8" y2="6"/>
|
||||
<line x1="3" y1="10" x2="21" y2="10"/>
|
||||
</svg>
|
||||
</button>
|
||||
{#if meetingPickerOpen}
|
||||
<div class="absolute right-0 top-full z-50 mt-1 min-w-48 rounded border border-[#444] bg-[#1e1e1e] py-1 shadow-lg">
|
||||
<button
|
||||
class="w-full px-3 py-1.5 text-left text-sm text-muted hover:bg-[#2a2a2a] {!selectedLinkedContextId ? 'text-white' : ''}"
|
||||
onclick={() => { selectedLinkedContextId = ''; meetingPickerOpen = false; }}
|
||||
>— kein Jour-fix —</button>
|
||||
{#each $meetingContexts ?? [] as ctx}
|
||||
<button
|
||||
class="w-full px-3 py-1.5 text-left text-sm hover:bg-[#2a2a2a] {selectedLinkedContextId === ctx.id ? 'text-accent' : 'text-white'}"
|
||||
onclick={() => { selectedLinkedContextId = ctx.id; meetingPickerOpen = false; }}
|
||||
>{ctx.name}</button>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<MarkdownEditor
|
||||
bind:this={entryEditor}
|
||||
placeholder="Details (optional)"
|
||||
placeholder="Was ist passiert? (1. Zeile = Titel)"
|
||||
minHeight="60px"
|
||||
wikiScope={journalScope === 'private'}
|
||||
onchange={(md) => entryText = md}
|
||||
onsave={handleAddEntry}
|
||||
/>
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<button
|
||||
class="rounded px-4 py-2 font-bold text-white hover:brightness-110"
|
||||
style="background-color: {journalScope === 'private' ? $scopeSettings.privateColor : $scopeSettings.businessColor}"
|
||||
|
|
@ -294,13 +256,41 @@
|
|||
{#if !selectedLinkedContextId}
|
||||
<button
|
||||
type="button"
|
||||
class="flex items-center gap-1.5 rounded-full border px-3 py-1 text-xs font-medium transition-colors {wiedervorlageChecked ? 'border-amber-500 bg-amber-500/20 text-amber-400' : 'border-[#444] text-muted hover:border-[#666] hover:text-white'}"
|
||||
class="rounded border p-1.5 text-base leading-none transition-colors {wiedervorlageChecked ? 'border-amber-500 bg-amber-500/20 text-amber-400' : 'border-[#444] text-muted hover:border-[#666] hover:text-white'}"
|
||||
onclick={() => wiedervorlageChecked = !wiedervorlageChecked}
|
||||
>
|
||||
<span class="text-base leading-none">{wiedervorlageChecked ? '⏰' : '○'}</span>
|
||||
Wiedervorlage
|
||||
</button>
|
||||
title="Wiedervorlage"
|
||||
>{wiedervorlageChecked ? '⏰' : '○'}</button>
|
||||
{/if}
|
||||
<!-- Meeting picker button -->
|
||||
<div class="relative {journalScope === 'private' ? 'hidden' : ''}">
|
||||
<button
|
||||
type="button"
|
||||
class="flex items-center gap-1 rounded border px-2 py-1.5 text-sm transition-colors {selectedLinkedContextId ? 'border-accent bg-accent/20 text-accent' : 'border-[#444] bg-bg text-muted hover:text-white'}"
|
||||
onclick={() => meetingPickerOpen = !meetingPickerOpen}
|
||||
title="Jour-fix verknüpfen"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"/>
|
||||
<line x1="16" y1="2" x2="16" y2="6"/>
|
||||
<line x1="8" y1="2" x2="8" y2="6"/>
|
||||
<line x1="3" y1="10" x2="21" y2="10"/>
|
||||
</svg>
|
||||
</button>
|
||||
{#if meetingPickerOpen}
|
||||
<div class="absolute left-0 top-full z-50 mt-1 min-w-48 rounded border border-[#444] bg-[#1e1e1e] py-1 shadow-lg">
|
||||
<button
|
||||
class="w-full px-3 py-1.5 text-left text-sm text-muted hover:bg-[#2a2a2a] {!selectedLinkedContextId ? 'text-white' : ''}"
|
||||
onclick={() => { selectedLinkedContextId = ''; meetingPickerOpen = false; }}
|
||||
>— kein Jour-fix —</button>
|
||||
{#each $meetingContexts ?? [] as ctx}
|
||||
<button
|
||||
class="w-full px-3 py-1.5 text-left text-sm hover:bg-[#2a2a2a] {selectedLinkedContextId === ctx.id ? 'text-accent' : 'text-white'}"
|
||||
onclick={() => { selectedLinkedContextId = ctx.id; meetingPickerOpen = false; }}
|
||||
>{ctx.name}</button>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -358,7 +348,7 @@
|
|||
{@const title = lines[0].replace(/^#{1,6}\s+/, '')}
|
||||
{@const body = lines.slice(1).join('\n').trim()}
|
||||
<div class="group mb-3 flex items-start gap-2 rounded bg-card-bg p-2.5">
|
||||
<span class="mt-0.5 text-xs text-muted whitespace-nowrap">{formatTime(entry.updatedAt)}</span>
|
||||
<span class="mt-0.5 text-xs text-muted whitespace-nowrap">{formatTime(entry)}</span>
|
||||
<div class="flex-1">
|
||||
<div class="flex flex-wrap items-center gap-1.5 font-bold">
|
||||
<LinkTitle text={title} />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/state';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
import { liveQuery } from 'dexie';
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
}
|
||||
let { onnavigate, hideLogo = false }: Props = $props();
|
||||
|
||||
const currentId = $derived($page.params.id ?? '');
|
||||
const currentId = $derived(page.params.id ?? '');
|
||||
|
||||
const contexts = liveQuery(() => db.contexts.filter(c => !c.deletedAt && !c.archivedAt).sortBy('sortOrder'));
|
||||
|
||||
|
|
@ -108,12 +108,12 @@
|
|||
{/if}
|
||||
|
||||
<!-- General -->
|
||||
<div class="mb-1 mt-4 pl-1 text-xs uppercase text-muted">General</div>
|
||||
<div class="mb-1 mt-6 pl-1 text-xs uppercase text-muted">General</div>
|
||||
<ul class="m-0 list-none p-0">
|
||||
{#if dailyLog}
|
||||
<li>
|
||||
<button
|
||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-sm transition-colors {currentId === 'daily-log' ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
|
||||
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors {currentId === 'daily-log' ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
|
||||
onclick={() => navigate('daily-log')}
|
||||
>
|
||||
{dailyLog.name}
|
||||
|
|
@ -126,7 +126,7 @@
|
|||
<ul class="m-0 list-none p-0">
|
||||
<li>
|
||||
<button
|
||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-sm transition-colors {$page.url.pathname.startsWith('/journal/archive') ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
|
||||
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors {page.url.pathname.startsWith('/journal/archive') ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
|
||||
onclick={() => { goto('/journal/archive'); onnavigate?.(); }}
|
||||
>
|
||||
📅 Archiv
|
||||
|
|
@ -135,7 +135,7 @@
|
|||
</ul>
|
||||
|
||||
<!-- Jour Fixes -->
|
||||
<div class="mb-1 mt-4 flex items-center justify-between pl-1 pr-1">
|
||||
<div class="mb-1 mt-6 flex items-center justify-between pl-1 pr-1">
|
||||
<button class="text-xs uppercase text-muted hover:text-white flex items-center gap-1" onclick={() => toggleSection('meetings')}>
|
||||
<span class="inline-block text-[10px] transition-transform {collapsed['meetings'] ? '-rotate-90' : ''}">{@html '▼'}</span>
|
||||
Jour Fixes
|
||||
|
|
@ -147,7 +147,7 @@
|
|||
{#each meetings as ctx}
|
||||
<li>
|
||||
<button
|
||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-sm transition-colors {currentId === ctx.id ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
|
||||
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors {currentId === ctx.id ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
|
||||
onclick={() => navigate(ctx.id)}
|
||||
>
|
||||
{ctx.name}
|
||||
|
|
@ -168,7 +168,7 @@
|
|||
{/if}
|
||||
<li>
|
||||
<button
|
||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
|
||||
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
|
||||
onclick={() => { goto('/meetings'); onnavigate?.(); }}
|
||||
>
|
||||
Alle Jour Fixes →
|
||||
|
|
@ -178,7 +178,7 @@
|
|||
{/if}
|
||||
|
||||
<!-- Projects -->
|
||||
<div class="mb-1 mt-4 flex items-center justify-between pl-1 pr-1">
|
||||
<div class="mb-1 mt-6 flex items-center justify-between pl-1 pr-1">
|
||||
<button class="text-xs uppercase text-muted hover:text-white flex items-center gap-1" onclick={() => toggleSection('projects')}>
|
||||
<span class="inline-block text-[10px] transition-transform {collapsed['projects'] ? '-rotate-90' : ''}">{@html '▼'}</span>
|
||||
Projects
|
||||
|
|
@ -190,7 +190,7 @@
|
|||
{#each projects as ctx}
|
||||
<li>
|
||||
<button
|
||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-sm transition-colors {currentId === ctx.id ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
|
||||
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors {currentId === ctx.id ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
|
||||
onclick={() => navigate(ctx.id)}
|
||||
>
|
||||
{displayName(ctx)}
|
||||
|
|
@ -211,7 +211,7 @@
|
|||
{/if}
|
||||
<li>
|
||||
<button
|
||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
|
||||
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
|
||||
onclick={() => { goto('/projects'); onnavigate?.(); }}
|
||||
>
|
||||
Alle Projekte →
|
||||
|
|
@ -221,7 +221,7 @@
|
|||
{/if}
|
||||
|
||||
<!-- Companies -->
|
||||
<div class="mb-1 mt-4 flex items-center justify-between pl-1 pr-1">
|
||||
<div class="mb-1 mt-6 flex items-center justify-between pl-1 pr-1">
|
||||
<button class="text-xs uppercase text-muted hover:text-white flex items-center gap-1" onclick={() => toggleSection('companies')}>
|
||||
<span class="inline-block text-[10px] transition-transform {collapsed['companies'] ? '-rotate-90' : ''}">{@html '▼'}</span>
|
||||
Firmen
|
||||
|
|
@ -233,7 +233,7 @@
|
|||
{#each companies as ctx}
|
||||
<li>
|
||||
<button
|
||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-sm transition-colors {currentId === ctx.id ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
|
||||
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors {currentId === ctx.id ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
|
||||
onclick={() => navigate(ctx.id)}
|
||||
>
|
||||
{displayName(ctx)}
|
||||
|
|
@ -254,7 +254,7 @@
|
|||
{/if}
|
||||
<li>
|
||||
<button
|
||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
|
||||
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
|
||||
onclick={() => { goto('/companies'); onnavigate?.(); }}
|
||||
>
|
||||
Alle Firmen →
|
||||
|
|
@ -264,7 +264,7 @@
|
|||
{/if}
|
||||
|
||||
<!-- People -->
|
||||
<div class="mb-1 mt-4 flex items-center justify-between pl-1 pr-1">
|
||||
<div class="mb-1 mt-6 flex items-center justify-between pl-1 pr-1">
|
||||
<button class="text-xs uppercase text-muted hover:text-white flex items-center gap-1" onclick={() => toggleSection('people')}>
|
||||
<span class="inline-block text-[10px] transition-transform {collapsed['people'] ? '-rotate-90' : ''}">{@html '▼'}</span>
|
||||
People
|
||||
|
|
@ -276,7 +276,7 @@
|
|||
{#each people as ctx}
|
||||
<li>
|
||||
<button
|
||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-sm transition-colors {currentId === ctx.id ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
|
||||
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors {currentId === ctx.id ? 'bg-accent font-bold text-white' : 'text-[#ccc] hover:bg-white/5 hover:text-white'}"
|
||||
onclick={() => navigate(ctx.id)}
|
||||
>
|
||||
{displayName(ctx)}
|
||||
|
|
@ -297,7 +297,7 @@
|
|||
{/if}
|
||||
<li>
|
||||
<button
|
||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
|
||||
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
|
||||
onclick={() => { goto('/persons'); onnavigate?.(); }}
|
||||
>
|
||||
Alle Personen →
|
||||
|
|
@ -307,7 +307,7 @@
|
|||
{/if}
|
||||
|
||||
<!-- Wiki -->
|
||||
<div class="mb-1 mt-4 flex items-center justify-between pl-1 pr-1">
|
||||
<div class="mb-1 mt-6 flex items-center justify-between pl-1 pr-1">
|
||||
<button class="text-xs uppercase text-muted hover:text-white flex items-center gap-1" onclick={() => toggleSection('wiki')}>
|
||||
<span class="inline-block text-[10px] transition-transform {collapsed['wiki'] ? '-rotate-90' : ''}">{@html '▼'}</span>
|
||||
Wiki
|
||||
|
|
@ -319,7 +319,7 @@
|
|||
{#each ($wikiNotebooks$ ?? []) as nb}
|
||||
<li>
|
||||
<button
|
||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-sm transition-colors text-[#ccc] hover:bg-white/5 hover:text-white"
|
||||
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors text-[#ccc] hover:bg-white/5 hover:text-white"
|
||||
onclick={() => { goto(`/wiki/notebook/${nb.id}`); onnavigate?.(); }}
|
||||
>
|
||||
{nb.name}
|
||||
|
|
@ -328,7 +328,7 @@
|
|||
{/each}
|
||||
<li>
|
||||
<button
|
||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
|
||||
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-xs text-[#666] transition-colors hover:bg-white/5 hover:text-[#aaa]"
|
||||
onclick={() => { goto('/wiki'); onnavigate?.(); }}
|
||||
>
|
||||
Alle Notizbücher →
|
||||
|
|
@ -339,7 +339,7 @@
|
|||
|
||||
<div class="mt-4">
|
||||
<button
|
||||
class="mb-1 w-full rounded px-2.5 py-2 text-left text-sm transition-colors flex items-center gap-2 text-[#ccc] hover:bg-white/5 hover:text-white"
|
||||
class="mb-1 w-full rounded px-2.5 py-2.5 text-left text-sm transition-colors flex items-center gap-2 text-[#ccc] hover:bg-white/5 hover:text-white"
|
||||
onclick={() => { goto('/trash'); onnavigate?.(); }}
|
||||
>
|
||||
<span>🗑</span>
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ export async function createHistoryEntry(topicId: string, date: string, text: st
|
|||
topicId,
|
||||
date,
|
||||
text,
|
||||
sortOrder: existing.length,
|
||||
sortOrder: Date.now(),
|
||||
linkedContextId,
|
||||
doneAt: null,
|
||||
wiedervorlageDate: autoWiedervorlage ? date : null,
|
||||
|
|
|
|||
|
|
@ -13,3 +13,19 @@ export function normalizeTitleAndBody(
|
|||
const newBody = body.trim() ? `${title}\n\n${body.trim()}` : title;
|
||||
return { title: short, body: newBody };
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits raw combined input into title + body.
|
||||
* First line (stripped of leading markdown heading markers) becomes the title.
|
||||
* Remaining lines become the body.
|
||||
* Then normalizeTitleAndBody is applied to enforce maxLen.
|
||||
*/
|
||||
export function extractTitleAndBody(
|
||||
raw: string,
|
||||
maxLen = DEFAULT_MAX_TITLE_LENGTH
|
||||
): { title: string; body: string } {
|
||||
const lines = raw.split('\n');
|
||||
const firstLine = lines[0].replace(/^#{1,6}\s*/, '').trim();
|
||||
const rest = lines.slice(1).join('\n').trim();
|
||||
return normalizeTitleAndBody(firstLine, rest, maxLen);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/state';
|
||||
import ContextPage from '$lib/components/ContextPage.svelte';
|
||||
|
||||
const contextId = $derived($page.params.id);
|
||||
const contextId = $derived(page.params.id);
|
||||
</script>
|
||||
|
||||
{#key contextId}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/state';
|
||||
import { goto } from '$app/navigation';
|
||||
import { db } from '$lib/db/schema';
|
||||
import RenderedMarkdown from '$lib/components/RenderedMarkdown.svelte';
|
||||
|
|
@ -18,8 +18,8 @@
|
|||
});
|
||||
|
||||
// URL params
|
||||
const month = $derived($page.url.searchParams.get('month') ?? ''); // YYYY-MM
|
||||
const day = $derived($page.url.searchParams.get('day') ?? ''); // DD
|
||||
const month = $derived(page.url.searchParams.get('month') ?? ''); // YYYY-MM
|
||||
const day = $derived(page.url.searchParams.get('day') ?? ''); // DD
|
||||
|
||||
// View: 'index' | 'month' | 'day'
|
||||
const view = $derived(day ? 'day' : month ? 'month' : 'index');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/state';
|
||||
import { goto } from '$app/navigation';
|
||||
import { db } from '$lib/db/schema';
|
||||
import { upsertPage, softDeletePage, togglePageFavorite, getNotebooksForPage, getBacklinksForPage, assignPageToNotebook, removePageFromNotebook, getAllNotebooks } from '$lib/db/repositories';
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
import type { Page, Notebook } from '@ka-note/shared';
|
||||
import { currentScope, scopeSettings } from '$lib/stores/scopeContext';
|
||||
import { useUnsavedGuard } from '$lib/utils/unsavedGuard.svelte';
|
||||
const pageId = $derived($page.params.id);
|
||||
const pageId = $derived(page.params.id);
|
||||
let currentPage = $state<Page | undefined>(undefined);
|
||||
|
||||
const SCOPE_KEY = 'wiki-scope';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/state';
|
||||
import { goto } from '$app/navigation';
|
||||
import { liveQuery } from 'dexie';
|
||||
import { db } from '$lib/db/schema';
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
if ($notebook$) currentScope.set($notebook$.isPrivate ? 'private' : 'business');
|
||||
});
|
||||
|
||||
const notebookId = $derived($page.params.id);
|
||||
const notebookId = $derived(page.params.id);
|
||||
const notebook$ = liveQuery(() => db.notebooks.get(notebookId));
|
||||
const pages$ = pagesForNotebook(notebookId);
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue