Applied consistent code formatting across the project using Prettier, now configured to use 4-space indentation instead of tabs.
333 lines
14 KiB
Svelte
333 lines
14 KiB
Svelte
<script lang="ts">
|
||
// *** Import Svelte specific
|
||
import { goto } from '$app/navigation';
|
||
|
||
// *** Import other supporting libraries
|
||
import { BookPlus, BookOpenText, FilePlus, Menu, Pencil } from '@lucide/svelte';
|
||
|
||
// *** Import Aether specific variables and functions
|
||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||
import {
|
||
ae_snip,
|
||
ae_loc,
|
||
ae_sess,
|
||
ae_api,
|
||
ae_trig,
|
||
slct,
|
||
slct_trigger
|
||
} from '$lib/stores/ae_stores';
|
||
import {
|
||
journals_loc,
|
||
journals_sess,
|
||
journals_slct,
|
||
journals_trig,
|
||
journals_prom
|
||
} from '$lib/ae_journals/ae_journals_stores';
|
||
import { journals_func } from '$lib/ae_journals/ae_journals_functions';
|
||
|
||
interface Props {
|
||
log_lvl?: number;
|
||
lq__journal_obj: any;
|
||
lq__journal_entry_obj_li: any;
|
||
}
|
||
|
||
let { log_lvl = 0, lq__journal_obj, lq__journal_entry_obj_li }: Props = $props();
|
||
|
||
// let ae_promises: key_val = {};
|
||
// let ae_tmp: key_val = {};
|
||
// let ae_trigger: any = null;
|
||
// let ae_triggers: key_val = {};
|
||
|
||
let show_menu: boolean = $state(false);
|
||
let typed_journal_passcode: string = $state('');
|
||
let passcode_timer: any = $state(null);
|
||
|
||
$effect(() => {
|
||
if (typed_journal_passcode?.length > 4) {
|
||
if (!$journals_sess?.journal_kv) {
|
||
$journals_sess.journal_kv = {};
|
||
}
|
||
if (!$journals_sess.journal_kv[$lq__journal_obj?.id]) {
|
||
$journals_sess.journal_kv[$lq__journal_obj?.id] = {};
|
||
}
|
||
|
||
verify_journal_passcode();
|
||
}
|
||
|
||
// We need to set a timeout to force the user to re-enter their private passcode
|
||
if (
|
||
$lq__journal_obj?.id &&
|
||
$journals_sess?.journal_kv[$lq__journal_obj?.id] &&
|
||
$journals_sess?.journal_kv[$lq__journal_obj?.id]?.journal_passcode_verified
|
||
) {
|
||
if (passcode_timer) {
|
||
if (log_lvl) {
|
||
console.log('Passcode timer already set');
|
||
}
|
||
return;
|
||
}
|
||
console.log('Setting passcode timer');
|
||
passcode_timer = setTimeout(
|
||
() => {
|
||
if (log_lvl) {
|
||
console.log('Passcode timer expired');
|
||
}
|
||
typed_journal_passcode = '';
|
||
if (!$journals_sess?.journal_kv[$lq__journal_obj?.id]) {
|
||
$journals_sess.journal_kv[$lq__journal_obj?.id] = {};
|
||
}
|
||
$journals_sess.journal_kv[$lq__journal_obj?.id].journal_passcode_verified =
|
||
false;
|
||
},
|
||
1000 * 60 * 1
|
||
); // 1 minutes
|
||
// }, 1000 * $lq__journal_obj?.passcode_timeout); // 5 minutes
|
||
}
|
||
});
|
||
|
||
function verify_journal_passcode() {
|
||
if (log_lvl) {
|
||
console.log(
|
||
`verify_journal_passcode: typed_journal_passcode = ${typed_journal_passcode} journal private passcode = ${$lq__journal_obj?.private_passcode}`
|
||
);
|
||
}
|
||
|
||
if (typed_journal_passcode === $lq__journal_obj?.private_passcode) {
|
||
console.log('Matched journal private passcode');
|
||
if (!$journals_sess?.journal_kv[$lq__journal_obj?.id]) {
|
||
$journals_sess.journal_kv[$lq__journal_obj?.id] = {};
|
||
}
|
||
$journals_sess.journal_kv[$lq__journal_obj?.id] = {
|
||
typed_journal_passcode: typed_journal_passcode,
|
||
journal_passcode_verified: true
|
||
};
|
||
|
||
typed_journal_passcode = '';
|
||
} else {
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<section
|
||
class="
|
||
rounded-lg p-2 m-2 w-full
|
||
flex flex-col flex-wrap items-center justify-center
|
||
bg-{$lq__journal_obj?.cfg_json.color_scheme}-100
|
||
text-gray-900 dark:text-gray-900
|
||
"
|
||
bind:clientHeight={$ae_loc.iframe_height_modal_body}
|
||
>
|
||
<header
|
||
class="ae_header journal__header flex flex-row flex-wrap gap-2 items-center justify-between w-full"
|
||
>
|
||
<h2 class="journal__name h3 text-center">
|
||
<BookOpenText class="inline-block text-neutral-800/60" />
|
||
{@html $lq__journal_obj?.name ?? 'Loading...'}
|
||
{#if $ae_loc.trusted_access && $ae_loc.edit_mode}
|
||
({$lq__journal_entry_obj_li?.length ?? '0'}×)
|
||
{/if}
|
||
{#await $journals_prom.load__journal_entry_obj_li}
|
||
<span class="fas fa-spinner fa-spin"></span>
|
||
{:then}
|
||
<!-- done -->
|
||
{/await}
|
||
</h2>
|
||
|
||
<div class="grow flex flex-row flex-wrap gap-2 items-center justify-end">
|
||
<section class="relative transition-all">
|
||
<!-- Menu Button -->
|
||
<button
|
||
type="button"
|
||
onclick={() => (show_menu = !show_menu)}
|
||
class="
|
||
btn
|
||
variant-outline-secondary hover:preset-filled-secondary-400-600
|
||
py-1 px-2 w-24
|
||
transition-all
|
||
"
|
||
title="Toggle menu"
|
||
>
|
||
<Menu size="1.5em" class="inline-block" />
|
||
<span class="hidden md:inline">Menu</span>
|
||
</button>
|
||
|
||
<!-- Menu -->
|
||
<!-- {#if show_menu} -->
|
||
<div
|
||
class="
|
||
absolute top-12 right-0
|
||
p-4 z-50 w-80
|
||
space-y-0.5
|
||
bg-white dark:bg-gray-800
|
||
border border-gray-500
|
||
shadow-xl rounded-lg
|
||
min-w-72
|
||
max-w-fit
|
||
"
|
||
class:hidden={!show_menu}
|
||
>
|
||
<div
|
||
class="
|
||
flex flex-row flex-wrap items-center justify-evenly gap-2 w-full
|
||
"
|
||
>
|
||
<span class="text-sm text-gray-500">
|
||
<span class="fas fa-info-circle text-blue-500"></span>
|
||
Journal ID: {$lq__journal_obj?.id}
|
||
</span>
|
||
<button
|
||
type="button"
|
||
onclick={() => {
|
||
// $journals_sess.show__modal_new__journal_entry_obj = true
|
||
// log_lvl = 3;
|
||
|
||
let data_kv = {
|
||
category_code: null
|
||
};
|
||
if ($journals_loc.qry__category_code) {
|
||
data_kv.category_code = $journals_loc.qry__category_code;
|
||
}
|
||
if (log_lvl) {
|
||
console.log(
|
||
'Creating new journal entry with data_kv:',
|
||
data_kv
|
||
);
|
||
}
|
||
journals_func
|
||
.create_ae_obj__journal_entry({
|
||
api_cfg: $ae_api,
|
||
journal_id: $lq__journal_obj?.journal_id,
|
||
data_kv: data_kv,
|
||
log_lvl: log_lvl
|
||
})
|
||
.then((results) => {
|
||
if (log_lvl) {
|
||
console.log('New journal entry created:', results);
|
||
}
|
||
$journals_slct.journal_entry_id =
|
||
results?.journal_entry_id_random;
|
||
// $journals_loc.entry.edit = true;
|
||
$journals_loc.entry.edit_kv[
|
||
$journals_slct.journal_entry_id
|
||
] = 'current';
|
||
// alert(`Journal entry created successfully! ${$journals_slct.journal_entry_id}`);
|
||
})
|
||
.catch((error) => {
|
||
console.error('Error updating journal entry:', error);
|
||
alert('Failed to update journal entry.');
|
||
})
|
||
.finally(() => {
|
||
if ($journals_slct.journal_entry_id) {
|
||
goto(
|
||
`/journals/${$lq__journal_obj?.journal_id}/entry/${$journals_slct.journal_entry_id}`
|
||
);
|
||
} else {
|
||
alert('Failed to create new journal entry.');
|
||
}
|
||
});
|
||
}}
|
||
class="
|
||
btn btn-sm
|
||
preset-tonal-secondary border border-secondary-500
|
||
hover:preset-filled-secondary-500
|
||
transition
|
||
"
|
||
title="Create a new journal entry for this journal: {$lq__journal_obj?.name}"
|
||
>
|
||
<FilePlus />
|
||
<!-- <span class="fas fa-plus m-1"></span> -->
|
||
<span class="hidden sm:inline"> New Journal Entry </span>
|
||
</button>
|
||
|
||
<button
|
||
type="button"
|
||
onclick={() => {
|
||
$journals_slct.tmp_journal_obj = {
|
||
name: $lq__journal_obj?.name,
|
||
description: $lq__journal_obj?.description,
|
||
type_code: $lq__journal_obj?.type_code,
|
||
passcode: $lq__journal_obj?.passcode,
|
||
passcode_timeout: $lq__journal_obj?.passcode_timeout,
|
||
auth_key: $lq__journal_obj?.auth_key,
|
||
cfg_json: $lq__journal_obj?.cfg_json
|
||
};
|
||
$journals_sess.show__modal_edit__journal_obj = true;
|
||
}}
|
||
class:hidden={!$ae_loc.edit_mode}
|
||
class="
|
||
btn btn-sm
|
||
preset-tonal-warning border border-warning-500
|
||
hover:preset-filled-warning-500
|
||
transition
|
||
"
|
||
title="Edit Journal meta and configuration (name, type, passcode, categories, etc.: {$lq__journal_obj?.name})"
|
||
>
|
||
<Pencil />
|
||
<span class="hidden md:inline"> Edit Journal </span>
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Set Journal private_passcode (string) -->
|
||
<!-- The Journal private_passcode will be used along with the Journal passcode to encrypt the journal entries. -->
|
||
<input
|
||
type="text"
|
||
bind:value={typed_journal_passcode}
|
||
placeholder="Journal passcode"
|
||
onchange={() => {
|
||
// console.log('HERE');
|
||
// verify_journal_passcode();
|
||
}}
|
||
class="input input-sm input-bordered w-full mb-2"
|
||
title="Enter private passcode of this journal"
|
||
/>
|
||
|
||
{#if $journals_sess?.journal_kv[$lq__journal_obj?.id]?.journal_passcode_verified}
|
||
<div class="text-sm text-gray-500">
|
||
<span class="fas fa-check-circle text-green-500"></span>
|
||
Journal passcode verified
|
||
</div>
|
||
{:else}
|
||
<div class="text-sm text-gray-500">
|
||
<span class="fas fa-exclamation-circle text-red-500"></span>
|
||
Journal passcode not verified {$lq__journal_obj?.private_passcode ??
|
||
'??'}
|
||
</div>
|
||
{/if}
|
||
</div>
|
||
<!-- {/if} -->
|
||
</section>
|
||
</div>
|
||
</header>
|
||
|
||
<!-- Show Journal description -->
|
||
<!-- class:bg-green-100={$lq__journal_obj?.cfg_json.color_scheme ?? 'green'} -->
|
||
<!-- prose-h1:text-gray-100 dark:prose-h1:text-gray-900 -->
|
||
<!-- <div> -->
|
||
{#if $lq__journal_obj?.description && $ae_loc.edit_mode}
|
||
<div
|
||
class="
|
||
prose
|
||
space-y-1
|
||
p-2
|
||
w-full max-w-(--breakpoint-sm) md:max-w-(--breakpoint-md)
|
||
font-mono
|
||
text-gray-900
|
||
dark:bg-blue-900/40 dark:text-gray-100
|
||
shadow-md rounded-lg
|
||
text-sm font-normal text-wrap word-break
|
||
|
||
prose-p:m-0 prose-p:p-0
|
||
prose-h1:underline prose-h1:decoration-double
|
||
prose-h2:underline
|
||
prose-h1:text-2xl prose-h2:text-xl prose-h3:text-lg
|
||
prose-h1:m-0 prose-h2:m-0 prose-h3:m-0 prose-h4:m-0 prose-h5:m-0 prose-h6:m-0
|
||
|
||
prose-li:m-0 prose-li:p-0 prose-li:line-height-none
|
||
"
|
||
>
|
||
{@html $lq__journal_obj.description_md_html}
|
||
</div>
|
||
{/if}
|
||
<!-- </div> -->
|
||
</section>
|