138 lines
4.1 KiB
Svelte
138 lines
4.1 KiB
Svelte
<script lang="ts">
|
|
import { liveQuery } from 'dexie';
|
|
import { db } from '$lib/db/schema';
|
|
import { resolveWiedervorlage, setWiedervorlage, convertToTopic, softDeleteHistoryEntry } from '$lib/db/repositories';
|
|
import type { HistoryEntry } from '@ka-note/shared';
|
|
import RenderedMarkdown from './RenderedMarkdown.svelte';
|
|
|
|
function truncateUrlDisplay(text: string): string {
|
|
if (!/^https?:\/\//i.test(text)) return text;
|
|
try {
|
|
const u = new URL(text);
|
|
const path = u.pathname !== '/' ? u.pathname : '';
|
|
const display = u.hostname + path;
|
|
return display.length > 60 ? display.slice(0, 57) + '…' : display;
|
|
} catch {
|
|
return text.length > 60 ? text.slice(0, 57) + '…' : text;
|
|
}
|
|
}
|
|
|
|
interface Props {
|
|
entry: HistoryEntry;
|
|
}
|
|
let { entry }: Props = $props();
|
|
|
|
let showVerschieben = $state(false);
|
|
let newDate = $state('');
|
|
let showConvert = $state(false);
|
|
let selectedContextId = $state('');
|
|
|
|
const meetingContexts = liveQuery(() =>
|
|
db.contexts
|
|
.filter(c => !c.deletedAt && c.type === 'meeting' && c.id !== 'daily-log')
|
|
.sortBy('sortOrder')
|
|
);
|
|
|
|
const lines = $derived(entry.text.split('\n'));
|
|
const title = $derived(lines[0]);
|
|
const body = $derived(lines.slice(1).join('\n').trim());
|
|
|
|
async function handleOk() {
|
|
await resolveWiedervorlage(entry.id);
|
|
}
|
|
|
|
async function handleDelete() {
|
|
await softDeleteHistoryEntry(entry.id);
|
|
}
|
|
|
|
async function handleVerschieben() {
|
|
if (!newDate) return;
|
|
await setWiedervorlage(entry.id, newDate);
|
|
showVerschieben = false;
|
|
newDate = '';
|
|
}
|
|
|
|
async function handleConvert() {
|
|
if (!selectedContextId) return;
|
|
await convertToTopic(entry.id, selectedContextId);
|
|
showConvert = false;
|
|
selectedContextId = '';
|
|
}
|
|
</script>
|
|
|
|
<div class="mb-3 rounded-lg border border-amber-500/60 bg-amber-950/30 p-3">
|
|
<div class="mb-2 flex items-start gap-2">
|
|
<span class="text-xs font-semibold uppercase tracking-wider text-amber-400">⏰ Wiedervorlage {entry.wiedervorlageDate}</span>
|
|
</div>
|
|
<div class="mb-3">
|
|
<div class="font-bold text-white">
|
|
{#if /^https?:\/\//i.test(title)}
|
|
<a href={title} target="_blank" rel="noopener noreferrer" class="text-blue-400 hover:underline">{truncateUrlDisplay(title)}</a>
|
|
{:else}
|
|
{title}
|
|
{/if}
|
|
</div>
|
|
{#if body}
|
|
<RenderedMarkdown text={body} class="mt-1 text-sm text-[#ccc]" />
|
|
{/if}
|
|
</div>
|
|
|
|
{#if showVerschieben}
|
|
<div class="mb-2 flex items-center gap-2">
|
|
<input
|
|
type="date"
|
|
class="rounded border border-[#444] bg-bg px-2 py-1 text-sm text-white"
|
|
bind:value={newDate}
|
|
/>
|
|
<button
|
|
class="rounded bg-amber-600 px-3 py-1 text-sm font-bold text-white hover:brightness-110"
|
|
onclick={handleVerschieben}
|
|
>OK</button>
|
|
<button
|
|
class="rounded bg-[#444] px-3 py-1 text-sm text-white hover:bg-[#555]"
|
|
onclick={() => showVerschieben = false}
|
|
>Abbrechen</button>
|
|
</div>
|
|
{:else if showConvert}
|
|
<div class="mb-2 flex items-center gap-2">
|
|
<select
|
|
class="flex-1 rounded border border-[#444] bg-bg px-2 py-1 text-sm text-white"
|
|
bind:value={selectedContextId}
|
|
>
|
|
<option value="">— Kontext wählen —</option>
|
|
{#each $meetingContexts ?? [] as ctx}
|
|
<option value={ctx.id}>{ctx.name}</option>
|
|
{/each}
|
|
</select>
|
|
<button
|
|
class="rounded bg-accent px-3 py-1 text-sm font-bold text-white hover:brightness-110"
|
|
onclick={handleConvert}
|
|
disabled={!selectedContextId}
|
|
>Erstellen</button>
|
|
<button
|
|
class="rounded bg-[#444] px-3 py-1 text-sm text-white hover:bg-[#555]"
|
|
onclick={() => showConvert = false}
|
|
>Abbrechen</button>
|
|
</div>
|
|
{:else}
|
|
<div class="flex gap-2">
|
|
<button
|
|
class="rounded bg-green-700 px-3 py-1 text-sm font-bold text-white hover:brightness-110"
|
|
onclick={handleOk}
|
|
>Ok</button>
|
|
<button
|
|
class="rounded bg-amber-700 px-3 py-1 text-sm text-white hover:brightness-110"
|
|
onclick={() => showVerschieben = true}
|
|
>Verschieben</button>
|
|
<button
|
|
class="rounded bg-[#444] px-3 py-1 text-sm text-white hover:bg-[#555]"
|
|
onclick={() => showConvert = true}
|
|
>In Thema wandeln</button>
|
|
<button
|
|
class="ml-auto rounded bg-red-900/60 px-3 py-1 text-sm text-red-300 hover:bg-red-800"
|
|
onclick={handleDelete}
|
|
>Löschen</button>
|
|
</div>
|
|
{/if}
|
|
</div>
|