style(journals): stabilize and standardize all configuration interfaces

- Implemented 'untrack' safeguards in all modal effect blocks to prevent reactivity loops.
- Standardized Module, Journal, and Entry configuration with unified tabbed UI and Aether Orange theme.
- Fixed critical 'journal is undefined' and ReferenceErrors in configuration modals.
- Restored missing button toggles and visibility options in journal-level settings.
- Documented Dexie liveQuery '$' prefix mandate in GEMINI.md and project documentation.
- Eliminated legacy JournalEntry_SettingsMenu in favor of ModalJournalEntryConfig.
This commit is contained in:
Scott Idem
2026-01-14 17:50:48 -05:00
parent 8ae23cdcd9
commit cdf318e744
8 changed files with 238 additions and 316 deletions

View File

@@ -2,17 +2,14 @@
/**
* ae_comp__journal_obj_id_edit.svelte
* Standardized Journal-level configuration.
* Restored missing visibility and button toggles.
*/
import {
CalendarClock,
Check,
Settings,
X,
Database,
CodeXml,
ShieldCheck,
BookOpenText,
MousePointerClick,
Trash2,
Fingerprint,
LockKeyhole,
@@ -20,13 +17,28 @@
Minus,
Palette,
MonitorPlay,
Layout
Layout,
Eye,
EyeOff,
Siren,
MessageSquareWarning,
Copy,
FilePlus,
Globe,
BookHeart,
BriefcaseBusiness,
Target,
Expand,
BetweenVerticalEnd,
BetweenVerticalStart,
X,
Settings
} from '@lucide/svelte';
import { Modal } from 'flowbite-svelte';
import { goto } from '$app/navigation';
import { untrack } from 'svelte';
// *** Import Aether specific variables and functions
import type { key_val } from '$lib/stores/ae_stores';
import {
ae_loc,
ae_api
@@ -57,8 +69,15 @@
// Deep copy on mount or when lq changes to ensure we have a working copy
$effect(() => {
if (show && lq__journal_obj && !tmp__journal_obj.journal_id) {
tmp__journal_obj = JSON.parse(JSON.stringify(lq__journal_obj));
if (show && lq__journal_obj) {
const source_id = lq__journal_obj.journal_id;
untrack(() => {
if (!tmp__journal_obj.journal_id || tmp__journal_obj.journal_id !== source_id) {
tmp__journal_obj = JSON.parse(JSON.stringify(lq__journal_obj));
// Ensure cfg_json exists
if (!tmp__journal_obj.cfg_json) tmp__journal_obj.cfg_json = {};
}
});
}
});
@@ -69,26 +88,10 @@
}
try {
const data_kv = {
name: tmp__journal_obj.name,
description: tmp__journal_obj.description ?? '',
type_code: tmp__journal_obj.type_code,
passcode: tmp__journal_obj.passcode,
private_passcode: tmp__journal_obj.private_passcode,
passcode_timeout: tmp__journal_obj.passcode_timeout,
auth_key: tmp__journal_obj.auth_key,
cfg_json: tmp__journal_obj.cfg_json,
group: tmp__journal_obj.group,
sort: tmp__journal_obj.sort,
hide: tmp__journal_obj.hide,
enable: tmp__journal_obj.enable,
priority: tmp__journal_obj.priority
};
await journals_func.update_ae_obj__journal({
api_cfg: $ae_api,
journal_id: lq__journal_obj?.journal_id,
data_kv: data_kv,
data_kv: tmp__journal_obj,
log_lvl: log_lvl
});
show = false;
@@ -128,11 +131,11 @@
{#snippet header()}
<h3 class="flex items-center gap-2 text-lg font-bold">
<BookOpenText class="text-primary-500" />
<span>Edit Journal: {lq__journal_obj?.name ?? '--'}</span>
<span>Edit Journal: {$lq__journal_obj?.name ?? '--'}</span>
</h3>
{/snippet}
<div class="space-y-6 py-2 h-[70vh] overflow-y-auto px-4">
<div class="space-y-6 py-2 h-[75vh] overflow-y-auto px-4">
<!-- Navigation Tabs -->
<div class="flex justify-center gap-1 mb-4 p-1 bg-surface-500/10 rounded-lg max-w-fit mx-auto sticky top-0 z-10 backdrop-blur-sm">
<button class="btn btn-sm transition-all {tab === 'general' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'general')}>
@@ -180,10 +183,10 @@
<!-- Categories -->
<section class="space-y-4 p-2">
<h2 class="text-lg font-bold flex items-center gap-2 border-b border-surface-500/30 pb-2">
<Settings size="1em" class="text-primary-500" />
<MonitorPlay size="1em" class="text-primary-500" />
Journal Categories
</h2>
<div class="space-y-2 bg-surface-500/5 p-4 rounded-lg">
<div class="space-y-2 bg-surface-500/5 p-4 rounded-lg border border-surface-500/10">
{#each tmp__journal_obj?.cfg_json?.category_li ?? [] as category, i}
<div class="flex gap-2 items-center">
<input type="text" bind:value={category.code} class="input input-sm w-32" placeholder="Code" />
@@ -210,7 +213,7 @@
<LockKeyhole size="1.2em" class="text-primary-500" />
Encryption Passcodes
</h2>
<div class="bg-warning-500/10 border border-warning-500/30 p-4 rounded-lg space-y-4">
<div class="bg-warning-500/10 border border-warning-500/30 p-4 rounded-lg space-y-4 shadow-inner">
<label class="label">
<span class="text-xs font-bold uppercase tracking-wider opacity-70">Primary Passcode (Stored)</span>
<div class="flex gap-2">
@@ -236,25 +239,27 @@
<Fingerprint size="1.2em" class="text-primary-500" />
Status & Lifecycle
</h2>
<div class="grid grid-cols-2 gap-4">
<label class="flex items-center space-x-3 cursor-pointer p-3 rounded-lg bg-surface-500/5 border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.enable} class="checkbox" />
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<label class="flex items-center space-x-3 cursor-pointer p-3 rounded-lg bg-surface-500/5 border border-surface-500/10 transition-colors hover:bg-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.enable} class="checkbox checkbox-primary" />
<span class="font-bold">Enabled</span>
</label>
<label class="flex items-center space-x-3 cursor-pointer p-3 rounded-lg bg-surface-500/5 border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.hide} class="checkbox" />
<label class="flex items-center space-x-3 cursor-pointer p-3 rounded-lg bg-surface-500/5 border border-surface-500/10 transition-colors hover:bg-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.hide} class="checkbox checkbox-primary" />
<span class="font-bold">Hidden</span>
</label>
<label class="flex items-center space-x-3 cursor-pointer p-3 rounded-lg bg-surface-500/5 border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.priority} class="checkbox" />
<label class="flex items-center space-x-3 cursor-pointer p-3 rounded-lg bg-surface-500/5 border border-surface-500/10 transition-colors hover:bg-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.priority} class="checkbox checkbox-primary" />
<span class="font-bold">Priority Journal</span>
</label>
</div>
</section>
<button class="btn btn-sm variant-filled-error w-full mt-12" onclick={delete_journal}>
<Trash2 size="1.1em" class="mr-2" /> Delete Entire Journal
</button>
<section class="pt-8">
<button class="btn btn-sm variant-filled-error w-full shadow-lg" onclick={delete_journal}>
<Trash2 size="1.1em" class="mr-2" /> Delete Entire Journal
</button>
</section>
</div>
{:else if tab === 'ui'}
@@ -262,9 +267,9 @@
<section class="space-y-4 p-2">
<h2 class="text-lg font-bold flex items-center gap-2 border-b border-surface-500/30 pb-2">
<MonitorPlay size="1.2em" class="text-primary-500" />
Editor & Viewer
Default View Modes
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 bg-surface-500/5 p-4 rounded-lg border border-surface-500/10">
<label class="label">
<span class="text-sm font-bold opacity-70">Preferred Viewer</span>
<select bind:value={tmp__journal_obj.cfg_json.pref_viewer} class="select variant-form-material">
@@ -280,25 +285,126 @@
<option value="codemirror">CodeMirror (Advanced)</option>
</select>
</label>
<label class="label">
<span class="text-sm font-bold opacity-70">Color Scheme</span>
<select bind:value={tmp__journal_obj.cfg_json.color_scheme} class="select variant-form-material">
<option value="">Default (Slate)</option>
<option value="blue">Deep Blue</option>
<option value="green">Nature Green</option>
<option value="orange">Aether Orange</option>
<option value="red">Warning Red</option>
<option value="yellow">Caution Yellow</option>
</select>
</label>
<label class="label">
<span class="text-sm font-bold opacity-70">Quick Add Placement</span>
<select bind:value={tmp__journal_obj.cfg_json.entry_add_text} class="select variant-form-material">
<option value="append">Append to End (Default)</option>
<option value="prepend">Prepend to Start</option>
</select>
</label>
</div>
</section>
<!-- Visibility Toggles (Restored) -->
<section class="space-y-4 p-2">
<h2 class="text-lg font-bold flex items-center gap-2 border-b border-surface-500/30 pb-2">
<Eye size="1.2em" class="text-primary-500" />
Entry Visibility (Global)
</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
<label class="flex items-center space-x-2 cursor-pointer p-2 bg-surface-500/5 rounded border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.cfg_json.hide_private} class="checkbox checkbox-sm" />
<span class="text-xs font-bold">Hide Private</span>
</label>
<label class="flex items-center space-x-2 cursor-pointer p-2 bg-surface-500/5 rounded border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.cfg_json.hide_personal} class="checkbox checkbox-sm" />
<span class="text-xs font-bold">Hide Personal</span>
</label>
<label class="flex items-center space-x-2 cursor-pointer p-2 bg-surface-500/5 rounded border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.cfg_json.hide_professional} class="checkbox checkbox-sm" />
<span class="text-xs font-bold">Hide Professional</span>
</label>
</div>
</section>
<!-- Button Toggles (Restored) -->
<section class="space-y-4 p-2">
<h2 class="text-lg font-bold flex items-center gap-2 border-b border-surface-500/30 pb-2">
<Settings size="1.2em" class="text-primary-500" />
Entry Feature Buttons
</h2>
<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-2">
<label class="flex items-center gap-2 p-2 bg-surface-500/5 rounded border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.cfg_json.hide_btn_alert} class="checkbox checkbox-sm" />
<span class="text-[10px] uppercase font-bold">Hide Alert</span>
</label>
<label class="flex items-center gap-2 p-2 bg-surface-500/5 rounded border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.cfg_json.hide_btn_private} class="checkbox checkbox-sm" />
<span class="text-[10px] uppercase font-bold">Hide Private</span>
</label>
<label class="flex items-center gap-2 p-2 bg-surface-500/5 rounded border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.cfg_json.hide_btn_public} class="checkbox checkbox-sm" />
<span class="text-[10px] uppercase font-bold">Hide Public</span>
</label>
<label class="flex items-center gap-2 p-2 bg-surface-500/5 rounded border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.cfg_json.hide_btn_personal} class="checkbox checkbox-sm" />
<span class="text-[10px] uppercase font-bold">Hide Pers.</span>
</label>
<label class="flex items-center gap-2 p-2 bg-surface-500/5 rounded border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.cfg_json.hide_btn_professional} class="checkbox checkbox-sm" />
<span class="text-[10px] uppercase font-bold">Hide Prof.</span>
</label>
<label class="flex items-center gap-2 p-2 bg-surface-500/5 rounded border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.cfg_json.hide_btn_template} class="checkbox checkbox-sm" />
<span class="text-[10px] uppercase font-bold">Hide Templ.</span>
</label>
<label class="flex items-center gap-2 p-2 bg-surface-500/5 rounded border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.cfg_json.hide_copy_plain_md} class="checkbox checkbox-sm" />
<span class="text-[10px] uppercase font-bold">Hide Copy MD</span>
</label>
<label class="flex items-center gap-2 p-2 bg-surface-500/5 rounded border border-surface-500/10">
<input type="checkbox" bind:checked={tmp__journal_obj.cfg_json.hide_clone} class="checkbox checkbox-sm" />
<span class="text-[10px] uppercase font-bold">Hide Clone</span>
</label>
</div>
</section>
<section class="space-y-4 p-2">
<h2 class="text-lg font-bold flex items-center gap-2 border-b border-surface-500/30 pb-2">
<Palette size="1.2em" class="text-primary-500" />
Visual Theme
<Layout size="1.2em" class="text-primary-500" />
List Interactions
</h2>
<label class="label">
<span class="text-sm font-bold opacity-70">Color Scheme</span>
<select bind:value={tmp__journal_obj.cfg_json.color_scheme} class="select variant-form-material">
<option value="">Default (Slate)</option>
<option value="blue">Deep Blue</option>
<option value="green">Nature Green</option>
<option value="orange">Aether Orange</option>
<option value="red">Warning Red</option>
<option value="yellow">Caution Yellow</option>
</select>
</label>
<div class="bg-surface-500/5 p-4 rounded-lg space-y-4">
<label class="label">
<span class="text-xs font-bold opacity-70">Expansion Trigger</span>
<select bind:value={tmp__journal_obj.cfg_json.expand_li_content} class="select select-sm variant-form-material">
<option value="click">Click to Expand</option>
<option value="hover">Hover to Expand</option>
</select>
</label>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
<label class="label">
<span class="text-xs font-bold opacity-70">List Max Height</span>
<select bind:value={tmp__journal_obj.cfg_json.entry_li_max_height} class="select select-sm variant-form-material">
<option value="">Default</option>
<option value="max-h-16">Small (16)</option>
<option value="max-h-32">Medium (32)</option>
<option value="max-h-64">Large (64)</option>
<option value="max-h-full">Full</option>
</select>
</label>
<label class="label">
<span class="text-xs font-bold opacity-70">Active Max Height</span>
<select bind:value={tmp__journal_obj.cfg_json.entry_li_click_max_height} class="select select-sm variant-form-material">
<option value="">Default</option>
<option value="active:max-h-64">Large (64)</option>
<option value="active:max-h-96">X-Large (96)</option>
<option value="active:max-h-full">Full</option>
</select>
</label>
</div>
</div>
</section>
</div>