- Created AeCompJournalEntryQuickAdd for high-velocity note creation - Extracted robust append/prepend logic from List View into AeCompModalJournalEntryAppend - Unified List and Detail views to use the shared modal for content manipulation - Added explicit Append/Prepend actions to Journal Entry settings menu - Updated TODO.md and Journals module documentation
197 lines
7.4 KiB
Svelte
197 lines
7.4 KiB
Svelte
<script lang="ts">
|
|
import { Modal } from 'flowbite-svelte';
|
|
import { Check, X } from '@lucide/svelte';
|
|
import { ae_util } from '$lib/ae_utils/ae_utils';
|
|
import { journals_func } from '$lib/ae_journals/ae_journals_functions';
|
|
import { ae_api } from '$lib/stores/ae_stores';
|
|
import type { key_val } from '$lib/stores/ae_stores';
|
|
|
|
interface Props {
|
|
open: boolean;
|
|
journal_entry: key_val;
|
|
journal_config: key_val; // The cfg_json from the journal object
|
|
mode?: 'append' | 'prepend' | 'auto';
|
|
onClose: () => void;
|
|
onUpdate: () => void;
|
|
log_lvl?: number;
|
|
}
|
|
|
|
let {
|
|
open = $bindable(false),
|
|
journal_entry,
|
|
journal_config,
|
|
mode = 'auto',
|
|
onClose,
|
|
onUpdate,
|
|
log_lvl = 0
|
|
}: Props = $props();
|
|
// Local State
|
|
let tmp_entry_obj: key_val = $state({});
|
|
|
|
// Header Options
|
|
let add_timestamp_header: boolean = $state(true);
|
|
let add_timestamp_header_w_day_of_week: boolean = $state(true);
|
|
let add_text_header: string = $state('');
|
|
let add_text: string = $state('');
|
|
|
|
// Change detection
|
|
let has_changes: boolean = $derived(add_text_header.length > 0 || add_text.length > 0);
|
|
|
|
// Initialize tmp object when entry changes or modal opens
|
|
$effect(() => {
|
|
if (open && journal_entry) {
|
|
tmp_entry_obj = JSON.parse(JSON.stringify(journal_entry));
|
|
// Reset fields
|
|
add_text_header = '';
|
|
add_text = '';
|
|
}
|
|
});
|
|
|
|
async function handle_save() {
|
|
let current_entry_content = tmp_entry_obj?.content || '';
|
|
let add_content = '';
|
|
let new_content = current_entry_content;
|
|
|
|
// Construct the header/content to add (Following original logic)
|
|
let timestamp_str = ae_util.iso_datetime_formatter(
|
|
new Date(),
|
|
'datetime_iso_12_no_seconds'
|
|
);
|
|
let day_of_week_str = add_timestamp_header_w_day_of_week
|
|
? ' (' + ae_util.iso_datetime_formatter(new Date(), 'week_long') + ')'
|
|
: '';
|
|
|
|
if (add_timestamp_header && add_text_header) {
|
|
add_content =
|
|
'## ' +
|
|
timestamp_str +
|
|
day_of_week_str +
|
|
' - ' +
|
|
add_text_header.trim() +
|
|
'\n' +
|
|
add_text.trim() +
|
|
'\n\n';
|
|
} else if (add_timestamp_header) {
|
|
add_content = '## ' + timestamp_str + day_of_week_str + '\n' + add_text.trim() + '\n\n';
|
|
} else if (add_text_header) {
|
|
add_content =
|
|
'## ' + add_text_header.trim() + day_of_week_str + '\n' + add_text.trim() + '\n\n';
|
|
} else {
|
|
add_content = add_text.trim() + '\n\n';
|
|
}
|
|
|
|
// Determine Append or Prepend
|
|
let effective_mode = mode;
|
|
if (effective_mode === 'auto') {
|
|
effective_mode = journal_config?.entry_add_text || 'append';
|
|
}
|
|
|
|
if (effective_mode == 'prepend') {
|
|
new_content = add_content + new_content;
|
|
} else {
|
|
// Append
|
|
new_content = new_content.trim() + '\n\n' + add_content;
|
|
}
|
|
|
|
new_content = new_content.trim() + '\n';
|
|
|
|
let data_kv = { content: new_content };
|
|
|
|
try {
|
|
let update_result = await journals_func.update_ae_obj__journal_entry({
|
|
api_cfg: $ae_api,
|
|
journal_entry_id: tmp_entry_obj?.journal_entry_id,
|
|
data_kv: data_kv,
|
|
log_lvl: log_lvl
|
|
});
|
|
|
|
if (update_result) {
|
|
// Success
|
|
onUpdate();
|
|
open = false;
|
|
} else {
|
|
alert('Failed to update journal entry.');
|
|
}
|
|
} catch (error) {
|
|
console.error('Error updating journal entry:', error);
|
|
alert('Failed to update journal entry.');
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<Modal
|
|
title="{(mode === 'auto' ? journal_config?.entry_add_text : mode) == 'append' ? 'Append to' : 'Prepend to'} Journal Entry: {journal_entry?.name ?? journal_entry?.created_on}"
|
|
bind:open={open}
|
|
autoclose={false}
|
|
placement="top-center"
|
|
size="xl"
|
|
class="top-center bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 rounded-lg border-gray-200 dark:border-gray-700 divide-gray-200 dark:divide-gray-700 shadow-md relative flex flex-col gap-1 mx-auto w-full"
|
|
>
|
|
<div class="modal">
|
|
<div class="modal-box">
|
|
<div class="flex flex-col gap-1">
|
|
<!-- Checkbox Options -->
|
|
<div>
|
|
<input
|
|
type="checkbox"
|
|
id="append_timestamp_header"
|
|
bind:checked={add_timestamp_header}
|
|
class="p-2 bg-slate-100 text-gray-900 dark:bg-slate-900 dark:text-gray-100 shadow-lg rounded-lg border border-gray-200 dark:border-gray-700 hover:border-gray-500 dark:hover:border-gray-500 inline-block"
|
|
/>
|
|
<label for="append_timestamp_header" class="p-2 inline-block">
|
|
Use timestamp as Markdown header
|
|
</label>
|
|
|
|
<input
|
|
type="checkbox"
|
|
id="append_timestamp_header_w_day_of_week"
|
|
bind:checked={add_timestamp_header_w_day_of_week}
|
|
class="p-2 bg-slate-100 text-gray-900 dark:bg-slate-900 dark:text-gray-100 shadow-lg rounded-lg border border-gray-200 dark:border-gray-700 hover:border-gray-500 dark:hover:border-gray-500 inline-block"
|
|
/>
|
|
<label for="append_timestamp_header_w_day_of_week" class="p-2 inline-block">
|
|
Include day of week
|
|
</label>
|
|
</div>
|
|
|
|
<!-- Text Header Input -->
|
|
<input
|
|
type="text"
|
|
placeholder="Markdown header for content (Optional)"
|
|
bind:value={add_text_header}
|
|
class="grow min-h-12 h-full w-full p-2 bg-slate-100 text-gray-900 dark:bg-slate-900 dark:text-gray-100 shadow-lg rounded-lg border border-gray-200 dark:border-gray-700 hover:border-gray-500 dark:hover:border-gray-500"
|
|
/>
|
|
|
|
<!-- Main Content Area -->
|
|
<textarea
|
|
bind:value={add_text}
|
|
class="grow min-h-48 h-full w-full p-2 bg-slate-100 text-gray-900 dark:bg-slate-900 dark:text-gray-100 shadow-lg rounded-lg border border-gray-200 dark:border-gray-700 hover:border-gray-500 dark:hover:border-gray-500"
|
|
placeholder="Content to {mode === 'auto'
|
|
? journal_config?.entry_add_text
|
|
: mode}...">
|
|
</textarea>
|
|
</div>
|
|
|
|
<div class="modal-action flex justify-end gap-2 mt-4">
|
|
<button
|
|
type="button"
|
|
disabled={!has_changes}
|
|
onclick={handle_save}
|
|
class="btn btn-sm md:btn-md lg:btn-lg min-w-32 hover:variant-outline-success hover:preset-filled-success-500"
|
|
class:preset-filled-primary-500={has_changes}
|
|
class:preset-filled-surface-500={!has_changes}
|
|
>
|
|
<Check class="mr-1" />
|
|
Update
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onclick={onClose}
|
|
class="btn preset-tonal-surface border border-surface-500 hover:preset-filled-surface-500 transition"
|
|
>
|
|
<X class="mr-1" />
|
|
Cancel
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Modal> |