Add dirty-tracking to Archive Content edit: disable Save, hide Cancel when unchanged

- ArchiveContentForm interface + factory for controlled input bindings
- obj_changed bindable prop wired to Cancel button visibility in parent page
- Split Save button: edit mode disables when clean, create mode always enabled
- Post-upload/select/remove syncs orig snapshot so file ops do not dirty the form
- Fix archive_content_id_random / archive_id_random → V3 field names in edit component
- Add missing file_extension field to ae_ArchiveContent type

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-05-07 16:57:58 -04:00
parent c71fc65be9
commit c7ebeebe29
3 changed files with 160 additions and 145 deletions

View File

@@ -863,6 +863,7 @@ export interface ae_ArchiveContent extends ae_BaseObj {
hosted_file_id_random?: string; // NO LONGER USE "_random" hosted_file_id_random?: string; // NO LONGER USE "_random"
filename?: string; filename?: string;
file_extension?: string;
subdirectory_path?: string; subdirectory_path?: string;
} }

View File

@@ -51,6 +51,8 @@ import { page } from '$app/state';
// let ae_tmp: key_val = {}; // let ae_tmp: key_val = {};
// let ae_triggers: key_val = {}; // let ae_triggers: key_val = {};
let archive_content_edit_dirty = $state(false);
// *** Quickly pull out data from parent(s) // *** Quickly pull out data from parent(s)
let ae_acct = $derived(data[data.account_id]); let ae_acct = $derived(data[data.account_id]);
$effect(() => { $effect(() => {
@@ -502,8 +504,8 @@ onDestroy(() => {
{#snippet header()} {#snippet header()}
<div class="flex w-full flex-row items-center justify-between"> <div class="flex w-full flex-row items-center justify-between">
<h3 class="text-lg font-semibold"> <h3 class="text-lg font-semibold">
{#if $ae_loc.trusted_access} {#if $ae_loc.trusted_access && (!$idaa_slct.archive_content_id || archive_content_edit_dirty)}
<!-- <div class="ae_options"> --> <!-- Hidden in edit mode when nothing has changed — no unsaved changes to cancel -->
<button <button
type="button" type="button"
onclick={() => { onclick={() => {
@@ -517,7 +519,6 @@ onDestroy(() => {
title={`View meeting: ${$lq__archive_content_obj?.name}`}> title={`View meeting: ${$lq__archive_content_obj?.name}`}>
<span class="fas fa-eye m-1"></span> Cancel <span class="fas fa-eye m-1"></span> Cancel
</button> </button>
<!-- </div> -->
{/if} {/if}
<span class="text-sm text-gray-500"> Edit Content: </span> <span class="text-sm text-gray-500"> Edit Content: </span>
@@ -526,7 +527,7 @@ onDestroy(() => {
</div> </div>
{/snippet} {/snippet}
<Archive_content_obj_id_edit {lq__archive_content_obj} /> <Archive_content_obj_id_edit {lq__archive_content_obj} bind:obj_changed={archive_content_edit_dirty} />
{#snippet footer()} {#snippet footer()}
<button <button

View File

@@ -28,9 +28,10 @@ import Element_manage_hosted_file_li_wrap from '$lib/elements/element_manage_hos
interface Props { interface Props {
log_lvl?: number; log_lvl?: number;
lq__archive_content_obj: any; lq__archive_content_obj: any;
obj_changed?: boolean;
} }
let { log_lvl = 0, lq__archive_content_obj }: Props = $props(); let { log_lvl = 0, lq__archive_content_obj, obj_changed = $bindable(false) }: Props = $props();
let create_archive_content_obj_promise: any; let create_archive_content_obj_promise: any;
let delete_archive_content_obj_promise: any; let delete_archive_content_obj_promise: any;
@@ -42,9 +43,7 @@ let prom_api__archive_content_obj__hosted_file: any = $state();
let description_new_html = $state( let description_new_html = $state(
$idaa_slct.archive_content_obj?.description ?? '' $idaa_slct.archive_content_obj?.description ?? ''
); );
let description_changed = $state(false);
let notes_new_html = $state($idaa_slct.archive_content_obj?.notes ?? ''); let notes_new_html = $state($idaa_slct.archive_content_obj?.notes ?? '');
let notes_changed = $state(false);
let disable_submit_btn = $state(false); let disable_submit_btn = $state(false);
let slct_hosted_file_kv: key_val = $state({}); let slct_hosted_file_kv: key_val = $state({});
@@ -83,7 +82,7 @@ if ($idaa_slct.archive_content_id) {
} else { } else {
$idaa_slct.archive_content_id = null; $idaa_slct.archive_content_id = null;
$idaa_slct.archive_content_obj = { $idaa_slct.archive_content_obj = {
archive_id_random: null, archive_id: null,
// archive_content_id_random: null, // archive_content_id_random: null,
archive_content_type: 'hosted_file', archive_content_type: 'hosted_file',
name: null, name: null,
@@ -114,6 +113,56 @@ if ($idaa_slct.archive_content_id) {
); );
} }
// Form shape for controlled inputs — enables dirty detection via snapshot comparison.
// Initialized AFTER the init block above so new-item defaults are in place.
interface ArchiveContentForm {
name: string;
archive_content_type: string;
filename: string;
file_extension: string;
original_datetime_date: string;
original_datetime_time: string;
original_timezone: string;
original_location: string;
hide: boolean;
priority: boolean | null;
enable: boolean;
sort: number | null;
group: string;
}
function create_archive_content_form(obj: any, current_timezone = ''): ArchiveContentForm {
return {
name: obj?.name ?? '',
archive_content_type: obj?.archive_content_type ?? 'hosted_file',
filename: obj?.filename ?? '',
file_extension: obj?.file_extension ?? '',
original_datetime_date: obj?.original_datetime
? ae_util.iso_datetime_formatter(obj.original_datetime, 'date_iso')
: '',
original_datetime_time: obj?.original_datetime
? ae_util.iso_datetime_formatter(obj.original_datetime, 'time_iso')
: '',
original_timezone: obj?.original_timezone ?? current_timezone,
original_location: obj?.original_location ?? '',
hide: obj?.hide ?? false,
priority: obj?.priority ?? null,
enable: obj?.enable ?? true,
sort: obj?.sort ?? null,
group: obj?.group ?? ''
};
}
let archive_content_form = $state(
create_archive_content_form($idaa_slct.archive_content_obj, $ae_loc.current_timezone)
);
let orig_archive_content_form = $state(
create_archive_content_form($idaa_slct.archive_content_obj, $ae_loc.current_timezone)
);
// Plain (non-reactive) snapshots for TipTap content comparison
let orig_description_html = $idaa_slct.archive_content_obj?.description ?? '';
let orig_notes_html = $idaa_slct.archive_content_obj?.notes ?? '';
// Timezone lookup — reactive IDB query; background refresh handled by liveQuery + TTL // Timezone lookup — reactive IDB query; background refresh handled by liveQuery + TTL
// Sort: sort DESC (higher = first, NULL=0 last), then name ASC — matches Aether backend convention. // Sort: sort DESC (higher = first, NULL=0 last), then name ASC — matches Aether backend convention.
const lq__lu_time_zone = liveQuery(() => const lq__lu_time_zone = liveQuery(() =>
@@ -138,6 +187,13 @@ function prevent_default<T extends Event>(fn: (event: T) => void) {
}; };
} }
function mark_archive_content_form_saved() {
orig_archive_content_form = JSON.parse(JSON.stringify(archive_content_form));
orig_description_html = description_new_html;
orig_notes_html = notes_new_html;
obj_changed = false;
}
async function handle_submit_form(event: SubmitEvent) { async function handle_submit_form(event: SubmitEvent) {
if (log_lvl > 1) { if (log_lvl > 1) {
console.log('*** handle_submit_form() ***'); console.log('*** handle_submit_form() ***');
@@ -163,7 +219,7 @@ async function handle_submit_form(event: SubmitEvent) {
let archive_content_do: key_val = {}; let archive_content_do: key_val = {};
if (!$idaa_slct.archive_content_id) { if (!$idaa_slct.archive_content_id) {
archive_content_do['archive_id_random'] = $idaa_slct.archive_id; archive_content_do['archive_id'] = $idaa_slct.archive_id;
} }
archive_content_do['name'] = archive_content_di.name; archive_content_do['name'] = archive_content_di.name;
@@ -253,21 +309,16 @@ async function handle_submit_form(event: SubmitEvent) {
} }
$idaa_slct.archive_content_id = $idaa_slct.archive_content_id =
archive_content_obj_create_result.archive_content_id_random; archive_content_obj_create_result.archive_content_id;
// $idaa_slct.archive_content_obj = await $lq__archive_content_obj;
// $idaa_slct.archive_content_obj.hosted_file_id_li = [];
// $idaa_slct.archive_content_obj.hosted_file_obj_li = [];
// $idaa_slct.archive_content_obj.upload_complete = false;
// $idaa_slct.archive_content_obj.description_new_html = '';
$idaa_slct.archive_content_obj = $idaa_slct.archive_content_obj =
archive_content_obj_create_result; archive_content_obj_create_result;
$idaa_slct.archive_content_obj.archive_content_id =
archive_content_obj_create_result.archive_content_id_random; // This is because we need use the string ID, not int ID.
$idaa_slct.archive_content_obj.upload_complete = false; $idaa_slct.archive_content_obj.upload_complete = false;
$idaa_slct.archive_content_obj.hosted_file_id_li = []; $idaa_slct.archive_content_obj.hosted_file_id_li = [];
$idaa_slct.archive_content_obj.hosted_file_obj_li = []; $idaa_slct.archive_content_obj.hosted_file_obj_li = [];
mark_archive_content_form_saved();
return archive_content_obj_create_result; return archive_content_obj_create_result;
}) })
.catch(function (error: any) { .catch(function (error: any) {
@@ -305,6 +356,7 @@ async function handle_submit_form(event: SubmitEvent) {
// We need to do all of this since the DB object has changed and the SLCT object does automatically update (yet...??? Svelte 5?). // We need to do all of this since the DB object has changed and the SLCT object does automatically update (yet...??? Svelte 5?).
// $idaa_slct.archive_content_obj = await $lq__archive_content_obj; // $idaa_slct.archive_content_obj = await $lq__archive_content_obj;
mark_archive_content_form_saved();
$idaa_slct.archive_content_id = null; $idaa_slct.archive_content_id = null;
$idaa_slct.archive_content_obj = {}; $idaa_slct.archive_content_obj = {};
$idaa_sess.archives.show__modal_edit__archive_content_id = false; $idaa_sess.archives.show__modal_edit__archive_content_id = false;
@@ -350,6 +402,12 @@ async function handle_hosted_files_uploaded(
) { ) {
$idaa_slct.archive_content_obj.hosted_file_obj_li = []; $idaa_slct.archive_content_obj.hosted_file_obj_li = [];
} }
// Sync form and snapshot so a successful upload doesn't mark the form as dirty.
archive_content_form.filename = archive_content_obj_update_result?.filename ?? '';
archive_content_form.file_extension = archive_content_obj_update_result?.file_extension ?? '';
archive_content_form.archive_content_type = 'hosted_file';
orig_archive_content_form = JSON.parse(JSON.stringify(archive_content_form));
}) })
.catch(function (error: any) { .catch(function (error: any) {
console.log('Something went wrong.'); console.log('Something went wrong.');
@@ -358,6 +416,24 @@ async function handle_hosted_files_uploaded(
}); });
} }
// Dirty detection — edit mode only. Create mode Save is always available.
$effect(() => {
if (!$idaa_slct.archive_content_id) return;
const form_changed =
JSON.stringify(archive_content_form) !== JSON.stringify(orig_archive_content_form);
const has_changes =
form_changed ||
description_new_html !== orig_description_html ||
notes_new_html !== orig_notes_html;
if (!obj_changed && has_changes) {
obj_changed = true;
} else if (obj_changed && !has_changes) {
obj_changed = false;
}
});
$effect(() => { $effect(() => {
if ( if (
upload_complete_local && upload_complete_local &&
@@ -414,6 +490,12 @@ $effect(() => {
) { ) {
$idaa_slct.archive_content_obj.hosted_file_obj_li = []; $idaa_slct.archive_content_obj.hosted_file_obj_li = [];
} }
// Sync form and snapshot so selecting an existing file doesn't mark form as dirty.
archive_content_form.filename = archive_content_obj_update_result?.filename ?? '';
archive_content_form.file_extension = archive_content_obj_update_result?.file_extension ?? '';
archive_content_form.archive_content_type = 'hosted_file';
orig_archive_content_form = JSON.parse(JSON.stringify(archive_content_form));
}) })
.catch(function (error: any) { .catch(function (error: any) {
console.log('Something went wrong.'); console.log('Something went wrong.');
@@ -465,9 +547,7 @@ $effect(() => {
name="name" name="name"
required required
max="200" max="200"
value={$idaa_slct.archive_content_obj?.name bind:value={archive_content_form.name}
? $idaa_slct.archive_content_obj.name
: ''}
autocomplete="off" autocomplete="off"
class=" class="
input preset-tonal-surface input preset-tonal-surface
@@ -493,43 +573,16 @@ $effect(() => {
<select <select
id="archive_content_type" id="archive_content_type"
name="archive_content_type" name="archive_content_type"
bind:value={ bind:value={archive_content_form.archive_content_type}
$idaa_slct.archive_content_obj.archive_content_type
}
class="select w-52"> class="select w-52">
<option value="">-- None --</option> <option value="">-- None --</option>
<option value="hosted_file" selected <option value="hosted_file">Hosted File in Æ</option>
>Hosted File in Æ</option>
<option value="html">Hosted HTML in Æ</option> <option value="html">Hosted HTML in Æ</option>
<option value="json">Hosted JSON in Æ</option> <option value="json">Hosted JSON in Æ</option>
<option value="url">External URL</option> <option value="url">External URL</option>
<option value="other">Other</option> <option value="other">Other</option>
</select> </select>
</label> </label>
<!-- <fieldset class="">
<legend class="">Public Access with Rotating Access Key/Passcode</legend>
<label for="enable_for_public_no" class="">No, disable public access
<input
type="radio"
class="radio"
id="enable_for_public_no"
name="enable_for_public"
value={false}
bind:group={$idaa_slct.archive_content_obj.enable_for_public}
>
</label>
<label for="enable_for_public_yes" class="">Yes, allow public access
<input
type="radio"
class="radio"
id="enable_for_public_yes"
name="enable_for_public"
value={true}
bind:group={$idaa_slct.archive_content_obj.enable_for_public}
>
</label>
</fieldset> -->
</div> </div>
{#if $idaa_slct.archive_content_id} {#if $idaa_slct.archive_content_id}
@@ -605,11 +658,11 @@ $effect(() => {
.add_to_use_files_method != 'select'} .add_to_use_files_method != 'select'}
class=""> class="">
<Element_manage_hosted_file_li_wrap <Element_manage_hosted_file_li_wrap
link_to_type={'account'} link_to_type="account"
link_to_id={$ae_loc?.account_id} link_to_id={$ae_loc?.account_id}
allow_basic={true} allow_basic={true}
allow_moderator={true} allow_moderator={true}
class_li={''} class_li=""
bind:slct_hosted_file_kv bind:slct_hosted_file_kv
bind:slct_hosted_file_id bind:slct_hosted_file_id
bind:slct_hosted_file_obj /> bind:slct_hosted_file_obj />
@@ -639,7 +692,7 @@ $effect(() => {
fake_delete: false, fake_delete: false,
log_lvl: log_lvl log_lvl: log_lvl
}) })
.then(function (delete_result) { .then(function () {
// Second - If deleted, then update the archive_content_obj // Second - If deleted, then update the archive_content_obj
console.log( console.log(
`File removed. Now update the archive_content_obj` `File removed. Now update the archive_content_obj`
@@ -664,10 +717,7 @@ $effect(() => {
log_lvl: log_lvl log_lvl: log_lvl
} }
) )
.then( .then(function () {
function (
archive_content_obj_update_result
) {
// We need to do all of this since the DB object has changed and the SLCT object does automatically update (yet...??? Svelte 5?). // We need to do all of this since the DB object has changed and the SLCT object does automatically update (yet...??? Svelte 5?).
// $idaa_slct.archive_content_obj = $lq__archive_content_obj; // $idaa_slct.archive_content_obj = $lq__archive_content_obj;
} }
@@ -705,6 +755,11 @@ $effect(() => {
[]; [];
$idaa_slct.archive_content_obj.hosted_file_obj_li = $idaa_slct.archive_content_obj.hosted_file_obj_li =
[]; [];
// Sync form snapshot after file removal
archive_content_form.filename = '';
archive_content_form.file_extension = '';
orig_archive_content_form = JSON.parse(JSON.stringify(archive_content_form));
}); });
} }
}} }}
@@ -715,35 +770,15 @@ $effect(() => {
<span class="fas fa-trash-alt m-1"></span> <span class="fas fa-trash-alt m-1"></span>
Remove File Remove File
{/await} {/await}
<!-- <span class="fas fa-trash-alt m-1"></span>
Remove File -->
</button> </button>
<!-- <label for="file_path">File Path
{#if !$ae_loc.administrator_access}
<span class="fas fa-lock" title="Field is locked"></span>
{:else}
<span class="fas fa-unlock" title="Field is unlocked"></span>
{/if}
<input
type="text"
id="file_path"
name="file_path"
value={($idaa_slct.archive_content_obj.file_path ? $idaa_slct.archive_content_obj.file_path : '')}
readonly={!$ae_loc.administrator_access}
class="input w-full"
>
</label> -->
<label for="filename" <label for="filename"
>Filename >Filename
<input <input
type="text" type="text"
id="filename" id="filename"
name="filename" name="filename"
value={$idaa_slct.archive_content_obj.filename bind:value={archive_content_form.filename}
? $idaa_slct.archive_content_obj.filename
: 'unknown'}
class="input w-full" /> class="input w-full" />
</label> </label>
@@ -761,9 +796,7 @@ $effect(() => {
type="text" type="text"
id="file_extension" id="file_extension"
name="file_extension" name="file_extension"
value={$idaa_slct.archive_content_obj.file_extension bind:value={archive_content_form.file_extension}
? $idaa_slct.archive_content_obj.file_extension
: 'ext'}
readonly={!$ae_loc.administrator_access} readonly={!$ae_loc.administrator_access}
class="input w-24" /> class="input w-24" />
</label> </label>
@@ -787,24 +820,14 @@ $effect(() => {
type="date" type="date"
id="original_datetime_date" id="original_datetime_date"
name="original_datetime_date" name="original_datetime_date"
value={$idaa_slct.archive_content_obj.original_datetime bind:value={archive_content_form.original_datetime_date}
? ae_util.iso_datetime_formatter(
$idaa_slct.archive_content_obj.original_datetime,
'date_iso'
)
: ''}
placeholder="YYYY-MM-DD" placeholder="YYYY-MM-DD"
class="input w-48" /> class="input w-48" />
<input <input
type="time" type="time"
id="original_datetime_time" id="original_datetime_time"
name="original_datetime_time" name="original_datetime_time"
value={$idaa_slct.archive_content_obj.original_datetime bind:value={archive_content_form.original_datetime_time}
? ae_util.iso_datetime_formatter(
$idaa_slct.archive_content_obj.original_datetime,
'time_iso'
)
: ''}
placeholder="HH:MM AM/PM" placeholder="HH:MM AM/PM"
class="input w-48" /> class="input w-48" />
</label> </label>
@@ -816,11 +839,7 @@ $effect(() => {
<select <select
id="original_timezone" id="original_timezone"
name="original_timezone" name="original_timezone"
value={$idaa_slct.archive_content_obj bind:value={archive_content_form.original_timezone}
.original_timezone
? $idaa_slct.archive_content_obj
.original_timezone
: $ae_loc.current_timezone}
class="select w-56" class="select w-56"
title="Select the original timezone"> title="Select the original timezone">
<option value="">-- None --</option> <option value="">-- None --</option>
@@ -834,11 +853,7 @@ $effect(() => {
<input <input
type="text" type="text"
name="timezone" name="timezone"
value={$idaa_slct.archive_content_obj bind:value={archive_content_form.original_timezone}
.original_timezone
? $idaa_slct.archive_content_obj
.original_timezone
: $ae_loc.current_timezone}
class="input w-56" /> class="input w-56" />
{/if} {/if}
</label> </label>
@@ -850,7 +865,7 @@ $effect(() => {
type="text" type="text"
id="original_location" id="original_location"
name="original_location" name="original_location"
value={$idaa_slct.archive_content_obj.original_location} bind:value={archive_content_form.original_location}
class="input w-96" /> class="input w-96" />
</label> </label>
</div> </div>
@@ -895,9 +910,7 @@ $effect(() => {
id="hide_yes" id="hide_yes"
name="hide" name="hide"
value={true} value={true}
bind:group={ bind:group={archive_content_form.hide}
$idaa_slct.archive_content_obj.hide
}
class="radio form-check-input" /> class="radio form-check-input" />
<label for="hide_yes">Yes</label> <label for="hide_yes">Yes</label>
</div> </div>
@@ -907,9 +920,7 @@ $effect(() => {
id="hide_no" id="hide_no"
name="hide" name="hide"
value={false} value={false}
bind:group={ bind:group={archive_content_form.hide}
$idaa_slct.archive_content_obj.hide
}
class="radio form-check-input" /> class="radio form-check-input" />
<label for="hide_no">No</label> <label for="hide_no">No</label>
</div> </div>
@@ -926,10 +937,7 @@ $effect(() => {
id="priority_yes" id="priority_yes"
name="priority" name="priority"
value={true} value={true}
bind:group={ bind:group={archive_content_form.priority}
$idaa_slct.archive_content_obj
.priority
}
class="radio form-check-input" /> class="radio form-check-input" />
<label for="priority_yes">Yes</label> <label for="priority_yes">Yes</label>
</div> </div>
@@ -939,10 +947,7 @@ $effect(() => {
id="priority_no" id="priority_no"
name="priority" name="priority"
value={false} value={false}
bind:group={ bind:group={archive_content_form.priority}
$idaa_slct.archive_content_obj
.priority
}
class="radio form-check-input" /> class="radio form-check-input" />
<label for="priority_no">No</label> <label for="priority_no">No</label>
</div> </div>
@@ -960,7 +965,7 @@ $effect(() => {
>Sort <input >Sort <input
type="number" type="number"
name="sort" name="sort"
value={$idaa_slct.archive_content_obj.sort} bind:value={archive_content_form.sort}
class="input preset-tonal-surface form-control w-24" /></label> class="input preset-tonal-surface form-control w-24" /></label>
<label <label
@@ -968,8 +973,7 @@ $effect(() => {
>Group <input >Group <input
type="text" type="text"
name="group" name="group"
value={$idaa_slct.archive_content_obj bind:value={archive_content_form.group}
.group ?? ''}
max="100" max="100"
class="input preset-tonal-surface form-control w-40" /></label> class="input preset-tonal-surface form-control w-40" /></label>
</span> </span>
@@ -988,10 +992,7 @@ $effect(() => {
id="enable_yes" id="enable_yes"
name="enable" name="enable"
value={true} value={true}
bind:group={ bind:group={archive_content_form.enable}
$idaa_slct.archive_content_obj
.enable
}
class="radio form-check-input" /> class="radio form-check-input" />
<label for="enable_yes">Yes</label> <label for="enable_yes">Yes</label>
</div> </div>
@@ -1001,10 +1002,7 @@ $effect(() => {
id="enable_no" id="enable_no"
name="enable" name="enable"
value={false} value={false}
bind:group={ bind:group={archive_content_form.enable}
$idaa_slct.archive_content_obj
.enable
}
class="radio form-check-input" /> class="radio form-check-input" />
<label for="enable_no">No</label> <label for="enable_no">No</label>
</div> </div>
@@ -1014,7 +1012,7 @@ $effect(() => {
<input <input
type="hidden" type="hidden"
name="enable" name="enable"
value={$idaa_slct.archive_content_obj.enable} /> value={archive_content_form.enable} />
{/if} {/if}
</span> </span>
@@ -1049,22 +1047,37 @@ $effect(() => {
d-flex align-items-center justify-content-between flex w-full flex-row d-flex align-items-center justify-content-between flex w-full flex-row
items-center justify-between gap-1 items-center justify-between gap-1
"> ">
<button {#if $idaa_slct.archive_content_id}
type="submit" <button
disabled={disable_submit_btn} type="submit"
class=" disabled={disable_submit_btn || !obj_changed}
novi_btn class="
btn btn-md preset-tonal-primary preset-outlined-primary-800-200 hover:preset-filled-primary-200-800 novi_btn
transition btn btn-md preset-tonal-primary preset-outlined-primary-800-200 hover:preset-filled-primary-200-800
"> transition
{#await prom_api__archive_content_obj} ">
<span class="fas fa-spinner fa-spin m-1"></span> Saving {#await prom_api__archive_content_obj}
{:then} <span class="fas fa-spinner fa-spin m-1"></span> Saving
<span class="fas fa-save m-1"></span> Save Changes {:then}
{/await} <span class="fas fa-save m-1"></span> Save Changes
<!-- <span class="fas fa-check m-1"></span> --> {/await}
<!-- Save Archive Content --> </button>
</button> {:else}
<button
type="submit"
disabled={disable_submit_btn}
class="
novi_btn
btn btn-md preset-tonal-warning hover:preset-filled-warning-200-800
transition
">
{#await prom_api__archive_content_obj}
<span class="fas fa-spinner fa-spin m-1"></span> Saving
{:then}
<span class="fas fa-save m-1"></span> Save New Content
{/await}
</button>
{/if}
{#if $idaa_slct.archive_content_id && !$idaa_slct.archive_content_obj?.hosted_file_id} {#if $idaa_slct.archive_content_id && !$idaa_slct.archive_content_obj?.hosted_file_id}
<button <button