Progress on moving must buttons and secondary things to the Journal Entry menu.
This commit is contained in:
@@ -51,6 +51,9 @@ let ae_promises: key_val = $state({});
|
||||
// let ae_trigger: any = null;
|
||||
// let ae_triggers: key_val = {};
|
||||
|
||||
let show_menu: boolean = $state(false);
|
||||
|
||||
|
||||
// let orig_entry_obj: key_val = $state({});
|
||||
let orig_entry_obj: key_val|null = $state({});
|
||||
let tmp_entry_obj_changed: boolean = $state(false);
|
||||
@@ -168,6 +171,7 @@ async function update_journal_entry() {
|
||||
history: tmp_entry_obj?.history,
|
||||
history_encrypted: null, // This should only be generated below.
|
||||
|
||||
sort: tmp_entry_obj?.sort,
|
||||
group: tmp_entry_obj?.group,
|
||||
archive_on: tmp_entry_obj?.archive_on,
|
||||
name: tmp_entry_obj?.name,
|
||||
@@ -611,7 +615,7 @@ function handle_cut_string(old_string: string) {
|
||||
|
||||
<header class="ae_header journal_entry__header flex flex-row flex-wrap gap-2 items-center justify-between w-full">
|
||||
|
||||
<div class="flex flex-row flex-wrap gap-2 items-center justify-start">
|
||||
<div class="flex-grow flex flex-row flex-wrap gap-2 items-center justify-start outline">
|
||||
<!-- Toggle edit for journal entry -->
|
||||
<button
|
||||
type="button"
|
||||
@@ -670,130 +674,10 @@ function handle_cut_string(old_string: string) {
|
||||
</span>
|
||||
|
||||
</h2>
|
||||
|
||||
<span class="flex flex-row flex-wrap gap-2 items-center justify-start">
|
||||
<!-- Button to copy the Markdown version -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
navigator.clipboard.writeText(tmp_entry_obj.content).then(() => {
|
||||
alert('Markdown content copied to clipboard!');
|
||||
}).catch((error) => {
|
||||
console.error('Failed to copy content:', error);
|
||||
alert('Failed to copy content.');
|
||||
});
|
||||
}}
|
||||
class="btn btn-sm p-1 variant-soft-secondary *:hover:inline lg:text-xs"
|
||||
title="Copy the markdown content"
|
||||
>
|
||||
<Copy size="1em" />
|
||||
<RemoveFormatting size="2em" />
|
||||
<span class="hidden">
|
||||
Copy Plaintext Markdown
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!-- Button to copy the HTML version -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
// Copy the HTML content to clipboard
|
||||
const htmlContent = $lq__journal_entry_obj?.content_md_html || '';
|
||||
navigator.clipboard.writeText(htmlContent).then(() => {
|
||||
alert('HTML content copied to clipboard!');
|
||||
}).catch((error) => {
|
||||
console.error('Failed to copy HTML content:', error);
|
||||
alert('Failed to copy HTML content.');
|
||||
});
|
||||
}}
|
||||
class="btn btn-sm p-1 variant-soft-secondary *:hover:inline lg:text-xs"
|
||||
title="Copy the HTML content"
|
||||
>
|
||||
<Copy size="1em" />
|
||||
<CodeXml size="2em" />
|
||||
<span class="hidden">
|
||||
Copy HTML
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!-- Button to copy the rich text (rendered HTML) version -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={async () => {
|
||||
const element = document.getElementById(`rendered_journal_entry_content_${$lq__journal_entry_obj?.journal_entry_id}`);
|
||||
if (!element) {
|
||||
console.error('Element not found: rendered_journal_entry_content');
|
||||
alert('Failed to copy rich content.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Get the rendered HTML content
|
||||
const htmlContent = element.innerHTML;
|
||||
|
||||
// Use the Clipboard API to write the HTML content as rich text
|
||||
await navigator.clipboard.write([
|
||||
new ClipboardItem({
|
||||
'text/html': new Blob([htmlContent], { type: 'text/html' }),
|
||||
}),
|
||||
]);
|
||||
|
||||
alert('Rendered rich content copied to clipboard!');
|
||||
} catch (error) {
|
||||
console.error('Failed to copy rich content:', error);
|
||||
alert('Failed to copy rich content.');
|
||||
}
|
||||
}}
|
||||
class="btn btn-sm p-1 variant-soft-secondary *:hover:inline lg:text-xs"
|
||||
title="Copy the rich text (rendered HTML) content"
|
||||
>
|
||||
<Copy size="1em" />
|
||||
<TypeOutline size="2em" />
|
||||
<span class="hidden">Copy Rich Text</span>
|
||||
</button>
|
||||
|
||||
<!-- Clone entry -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
// Clone the journal entry
|
||||
// We only want to clone certain fields from the original journal entry object to avoid conflicts.
|
||||
let data_kv = {
|
||||
code: $lq__journal_entry_obj?.code,
|
||||
category_code: $lq__journal_entry_obj?.category_code,
|
||||
name: $lq__journal_entry_obj?.name,
|
||||
short_name: $lq__journal_entry_obj?.short_name,
|
||||
content: $lq__journal_entry_obj?.content,
|
||||
description: $lq__journal_entry_obj?.description,
|
||||
tags: $lq__journal_entry_obj?.tags,
|
||||
};
|
||||
|
||||
journals_func.create_ae_obj__journal_entry({
|
||||
api_cfg: $ae_api,
|
||||
journal_id: $lq__journal_entry_obj?.journal_id,
|
||||
data_kv: data_kv,
|
||||
log_lvl: log_lvl,
|
||||
}).then((result) => {
|
||||
alert('Journal entry cloned successfully!');
|
||||
goto(`/journals/${result.journal_id_random}/entry/${result.journal_entry_id_random}`);
|
||||
}).catch((error) => {
|
||||
console.error('Error cloning journal entry:', error);
|
||||
alert('Failed to clone journal entry.');
|
||||
});
|
||||
}}
|
||||
class="btn btn-sm p-1 variant-soft-secondary hover:variant-filled-secondary *:hover:inline lg:text-xs"
|
||||
title="Clone this journal entry"
|
||||
>
|
||||
<!-- class="btn btn-sm variant-soft-surface hover:variant-filled-warning transition py-1 px-2" -->
|
||||
<!-- <Copy strokeWidth="1" /> -->
|
||||
<Copy size="2em" />
|
||||
<span class="hidden md:inline">Clone</span>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="flex flex-row flex-wrap gap-2 items-center justify-end">
|
||||
<div class="flex-grow flex flex-row flex-wrap gap-2 items-center justify-end">
|
||||
<div class="flex flex-row flex-wrap gap-1 items-center justify-center">
|
||||
|
||||
<!-- Tags for journal entry. Comma delimited list. -->
|
||||
{#if $journals_loc.entry.edit_kv[$lq__journal_entry_obj?.journal_entry_id]}
|
||||
@@ -901,9 +785,370 @@ function handle_cut_string(old_string: string) {
|
||||
|
||||
</div>
|
||||
|
||||
<section class="relative">
|
||||
<!-- Menu Button -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => (show_menu = !show_menu)}
|
||||
class="btn variant-outline-secondary hover:variant-filled-secondary transition py-1 px-2"
|
||||
title="Toggle menu"
|
||||
>
|
||||
<Menu size="1.5em" class="inline-block" />
|
||||
Menu
|
||||
</button>
|
||||
|
||||
<!-- Menu -->
|
||||
{#if show_menu}
|
||||
<div
|
||||
class="absolute top-12 right-0 bg-white dark:bg-gray-800 shadow-lg rounded-lg p-4 z-50 w-80"
|
||||
>
|
||||
<!-- Copy and Clone Buttons -->
|
||||
<div>
|
||||
<!-- Button to copy the Markdown version -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
navigator.clipboard.writeText(tmp_entry_obj.content).then(() => {
|
||||
alert('Markdown content copied to clipboard!');
|
||||
}).catch((error) => {
|
||||
console.error('Failed to copy content:', error);
|
||||
alert('Failed to copy content.');
|
||||
});
|
||||
}}
|
||||
class="btn btn-sm w-full mb-2 p-1 variant-soft-secondary *:hover:inline lg:text-xs"
|
||||
title="Copy the markdown content"
|
||||
>
|
||||
<Copy size="1em" />
|
||||
<RemoveFormatting size="2em" />
|
||||
<span class="hidden">
|
||||
Copy Plaintext Markdown
|
||||
</span>
|
||||
</button>
|
||||
<!-- Button to copy the HTML version -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
// Copy the HTML content to clipboard
|
||||
const htmlContent = $lq__journal_entry_obj?.content_md_html || '';
|
||||
navigator.clipboard.writeText(htmlContent).then(() => {
|
||||
alert('HTML content copied to clipboard!');
|
||||
}).catch((error) => {
|
||||
console.error('Failed to copy HTML content:', error);
|
||||
alert('Failed to copy HTML content.');
|
||||
});
|
||||
}}
|
||||
class="btn btn-sm w-full mb-2 p-1 variant-soft-secondary *:hover:inline lg:text-xs"
|
||||
title="Copy the HTML content"
|
||||
>
|
||||
<Copy size="1em" />
|
||||
<CodeXml size="2em" />
|
||||
<span class="hidden">
|
||||
Copy HTML
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!-- Button to copy the rich text (rendered HTML) version -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={async () => {
|
||||
const element = document.getElementById(`rendered_journal_entry_content_${$lq__journal_entry_obj?.journal_entry_id}`);
|
||||
if (!element) {
|
||||
console.error('Element not found: rendered_journal_entry_content');
|
||||
alert('Failed to copy rich content.');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Get the rendered HTML content
|
||||
const htmlContent = element.innerHTML;
|
||||
|
||||
// Use the Clipboard API to write the HTML content as rich text
|
||||
await navigator.clipboard.write([
|
||||
new ClipboardItem({
|
||||
'text/html': new Blob([htmlContent], { type: 'text/html' }),
|
||||
}),
|
||||
]);
|
||||
|
||||
alert('Rendered rich content copied to clipboard!');
|
||||
} catch (error) {
|
||||
console.error('Failed to copy rich content:', error);
|
||||
alert('Failed to copy rich content.');
|
||||
}
|
||||
}}
|
||||
class="btn btn-sm w-full mb-2 p-1 variant-soft-secondary *:hover:inline lg:text-xs"
|
||||
title="Copy the rich text (rendered HTML) content"
|
||||
>
|
||||
<Copy size="1em" />
|
||||
<TypeOutline size="2em" />
|
||||
<span class="hidden">Copy Rich Text</span>
|
||||
</button>
|
||||
|
||||
<!-- Clone entry -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
// Clone the journal entry
|
||||
// We only want to clone certain fields from the original journal entry object to avoid conflicts.
|
||||
let data_kv = {
|
||||
code: $lq__journal_entry_obj?.code,
|
||||
category_code: $lq__journal_entry_obj?.category_code,
|
||||
name: $lq__journal_entry_obj?.name,
|
||||
short_name: $lq__journal_entry_obj?.short_name,
|
||||
content: $lq__journal_entry_obj?.content,
|
||||
description: $lq__journal_entry_obj?.description,
|
||||
tags: $lq__journal_entry_obj?.tags,
|
||||
};
|
||||
|
||||
journals_func.create_ae_obj__journal_entry({
|
||||
api_cfg: $ae_api,
|
||||
journal_id: $lq__journal_entry_obj?.journal_id,
|
||||
data_kv: data_kv,
|
||||
log_lvl: log_lvl,
|
||||
}).then((result) => {
|
||||
alert('Journal entry cloned successfully!');
|
||||
goto(`/journals/${result.journal_id_random}/entry/${result.journal_entry_id_random}`);
|
||||
}).catch((error) => {
|
||||
console.error('Error cloning journal entry:', error);
|
||||
alert('Failed to clone journal entry.');
|
||||
});
|
||||
}}
|
||||
class="btn btn-sm w-full mb-2 p-1 variant-soft-secondary hover:variant-filled-secondary *:hover:inline lg:text-xs"
|
||||
title="Clone this journal entry"
|
||||
>
|
||||
<!-- class="btn btn-sm variant-soft-surface hover:variant-filled-warning transition py-1 px-2" -->
|
||||
<!-- <Copy strokeWidth="1" /> -->
|
||||
<Copy size="2em" />
|
||||
<span class="hidden md:inline">Clone Entry</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="divider my-2"></div>
|
||||
|
||||
<!-- Core Object Properties -->
|
||||
<div>
|
||||
<!-- Set/unset priority (boolean) -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
tmp_entry_obj.priority = !$lq__journal_entry_obj?.priority;
|
||||
update_journal_entry();
|
||||
}}
|
||||
class="btn w-full mb-2 variant-soft-tertiary transition hover:variant-filled-tertiary"
|
||||
title="Toggle priority of this journal entry"
|
||||
>
|
||||
{#if $lq__journal_entry_obj?.priority}
|
||||
<Flag strokeWidth="2.5" color="green" class="inline-block" />
|
||||
{:else}
|
||||
<FlagOff strokeWidth="1" color="gray" class="inline-block" />
|
||||
{/if}
|
||||
<span class="hidden lg:inline">
|
||||
Priority
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!-- Set sort order (number) -->
|
||||
<span
|
||||
class:hidden={!$ae_loc.edit_mode}
|
||||
class="w-full mb-2 flex flex-row flex-wrap items-center justify-center border border-gray-300 rounded-lg">
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
console.log('Incrementing sort order');
|
||||
tmp_entry_obj.sort = $lq__journal_entry_obj?.sort ? $lq__journal_entry_obj?.sort + 1 : 1;
|
||||
console.log('Incremented sort order:', tmp_entry_obj.sort);
|
||||
update_journal_entry();
|
||||
}}
|
||||
class="btn-icon-sm variant-soft-tertiary transition hover:variant-filled-tertiary"
|
||||
title="Increment sort order of this journal entry"
|
||||
>
|
||||
<Plus strokeWidth="2.5" color="blue" />
|
||||
</button>
|
||||
<span class="mx-1">
|
||||
{#if $lq__journal_entry_obj?.sort}
|
||||
{$lq__journal_entry_obj.sort}
|
||||
{:else}
|
||||
<!-- <ArrowDown01 /> -->
|
||||
<ArrowDown10 />
|
||||
{/if}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
console.log('Decrementing sort order');
|
||||
tmp_entry_obj.sort = $lq__journal_entry_obj?.sort ? $lq__journal_entry_obj?.sort - 1 : 0;
|
||||
console.log('Decremented sort order:', tmp_entry_obj.sort);
|
||||
update_journal_entry();
|
||||
}}
|
||||
class="btn-icon-sm variant-soft-tertiary transition hover:variant-filled-tertiary"
|
||||
title="Decrement sort order of this journal entry"
|
||||
>
|
||||
<Minus strokeWidth="2.5" color="blue" />
|
||||
</button>
|
||||
</span>
|
||||
|
||||
|
||||
<!-- Set group (string) -->
|
||||
<input
|
||||
type="text"
|
||||
bind:value={tmp_entry_obj.group}
|
||||
placeholder="Group"
|
||||
onchange={() => {
|
||||
update_journal_entry();
|
||||
}}
|
||||
class:hidden={!$ae_loc.edit_mode}
|
||||
class="input input-sm input-bordered w-full mb-2"
|
||||
title="Set group (for sorting) of this journal entry"
|
||||
/>
|
||||
|
||||
<!-- Set archive datetime (string) -->
|
||||
<span class="w-full mb-2 flex flex-row flex-wrap items-center justify-center border border-gray-200 rounded-lg">
|
||||
|
||||
<input
|
||||
type="datetime-local"
|
||||
bind:value={tmp_entry_obj.archive_on}
|
||||
placeholder="Archive On"
|
||||
onchange={() => {
|
||||
update_journal_entry();
|
||||
}}
|
||||
class:hidden={!$ae_loc.edit_mode}
|
||||
class="input input-sm input-bordered w-auto border-none"
|
||||
title="Set archive on datetime for archiving this journal entry"
|
||||
/>
|
||||
|
||||
{#if $lq__journal_entry_obj?.archive_on}
|
||||
<!-- Button to clear the datetime -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
tmp_entry_obj.archive_on = null;
|
||||
update_journal_entry();
|
||||
}}
|
||||
class:hidden={!$ae_loc.edit_mode}
|
||||
class="btn btn-icon btn-icon-sm variant-glass-warning hover:variant-filled-warning transition *:hover:inline"
|
||||
title="Clear the archive on datetime for this journal entry"
|
||||
>
|
||||
<X strokeWidth="2.5" color="red" />
|
||||
<!-- <span class="hidden">Clear Archive</span> -->
|
||||
</button>
|
||||
{:else}
|
||||
<!-- Button to set the datetime to now -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
// tmp_entry_obj.archive_on = new Date().toISOString();
|
||||
// console.log('Archive on datetime set to now:', tmp_entry_obj.archive_on);
|
||||
tmp_entry_obj = {
|
||||
...tmp_entry_obj,
|
||||
archive_on: new Date().toISOString()
|
||||
};
|
||||
console.log('Archive on datetime set to now:', tmp_entry_obj.archive_on);
|
||||
update_journal_entry();
|
||||
}}
|
||||
class:hidden={!$ae_loc.edit_mode}
|
||||
class="btn btn-icon btn-icon-sm variant-glass-warning hover:variant-filled-warning transition *:hover:inline"
|
||||
title="Set the archive on datetime for this journal entry"
|
||||
>
|
||||
<Clock strokeWidth="2.5" color="blue" />
|
||||
<!-- <span class="hidden">Set Archive</span> -->
|
||||
</button>
|
||||
{/if}
|
||||
</span>
|
||||
|
||||
<!-- Set/unset hide (boolean) -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
tmp_entry_obj.hide = !$lq__journal_entry_obj?.hide;
|
||||
update_journal_entry();
|
||||
}}
|
||||
class="btn btn-sm md:btn-md w-full mb-2 variant-soft-warning hover:variant-filled-warning transition"
|
||||
title="Toggle visibility of this journal entry"
|
||||
>
|
||||
{#if $lq__journal_entry_obj?.hide}
|
||||
<EyeOff strokeWidth="1" color="red" class="inline-block" />
|
||||
<span class="hidden md:inline">Hidden</span>
|
||||
{:else}
|
||||
<Eye strokeWidth="2.5" color="green" class="inline-block" />
|
||||
<span class="hidden md:inline">Visible</span>
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
<!-- Set/unset enable (boolean) -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
tmp_entry_obj.enable = !$lq__journal_entry_obj?.enable;
|
||||
update_journal_entry();
|
||||
}}
|
||||
class:hidden={!$ae_loc.administrator_access || !$ae_loc.edit_mode}
|
||||
class="btn btn-sm md:btn-md w-full mb-2 variant-soft-error hover:variant-filled-error transition"
|
||||
title="Toggle enable status of this journal entry"
|
||||
>
|
||||
{#if $lq__journal_entry_obj?.enable}
|
||||
<ShieldCheck strokeWidth="2.5" color="green" class="inline-block" />
|
||||
<span class="hidden md:inline">Enabled</span>
|
||||
{:else}
|
||||
<ShieldMinus strokeWidth="1" color="red" class="inline-block" />
|
||||
<span class="hidden md:inline">Disabled</span>
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
<!-- Delete journal entry -->
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
if (confirm(`Are you sure you want to delete this journal entry?`)) {
|
||||
let delete_method = 'disable';
|
||||
if ($ae_loc.administrator_access && $ae_loc.edit_mode) {
|
||||
delete_method = 'delete';
|
||||
}
|
||||
journals_func.delete_ae_obj_id__journal_entry({
|
||||
api_cfg: $ae_api,
|
||||
journal_entry_id: $lq__journal_entry_obj?.journal_entry_id,
|
||||
method: delete_method, // 'delete', 'disable', 'hide'
|
||||
log_lvl: log_lvl
|
||||
}).then(() => {
|
||||
// Optionally, you can provide feedback to the user
|
||||
alert('Journal entry deleted successfully!');
|
||||
}).catch((error) => {
|
||||
console.error('Error deleting journal entry:', error);
|
||||
alert('Failed to delete journal entry.');
|
||||
}).finally(() => {
|
||||
$journals_slct.journal_id = null;
|
||||
$journals_slct.journal_obj = null;
|
||||
goto(`/journals/${$lq__journal_entry_obj?.journal_id}`);
|
||||
});
|
||||
}
|
||||
}}
|
||||
class:hidden={!$ae_loc.edit_mode}
|
||||
class="btn btn-sm md:btn-md w-full mb-2 variant-soft-error hover:variant-filled-error transition"
|
||||
title="Delete this journal entry"
|
||||
>
|
||||
|
||||
{#if ($ae_loc.administrator_access && $ae_loc.edit_mode)}
|
||||
<FileX strokeWidth="2.5" color="red" class="inline-block" />
|
||||
<span class="hidden md:inline">Delete</span>
|
||||
{:else}
|
||||
|
||||
<Trash2 strokeWidth="2.5" color="orange" class="inline-block" />
|
||||
<span class="hidden md:inline">Remove</span>
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
<section
|
||||
class="flex flex-row flex-wrap gap-1 items-center justify-evenly w-full max-w-sm "
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user