fix(journals): add type='button' to prevent form submission and migrate to V3 Action API for file downloads
This commit is contained in:
@@ -168,7 +168,7 @@
|
||||
// Legacy endpoints often expect integer IDs and will return 404 for string IDs.
|
||||
const file_id = hosted_file_obj.event_file_id || hosted_file_obj.hosted_file_id || hosted_file_id;
|
||||
const obj_type_path = hosted_file_obj.event_file_id ? 'event_file' : 'hosted_file';
|
||||
return `${$ae_api.base_url}/v3/action/${obj_type_path}/${file_id}/download?filename=${ae_util.clean_filename(final_filename)}&x_no_account_id_token=${$ae_api.account_id}`;
|
||||
return `${$ae_api.base_url}/v3/action/${obj_type_path}/${file_id}/download?filename=${ae_util.clean_filename(final_filename)}&key=${$ae_api.account_id}`;
|
||||
});
|
||||
|
||||
async function handle_click() {
|
||||
|
||||
@@ -644,7 +644,7 @@ export const download_hosted_file = async function download_hosted_file({
|
||||
|
||||
const task_id = hosted_file_id;
|
||||
|
||||
const endpoint = `/hosted_file/${hosted_file_id}/download`;
|
||||
const endpoint = `/v3/action/hosted_file/${hosted_file_id}/download`;
|
||||
if (filename) {
|
||||
params['filename'] = filename;
|
||||
}
|
||||
@@ -697,7 +697,7 @@ export const delete_hosted_file = async function delete_hosted_file({
|
||||
}) {
|
||||
console.log('*** stores_hosted_api.js: delete_hosted_file() ***');
|
||||
|
||||
const endpoint = `/hosted_file/${hosted_file_id}`;
|
||||
const endpoint = `/v3/action/hosted_file/${hosted_file_id}`;
|
||||
if (link_to_type) {
|
||||
params['link_to_type'] = link_to_type;
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
open_file_status_message = 'Downloading file to cache...';
|
||||
|
||||
// Use the PROVEN endpoint path from api.ts that is known to work in Default Mode.
|
||||
const url = `${$ae_api.base_url}/v3/action/hosted_file/${event_file_obj.hosted_file_id}/download?return_file=true&filename=${encodeURIComponent(event_file_obj.filename)}&x_no_account_id_token=direct-download`;
|
||||
const url = `${$ae_api.base_url}/v3/action/hosted_file/${event_file_obj.hosted_file_id}/download?return_file=true&filename=${encodeURIComponent(event_file_obj.filename)}&key=${$ae_api.account_id}`;
|
||||
|
||||
const dl_result = await native.download_to_cache({
|
||||
url,
|
||||
|
||||
@@ -394,7 +394,7 @@
|
||||
<a
|
||||
href="{$ae_api.base_url}/event/file/{event_file_obj?.event_file_id}/download?filename={ae_util.clean_filename(
|
||||
event_file_obj?.filename
|
||||
)}&key=${$ae_api.account_id}"
|
||||
)}&key={$ae_api.account_id}"
|
||||
class="btn btn-sm p-1 preset-tonal-secondary *:hover:inline lg:text-xs underline"
|
||||
title={`Download this file:\n${ae_util.clean_filename(event_file_obj?.filename)}\n[API] SHA256: ${event_file_obj?.hash_sha256.slice(0, 10)}...\nHosted ID: ${event_file_obj?.hosted_file_id} Event File ID: ${event_file_obj?.event_file_id}`}
|
||||
>
|
||||
@@ -431,11 +431,11 @@
|
||||
>
|
||||
<span class="text-xs text-gray-500 w-32"> Session Name: </span>
|
||||
<a
|
||||
href="{$ae_api.base_url}/event/file/{event_file_obj?.event_file_id}/download?filename={event_file_obj?.event_session_code}-{ae_util
|
||||
href="{$ae_api.base_url}/v3/action/event_file/{event_file_obj?.event_file_id}/download?filename={event_file_obj?.event_session_code}-{ae_util
|
||||
.clean_filename(event_file_obj?.event_presentation_name)
|
||||
.substring(0, 20)}-{ae_util.clean_filename(
|
||||
event_file_obj?.event_presenter_full_name
|
||||
)}.{event_file_obj?.extension}&key=${$ae_api.account_id}"
|
||||
)}.{event_file_obj?.extension}&key={$ae_api.account_id}"
|
||||
class="btn btn-sm p-1 preset-tonal-secondary *:hover:inline lg:text-xs underline"
|
||||
title={`Download renamed with session name to: ${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_session_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}`}
|
||||
>
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
|
||||
import Archive_content_obj_li from './ae_idaa_comp__archive_content_obj_li.svelte';
|
||||
import Archive_content_obj_id_edit from './ae_idaa_comp__archive_content_obj_id_edit.svelte';
|
||||
// import Media_player from './../ae_idaa_comp__media_player.svelte';
|
||||
import Modal_media_player from './ae_idaa_comp__modal_media_player.svelte';
|
||||
import Help_tech from '$lib/app_components/e_app_help_tech.svelte';
|
||||
|
||||
|
||||
@@ -91,8 +91,8 @@
|
||||
<audio autoplay controls style="max-width: 100%; max-height: 65vh;" class="w-96 h-auto">
|
||||
<source
|
||||
id="view_archive_content_audio_source"
|
||||
src="{$ae_api.base_url}/hosted_file/{$idaa_slct.archive_content_obj
|
||||
?.hosted_file_id}/download?key=${$ae_api.account_id}"
|
||||
src="{$ae_api.base_url}/v3/action/hosted_file/{$idaa_slct.archive_content_obj
|
||||
?.hosted_file_id}/download?key={$ae_api.account_id}"
|
||||
type="audio/mpeg"
|
||||
/>
|
||||
<!--<source src="audio.ogg" type="audio/ogg">-->
|
||||
@@ -103,8 +103,8 @@
|
||||
<!-- style="max-width: 100%; max-height: 65vh;" -->
|
||||
<video autoplay controls class="w-full h-auto">
|
||||
<source
|
||||
src="{$ae_api.base_url}/hosted_file/{$idaa_slct.archive_content_obj
|
||||
?.hosted_file_id}/download?key=${$ae_api.account_id}"
|
||||
src="{$ae_api.base_url}/v3/action/hosted_file/{$idaa_slct.archive_content_obj
|
||||
?.hosted_file_id}/download?key={$ae_api.account_id}"
|
||||
type="video/mp4"
|
||||
/>
|
||||
<!--<source src="video.ogg" type="video/ogg">-->
|
||||
@@ -113,15 +113,15 @@
|
||||
</video>
|
||||
{:else if file_icons[$idaa_slct.archive_content_obj.file_extension] == 'file-image'}
|
||||
<img
|
||||
src="{$ae_api.base_url}/hosted_file/{$idaa_slct.archive_content_obj
|
||||
?.hosted_file_id}/download?key=${$ae_api.account_id}"
|
||||
src="{$ae_api.base_url}/v3/action/hosted_file/{$idaa_slct.archive_content_obj
|
||||
?.hosted_file_id}/download?key={$ae_api.account_id}"
|
||||
alt={$idaa_slct.archive_content_obj.name}
|
||||
style="max-width: 100%; max-height: 65vh;"
|
||||
/>
|
||||
{:else}
|
||||
<a
|
||||
href="{$ae_api.base_url}/hosted_file/{$idaa_slct.archive_content_obj
|
||||
?.hosted_file_id}/download?key=${$ae_api.account_id}"
|
||||
href="{$ae_api.base_url}/v3/action/hosted_file/{$idaa_slct.archive_content_obj
|
||||
?.hosted_file_id}/download?key={$ae_api.account_id}"
|
||||
target="_blank"
|
||||
class="
|
||||
novi_btn
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
</a>
|
||||
<!-- <a href="/about" class="btn btn-sm">About</a> -->
|
||||
<!-- <a href="/settings" class="btn btn-sm">Settings</a> -->
|
||||
<button
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
if ($ae_loc.edit_mode) {
|
||||
// Confirm before clearing
|
||||
@@ -249,8 +249,7 @@
|
||||
"
|
||||
>
|
||||
<!-- Scroll to top button -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
class="
|
||||
ae_btn_success_outlined
|
||||
|
||||
@@ -291,9 +290,8 @@
|
||||
|
||||
<!-- Scroll to the right button -->
|
||||
<!-- Temporarily hidden until I figure out a better way to do this -->
|
||||
<button
|
||||
<button type="button"
|
||||
class:hidden={1 == 1}
|
||||
type="button"
|
||||
class="
|
||||
ae_btn_success_outlined
|
||||
|
||||
@@ -320,8 +318,7 @@
|
||||
</button>
|
||||
|
||||
<!-- Scroll to bottom button -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
class="
|
||||
ae_btn_success_outlined
|
||||
|
||||
|
||||
@@ -120,8 +120,7 @@
|
||||
<!-- Administrative Action Bar (Edit Mode Only) -->
|
||||
{#if $ae_loc.edit_mode}
|
||||
<nav class="flex flex-row flex-wrap gap-3 items-center justify-center w-full py-4 border-y border-surface-500/10">
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
class="btn variant-filled-secondary shadow-lg hover:scale-105 transition-transform"
|
||||
onclick={() => $journals_sess.show__modal_new__journal_obj = true}
|
||||
>
|
||||
@@ -129,8 +128,7 @@
|
||||
<span>New Journal</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
class="btn variant-filled-surface border border-surface-500/30 shadow-lg hover:scale-105 transition-transform"
|
||||
onclick={() => show_import_modal = true}
|
||||
>
|
||||
@@ -138,8 +136,7 @@
|
||||
<span>Import</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
class="btn variant-soft-surface shadow-lg hover:scale-105 transition-transform"
|
||||
onclick={() => $journals_sess.show__modal__journals_config = true}
|
||||
>
|
||||
@@ -163,8 +160,7 @@
|
||||
<SquareLibrary size="4em" class="mx-auto mb-4 opacity-20" />
|
||||
<h3 class="text-2xl font-bold mb-2">No Journals Found</h3>
|
||||
<p class="opacity-60 mb-6">You haven't created any journals yet. Start by creating one to begin your documentation journey.</p>
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
class="btn variant-filled-primary"
|
||||
onclick={() => $journals_sess.show__modal_new__journal_obj = true}
|
||||
>
|
||||
|
||||
@@ -99,8 +99,7 @@
|
||||
"
|
||||
>
|
||||
<!-- If middle click then open the all journals page in a new tab. Otherwise show/hide the menu. -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onmousedown={(event) => {
|
||||
if (event.button === 1) {
|
||||
// Middle click - open in new tab
|
||||
@@ -230,8 +229,7 @@ Middle-click to open in new tab`}
|
||||
</a>
|
||||
{:else}
|
||||
<!-- Edit Journal button. Creates a modal to edit the journal. -->
|
||||
<!-- <button
|
||||
type="button"
|
||||
<!-- <button type="button"
|
||||
onclick={() => {
|
||||
tmp_journal_obj = {
|
||||
name: $lq__journal_obj?.name,
|
||||
@@ -265,8 +263,7 @@ Middle-click to open in new tab`}
|
||||
<!-- <span class="text-sm text-gray-500 hidden md:inline">
|
||||
New entry:
|
||||
</span> -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
// $journals_sess.show__modal_new__journal_entry_obj = true;
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@
|
||||
{#if $ae_loc.edit_mode && on_force_reset}
|
||||
<div class="pt-4 border-t border-error-500/20">
|
||||
<p class="text-xs mb-2 opacity-70 italic">Passcode lost? You can force a reset to plain text, but all currently encrypted data will be permanently deleted.</p>
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
|
||||
class="btn btn-sm variant-filled-error font-bold"
|
||||
onclick={on_force_reset}
|
||||
>
|
||||
@@ -89,8 +89,7 @@
|
||||
{/if}
|
||||
|
||||
<!-- Floating Save Button -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={on_save}
|
||||
disabled={!has_changed}
|
||||
class="btn btn-sm md:btn-md lg:btn-lg fixed top-72 right-6 min-w-32 variant-filled-success shadow-xl z-20 transition-all"
|
||||
@@ -100,8 +99,7 @@
|
||||
</button>
|
||||
|
||||
<!-- Inline Save Button (Mobile/Context) -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={on_save}
|
||||
disabled={!has_changed}
|
||||
class="btn variant-filled-warning w-full max-w-96 mt-4"
|
||||
|
||||
@@ -58,8 +58,7 @@
|
||||
</a>
|
||||
|
||||
<div class="flex items-center gap-2 grow">
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={toggle_edit_mode}
|
||||
class="btn-icon btn-icon-sm transition-all {has_changed && $journals_loc.entry.edit_kv[entry.journal_entry_id] === 'current' ? 'variant-filled-success' : 'variant-soft-surface'}"
|
||||
>
|
||||
@@ -90,7 +89,7 @@
|
||||
<!-- Auto-Save indicator -->
|
||||
{#if $journals_loc.entry.edit_kv[entry.journal_entry_id] === 'current'}
|
||||
<div class="flex items-center gap-1 px-2 border-r border-surface-500/20 mr-1">
|
||||
<button
|
||||
<button type="button"
|
||||
class="btn-icon btn-icon-sm { $journals_loc.entry.auto_save ? 'text-primary-500' : 'opacity-30'}"
|
||||
onclick={() => $journals_loc.entry.auto_save = !$journals_loc.entry.auto_save}
|
||||
title="Toggle Auto Save"
|
||||
@@ -107,7 +106,7 @@
|
||||
|
||||
<!-- Decrypt Toggle (Lock) -->
|
||||
{#if entry.private}
|
||||
<button
|
||||
<button type="button"
|
||||
class="btn-icon btn-icon-sm transition-all {is_decrypted ? 'variant-filled-success shadow-lg shadow-success-500/20' : 'variant-soft-warning'}"
|
||||
onclick={on_decrypt}
|
||||
title={is_decrypted ? 'Lock Content' : 'Decrypt Content'}
|
||||
@@ -119,7 +118,8 @@
|
||||
<div class="w-[1px] h-6 bg-surface-500/20 mx-1"></div>
|
||||
|
||||
<!-- Unified Config Button -->
|
||||
<button
|
||||
<button type="button"
|
||||
|
||||
class="btn btn-sm variant-soft-primary font-bold"
|
||||
onclick={on_show_config}
|
||||
>
|
||||
@@ -128,7 +128,7 @@
|
||||
|
||||
<!-- Explicit Save (Mobile/Backup) -->
|
||||
{#if has_changed && save_status !== 'saving'}
|
||||
<button class="btn btn-sm variant-filled-primary shadow-lg" onclick={on_save}>
|
||||
<button type="button" class="btn btn-sm variant-filled-primary shadow-lg" onclick={on_save}>
|
||||
<Save size="1.1em" class="mr-2" /> Save
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
@@ -173,8 +173,7 @@
|
||||
</h3>
|
||||
|
||||
{#if $ae_loc.edit_mode}
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
class="btn btn-sm variant-soft-warning font-semibold"
|
||||
onclick={() => {
|
||||
$ae_sess.files.add_to_use_files_method = ($ae_sess.files.add_to_use_files_method === 'upload') ? 'select' : 'upload';
|
||||
@@ -207,7 +206,7 @@
|
||||
|
||||
<div class="flex items-center gap-1 ml-2">
|
||||
{#if $ae_loc.edit_mode}
|
||||
<button
|
||||
<button type="button"
|
||||
class="btn btn-sm variant-soft-error"
|
||||
onclick={() => handle_remove_file(file_id)}
|
||||
title="Remove attachment"
|
||||
|
||||
@@ -376,7 +376,7 @@
|
||||
<AlertCircle size="2.5em" />
|
||||
<span class="text-xl">{decryption_error}</span>
|
||||
</div>
|
||||
<button class="btn btn-sm variant-filled-error shadow-lg font-bold" onclick={() => decryption_error = null}>
|
||||
<button type="button" class="btn btn-sm variant-filled-error shadow-lg font-bold" onclick={() => decryption_error = null}>
|
||||
<XCircle size="1.2em" class="mr-2" /> Dismiss
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -193,8 +193,7 @@
|
||||
<span class="flex flex-row flex-wrap gap-1 items-center justify-center">
|
||||
{#if !journals_journal_entry_obj.private}
|
||||
<!-- Button to copy the Markdown version -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
let tmp_entry_obj = journals_journal_entry_obj;
|
||||
|
||||
@@ -217,8 +216,7 @@
|
||||
</button>
|
||||
|
||||
<!-- Button to copy the rendered to HTML version -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
let htmlContent =
|
||||
journals_journal_entry_obj.content_md_html || '';
|
||||
@@ -246,8 +244,7 @@
|
||||
</button>
|
||||
|
||||
<!-- Button to copy the rich text (rendered HTML) version -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={async () => {
|
||||
const element = document.getElementById(
|
||||
`rendered_journal_entry_content_${journals_journal_entry_obj.journal_entry_id}`
|
||||
@@ -286,8 +283,7 @@
|
||||
</button>
|
||||
|
||||
<!-- Clone entry -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
let data_kv = {
|
||||
code: journals_journal_entry_obj.code,
|
||||
@@ -337,8 +333,7 @@
|
||||
<span class="text-xs text-gray-500 hidden">Private</span>
|
||||
|
||||
<!-- Button to copy the Markdown version -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
let tmp_entry_obj = journals_journal_entry_obj;
|
||||
|
||||
@@ -401,8 +396,7 @@
|
||||
|
||||
<!-- Category code for journal entry -->
|
||||
{#if journals_journal_entry_obj.category_code}
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
if (
|
||||
$journals_loc.entry.qry__category_code ==
|
||||
@@ -440,8 +434,7 @@ Journal ID: ${journals_journal_entry_obj?.journal_id}
|
||||
</a>
|
||||
|
||||
<!-- Button to show a modal that will allow for a quick append to Journal Entry option. -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
$journals_sess.show__modal_append__journal_entry_id =
|
||||
journals_journal_entry_obj?.id;
|
||||
@@ -561,8 +554,7 @@ Journal ID: ${journals_journal_entry_obj?.journal_id}
|
||||
</span>
|
||||
|
||||
<!-- Set/unset hide (boolean) -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
let data_kv = {
|
||||
hide: journals_journal_entry_obj?.hide ? false : true
|
||||
|
||||
@@ -123,8 +123,7 @@
|
||||
</button>
|
||||
|
||||
<!-- Clear search text button -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
class:hidden={!$journals_loc.entry.qry__search_text && !$journals_loc.entry.qry__category_code}
|
||||
onclick={() => {
|
||||
$journals_loc.entry.qry__search_text = '';
|
||||
|
||||
@@ -124,6 +124,7 @@
|
||||
</span>
|
||||
<div class="flex justify-end space-x-2 grow sm:grow-0">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm variant-ghost-surface"
|
||||
onclick={() => note_content = ""}
|
||||
disabled={is_submitting || note_content.length === 0}
|
||||
@@ -131,6 +132,7 @@
|
||||
Clear
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm variant-filled-primary font-bold shadow-md"
|
||||
onclick={handle_submit}
|
||||
disabled={is_submitting || !target_journal_id || note_content.length === 0}
|
||||
|
||||
@@ -181,19 +181,19 @@
|
||||
<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 === 'actions' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'actions')}>
|
||||
<button type="button" class="btn btn-sm transition-all {tab === 'actions' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'actions')}>
|
||||
<Zap size="1.1em" class="mr-1" /> Quick Actions
|
||||
</button>
|
||||
<button class="btn btn-sm transition-all {tab === 'general' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'general')}>
|
||||
<button type="button" class="btn btn-sm transition-all {tab === 'general' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'general')}>
|
||||
<Layout size="1.1em" class="mr-1" /> General
|
||||
</button>
|
||||
<button class="btn btn-sm transition-all {tab === 'security' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'security')}>
|
||||
<button type="button" class="btn btn-sm transition-all {tab === 'security' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'security')}>
|
||||
<ShieldCheck size="1.1em" class="mr-1" /> Status & Security
|
||||
</button>
|
||||
<button class="btn btn-sm transition-all {tab === 'ui' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'ui')}>
|
||||
<button type="button" class="btn btn-sm transition-all {tab === 'ui' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'ui')}>
|
||||
<Palette size="1.1em" class="mr-1" /> UI/Visuals
|
||||
</button>
|
||||
<button class="btn btn-sm transition-all {tab === 'json' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'json')}>
|
||||
<button type="button" class="btn btn-sm transition-all {tab === 'json' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'json')}>
|
||||
<CodeXml size="1.1em" class="mr-1" /> JSON
|
||||
</button>
|
||||
</div>
|
||||
@@ -201,13 +201,13 @@
|
||||
{#if tab === 'actions'}
|
||||
<div class="space-y-6 animate-in fade-in duration-300">
|
||||
<section class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<button class="btn variant-soft-secondary w-full py-4 text-lg font-bold" onclick={() => { show = false; on_new_entry?.(); }}>
|
||||
<button type="button" class="btn variant-soft-secondary w-full py-4 text-lg font-bold" onclick={() => { show = false; on_new_entry?.(); }}>
|
||||
<FilePlus size="1.5em" class="mr-2"/> New Journal Entry
|
||||
</button>
|
||||
<button class="btn variant-soft-surface w-full py-4" onclick={() => { show = false; on_show_export?.(); }}>
|
||||
<button type="button" class="btn variant-soft-surface w-full py-4" onclick={() => { show = false; on_show_export?.(); }}>
|
||||
<FileDown size="1.5em" class="mr-2"/> Export Entries
|
||||
</button>
|
||||
<button class="btn variant-soft-surface w-full py-4" onclick={() => { show = false; on_show_import?.(); }}>
|
||||
<button type="button" class="btn variant-soft-surface w-full py-4" onclick={() => { show = false; on_show_import?.(); }}>
|
||||
<FileUp size="1.5em" class="mr-2"/> Import Entries
|
||||
</button>
|
||||
</section>
|
||||
@@ -252,12 +252,12 @@
|
||||
<div class="flex gap-2 items-center">
|
||||
<input type="text" bind:value={category.code} class="input input-sm w-32" placeholder="Code" />
|
||||
<input type="text" bind:value={category.name} class="input input-sm grow" placeholder="Display Name" />
|
||||
<button class="btn-icon btn-icon-sm variant-soft-error" onclick={() => { tmp__journal_obj.cfg_json.category_li.splice(i, 1); }}>
|
||||
<button type="button" class="btn-icon btn-icon-sm variant-soft-error" onclick={() => { tmp__journal_obj.cfg_json.category_li.splice(i, 1); }}>
|
||||
<Minus size="1em" />
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
<button class="btn btn-sm variant-soft-primary w-full mt-2" onclick={() => {
|
||||
<button type="button" class="btn btn-sm variant-soft-primary w-full mt-2" onclick={() => {
|
||||
if(!tmp__journal_obj.cfg_json.category_li) tmp__journal_obj.cfg_json.category_li = [];
|
||||
tmp__journal_obj.cfg_json.category_li.push({code: '', name: ''});
|
||||
}}>
|
||||
@@ -303,9 +303,9 @@
|
||||
<span class="text-xs opacity-60">Manual list position</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<button class="btn-icon btn-icon-sm variant-soft-surface" onclick={() => { tmp__journal_obj.sort = (tmp__journal_obj.sort ?? 0) - 1; handle_update_journal(false); }}><Minus size="1em"/></button>
|
||||
<button type="button" class="btn-icon btn-icon-sm variant-soft-surface" onclick={() => { tmp__journal_obj.sort = (tmp__journal_obj.sort ?? 0) - 1; handle_update_journal(false); }}><Minus size="1em"/></button>
|
||||
<span class="font-mono font-bold w-8 text-center text-lg">{tmp__journal_obj.sort ?? 0}</span>
|
||||
<button class="btn-icon btn-icon-sm variant-soft-surface" onclick={() => { tmp__journal_obj.sort = (tmp__journal_obj.sort ?? 0) + 1; handle_update_journal(false); }}><Plus size="1em"/></button>
|
||||
<button type="button" class="btn-icon btn-icon-sm variant-soft-surface" onclick={() => { tmp__journal_obj.sort = (tmp__journal_obj.sort ?? 0) + 1; handle_update_journal(false); }}><Plus size="1em"/></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -339,7 +339,7 @@
|
||||
</section>
|
||||
|
||||
<section class="pt-8">
|
||||
<button class="btn btn-sm variant-filled-error w-full shadow-lg" onclick={delete_journal}>
|
||||
<button type="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>
|
||||
@@ -505,10 +505,10 @@
|
||||
|
||||
{#snippet footer()}
|
||||
<div class="flex gap-4">
|
||||
<button class="btn variant-ghost-surface font-bold min-w-[100px]" onclick={() => (show = false)}>
|
||||
<button type="button" class="btn variant-ghost-surface font-bold min-w-[100px]" onclick={() => (show = false)}>
|
||||
<X size="1.2em" class="mr-2" /> Cancel
|
||||
</button>
|
||||
<button class="btn variant-filled-primary font-bold shadow-lg min-w-[120px]" onclick={() => handle_update_journal(true)}>
|
||||
<button type="button" class="btn variant-filled-primary font-bold shadow-lg min-w-[120px]" onclick={() => handle_update_journal(true)}>
|
||||
<Check size="1.2em" class="mr-2" /> Save Changes
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -180,8 +180,7 @@
|
||||
|
||||
<div class="grow flex flex-row flex-wrap gap-2 items-center justify-end">
|
||||
<!-- Simplified Config Trigger -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => ($journals_sess.show__modal_edit__journal_obj = true)}
|
||||
class="btn variant-filled-secondary py-1 px-3 shadow-md"
|
||||
title="Journal Config & Actions"
|
||||
|
||||
@@ -86,18 +86,21 @@
|
||||
<!-- 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
|
||||
type="button"
|
||||
class="btn btn-sm transition-all {tab === 'form' ? 'variant-filled-primary' : 'variant-soft-surface'}"
|
||||
onclick={() => (tab = 'form')}
|
||||
>
|
||||
<Settings size="1.1em" class="mr-1" /> Config
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm transition-all {tab === 'local_json' ? 'variant-filled-primary' : 'variant-soft-surface'}"
|
||||
onclick={() => (tab = 'local_json')}
|
||||
>
|
||||
<Database size="1.1em" class="mr-1" /> Local JSON
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm transition-all {tab === 'session_json' ? 'variant-filled-primary' : 'variant-soft-surface'}"
|
||||
onclick={() => (tab = 'session_json')}
|
||||
>
|
||||
@@ -277,10 +280,10 @@
|
||||
|
||||
{#snippet footer()}
|
||||
<div class="flex gap-4">
|
||||
<button class="btn variant-ghost-surface font-bold min-w-[100px]" onclick={() => (show = false)}>
|
||||
<button type="button" class="btn variant-ghost-surface font-bold min-w-[100px]" onclick={() => (show = false)}>
|
||||
<X size="1.2em" class="mr-2" /> Cancel
|
||||
</button>
|
||||
<button class="btn variant-filled-primary font-bold shadow-lg min-w-[120px]" onclick={handle_save}>
|
||||
<button type="button" class="btn variant-filled-primary font-bold shadow-lg min-w-[120px]" onclick={handle_save}>
|
||||
<Check size="1.2em" class="mr-2" /> Save Changes
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -172,8 +172,7 @@ async function handle_save() {
|
||||
</div>
|
||||
|
||||
<div class="modal-action flex justify-end gap-2 mt-4">
|
||||
<button
|
||||
type="button"
|
||||
<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"
|
||||
@@ -183,8 +182,7 @@ async function handle_save() {
|
||||
<Check class="mr-1" />
|
||||
Update
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={on_close}
|
||||
class="btn preset-tonal-surface border border-surface-500 hover:preset-filled-surface-500 transition"
|
||||
>
|
||||
|
||||
@@ -121,16 +121,16 @@
|
||||
<div class="space-y-6 py-2 h-[60vh] 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 === 'actions' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'actions')}>
|
||||
<button type="button" class="btn btn-sm transition-all {tab === 'actions' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'actions')}>
|
||||
<Zap size="1.1em" class="mr-1" /> Quick Actions
|
||||
</button>
|
||||
<button class="btn btn-sm transition-all {tab === 'meta' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'meta')}>
|
||||
<button type="button" class="btn btn-sm transition-all {tab === 'meta' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'meta')}>
|
||||
<Shapes size="1.1em" class="mr-1" /> Metadata
|
||||
</button>
|
||||
<button class="btn btn-sm transition-all {tab === 'security' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'security')}>
|
||||
<button type="button" class="btn btn-sm transition-all {tab === 'security' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'security')}>
|
||||
<ShieldCheck size="1.1em" class="mr-1" /> Status & Security
|
||||
</button>
|
||||
<button class="btn btn-sm transition-all {tab === 'json' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'json')}>
|
||||
<button type="button" class="btn btn-sm transition-all {tab === 'json' ? 'variant-filled-primary' : 'variant-soft-surface'}" onclick={() => (tab = 'json')}>
|
||||
<CodeXml size="1.1em" class="mr-1" /> JSON
|
||||
</button>
|
||||
</div>
|
||||
@@ -138,16 +138,16 @@
|
||||
{#if tab === 'actions'}
|
||||
<div class="space-y-6 animate-in fade-in duration-300">
|
||||
<section class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<button class="btn variant-soft-secondary w-full" onclick={() => { show = false; on_prepend?.(); }}>
|
||||
<button type="button" class="btn variant-soft-secondary w-full" onclick={() => { show = false; on_prepend?.(); }}>
|
||||
<ArrowUpToLine size="1.2em" class="mr-2"/> Prepend Content
|
||||
</button>
|
||||
<button class="btn variant-soft-secondary w-full" onclick={() => { show = false; on_append?.(); }}>
|
||||
<button type="button" class="btn variant-soft-secondary w-full" onclick={() => { show = false; on_append?.(); }}>
|
||||
<ArrowDownToLine size="1.2em" class="mr-2"/> Append Content
|
||||
</button>
|
||||
<button class="btn variant-soft-surface w-full" onclick={() => { show = false; on_show_export?.(); }}>
|
||||
<button type="button" class="btn variant-soft-surface w-full" onclick={() => { show = false; on_show_export?.(); }}>
|
||||
<FileDown size="1.2em" class="mr-2"/> Export Entry
|
||||
</button>
|
||||
<button class="btn variant-soft-surface w-full" onclick={() => { /* Clone logic here */ alert('Clone not yet implemented in modal'); }}>
|
||||
<button type="button" class="btn variant-soft-surface w-full" onclick={() => { /* Clone logic here */ alert('Clone not yet implemented in modal'); }}>
|
||||
<Copy size="1.2em" class="mr-2"/> Clone Entry
|
||||
</button>
|
||||
</section>
|
||||
@@ -156,7 +156,7 @@
|
||||
<h4 class="text-xs font-bold uppercase opacity-50">Quick Category</h4>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{#each journal?.cfg_json?.category_li ?? [] as cat}
|
||||
<button
|
||||
<button type="button"
|
||||
class="btn btn-sm {tmp_entry_obj.category_code === cat.code ? 'variant-filled-primary' : 'variant-soft-primary'}"
|
||||
onclick={() => { tmp_entry_obj.category_code = cat.code; handle_update_entry(); on_save(); }}
|
||||
>
|
||||
@@ -195,9 +195,9 @@
|
||||
<label class="label">
|
||||
<span class="text-sm font-bold opacity-70">Sort Priority</span>
|
||||
<div class="flex items-center gap-2">
|
||||
<button class="btn-icon btn-icon-sm variant-soft-surface" onclick={() => { tmp_entry_obj.sort = (tmp_entry_obj.sort ?? 0) - 1; handle_update_entry(); on_save(); }}><Minus size="1em"/></button>
|
||||
<button type="button" class="btn-icon btn-icon-sm variant-soft-surface" onclick={() => { tmp_entry_obj.sort = (tmp_entry_obj.sort ?? 0) - 1; handle_update_entry(); on_save(); }}><Minus size="1em"/></button>
|
||||
<span class="font-mono font-bold w-8 text-center">{tmp_entry_obj.sort ?? 0}</span>
|
||||
<button class="btn-icon btn-icon-sm variant-soft-surface" onclick={() => { tmp_entry_obj.sort = (tmp_entry_obj.sort ?? 0) + 1; handle_update_entry(); on_save(); }}><Plus size="1em"/></button>
|
||||
<button type="button" class="btn-icon btn-icon-sm variant-soft-surface" onclick={() => { tmp_entry_obj.sort = (tmp_entry_obj.sort ?? 0) + 1; handle_update_entry(); on_save(); }}><Plus size="1em"/></button>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
@@ -238,9 +238,9 @@
|
||||
<span class="text-xs opacity-60">Manual list position</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<button class="btn-icon btn-icon-sm variant-soft-surface" onclick={() => { tmp_entry_obj.sort = (tmp_entry_obj.sort ?? 0) - 1; handle_update_entry(); on_save(); }}><Minus size="1em"/></button>
|
||||
<button type="button" class="btn-icon btn-icon-sm variant-soft-surface" onclick={() => { tmp_entry_obj.sort = (tmp_entry_obj.sort ?? 0) - 1; handle_update_entry(); on_save(); }}><Minus size="1em"/></button>
|
||||
<span class="font-mono font-bold w-8 text-center text-lg">{tmp_entry_obj.sort ?? 0}</span>
|
||||
<button class="btn-icon btn-icon-sm variant-soft-surface" onclick={() => { tmp_entry_obj.sort = (tmp_entry_obj.sort ?? 0) + 1; handle_update_entry(); on_save(); }}><Plus size="1em"/></button>
|
||||
<button type="button" class="btn-icon btn-icon-sm variant-soft-surface" onclick={() => { tmp_entry_obj.sort = (tmp_entry_obj.sort ?? 0) + 1; handle_update_entry(); on_save(); }}><Plus size="1em"/></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -267,7 +267,7 @@
|
||||
<RefreshCcw size="1.2em" /> Disaster Recovery
|
||||
</h4>
|
||||
<p class="text-xs opacity-70 mb-4 italic">If the encryption passcode is lost, the data is unrecoverable. You can force a reset to plain text to reuse this entry ID.</p>
|
||||
<button class="btn btn-sm variant-filled-error w-full font-bold" onclick={() => { show = false; on_force_reset?.(); }}>
|
||||
<button type="button" class="btn btn-sm variant-filled-error w-full font-bold" onclick={() => { show = false; on_force_reset?.(); }}>
|
||||
Force Reset to Plain Text
|
||||
</button>
|
||||
</div>
|
||||
@@ -275,7 +275,7 @@
|
||||
{/if}
|
||||
|
||||
<section class="pt-12">
|
||||
<button class="btn btn-sm variant-soft-error w-full" onclick={() => { alert('Delete logic handled in parent component'); }}>
|
||||
<button type="button" class="btn btn-sm variant-soft-error w-full" onclick={() => { alert('Delete logic handled in parent component'); }}>
|
||||
<Trash2 size="1.1em" class="mr-2" /> Delete Entry
|
||||
</button>
|
||||
</section>
|
||||
@@ -294,7 +294,7 @@
|
||||
</div>
|
||||
|
||||
{#snippet footer()}
|
||||
<button class="btn variant-filled-primary font-bold shadow-lg min-w-[120px]" onclick={() => (show = false)}>
|
||||
<button type="button" class="btn variant-filled-primary font-bold shadow-lg min-w-[120px]" onclick={() => (show = false)}>
|
||||
<Check size="1.2em" class="mr-2" />
|
||||
Done
|
||||
</button>
|
||||
|
||||
@@ -111,7 +111,8 @@
|
||||
</label>
|
||||
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-2">
|
||||
{#each templates as template}
|
||||
<button
|
||||
<button type="button"
|
||||
|
||||
class="btn variant-ringed-surface flex flex-col gap-1 p-2 h-24 items-center justify-center border-2 text-center {selected_template_id === template.id ? 'border-primary-500 bg-primary-50 dark:bg-primary-900/20' : 'opacity-60'}"
|
||||
onclick={() => { selected_template_id = template.id; generate_preview(); }}
|
||||
>
|
||||
@@ -144,13 +145,13 @@
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="modal-action flex justify-between items-center">
|
||||
<button class="btn preset-tonal-secondary" onclick={on_close}>Close</button>
|
||||
<button type="button" class="btn preset-tonal-secondary" onclick={on_close}>Close</button>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<button class="btn variant-soft-primary" onclick={handle_copy}>
|
||||
<button type="button" class="btn variant-soft-primary" onclick={handle_copy}>
|
||||
<Copy class="mr-2" size="1.2em" /> Copy to Clipboard
|
||||
</button>
|
||||
<button class="btn preset-filled-primary" onclick={handle_download}>
|
||||
<button type="button" class="btn preset-filled-primary" onclick={handle_download}>
|
||||
<Download class="mr-2" size="1.2em" /> Download File
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -232,8 +232,8 @@
|
||||
{/if}
|
||||
|
||||
<div class="modal-action">
|
||||
<button class="btn preset-tonal-secondary" onclick={on_close}>Cancel</button>
|
||||
<button
|
||||
<button type="button" class="btn preset-tonal-secondary" onclick={on_close}>Cancel</button>
|
||||
<button type="button"
|
||||
class="btn preset-filled-primary"
|
||||
disabled={parsed_entries.length === 0 || is_importing}
|
||||
onclick={handle_import}
|
||||
|
||||
@@ -105,8 +105,7 @@
|
||||
{obj_enable} -->
|
||||
|
||||
<!-- Set/unset priority (boolean) -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
obj_priority = !obj_priority;
|
||||
// update_journal_entry();
|
||||
@@ -127,8 +126,7 @@
|
||||
class:hidden={!$ae_loc.edit_mode}
|
||||
class="flex flex-row flex-wrap items-center justify-center border border-gray-300 rounded-lg"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
obj_sort = obj_sort ? obj_sort + 1 : 1;
|
||||
// update_journal_entry();
|
||||
@@ -146,8 +144,7 @@
|
||||
<ArrowDown10 />
|
||||
{/if}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
obj_sort = obj_sort ? obj_sort - 1 : 0;
|
||||
// update_journal_entry();
|
||||
@@ -190,8 +187,7 @@
|
||||
|
||||
{#if obj_archive_on}
|
||||
<!-- Button to clear the datetime -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
obj_archive_on = null;
|
||||
// update_journal_entry();
|
||||
@@ -205,8 +201,7 @@
|
||||
</button>
|
||||
{:else}
|
||||
<!-- Button to set the datetime to now -->
|
||||
<button
|
||||
type="button"
|
||||
<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);
|
||||
@@ -225,8 +220,7 @@
|
||||
</span>
|
||||
|
||||
<!-- Set/unset hide (boolean) -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
obj_hide = !obj_hide;
|
||||
update_journal_entry();
|
||||
@@ -244,8 +238,7 @@
|
||||
</button>
|
||||
|
||||
<!-- Set/unset enable (boolean) -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
obj_enable = !obj_enable;
|
||||
// update_journal_entry();
|
||||
@@ -264,8 +257,7 @@
|
||||
</button>
|
||||
|
||||
<!-- Delete journal entry -->
|
||||
<button
|
||||
type="button"
|
||||
<button type="button"
|
||||
onclick={() => {
|
||||
if (confirm(`Are you sure you want to delete this journal entry?`)) {
|
||||
let delete_method = 'disable';
|
||||
|
||||
Reference in New Issue
Block a user