refactor: harden type safety and modernize core forms for Svelte 5
- Standardize 'ae_BaseObj' and event types in 'ae_types.ts' to handle nullable fields from V3 API/Dexie. - Modernize Person, Address, and Contact forms with Svelte 5 Runes and reactive synchronization. - Refactor Event Settings and its sub-components to use the 'onsave' callback pattern, removing deprecated dispatchers. - Hardened 'element_data_store_v2' with safe initialization and localStorage caching logic. - Clean up unused 'element_data_store.svelte' (V1) and suppress Electron environment type errors in 'tmp_shell_handlers.ts'. - Update documentation and workspace settings to reflect Phase 5 reactive patterns.
This commit is contained in:
@@ -12,24 +12,6 @@
|
||||
import { ae_util } from '$lib/ae_utils/ae_utils';
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
|
||||
onMount(() => {
|
||||
console.log(
|
||||
`ae_e_data_store ${ds_code} account_id=${$ae_loc.account_id} for_type=${for_type} for_id=${for_id}`
|
||||
);
|
||||
});
|
||||
|
||||
// export let store: string = 'local';
|
||||
|
||||
let ae_promises: key_val = {};
|
||||
// let ae_tmp: key_val = {};
|
||||
// let ae_triggers: key_val = {};
|
||||
|
||||
let ds_get_results: Promise<any> | key_val = $state();
|
||||
let ds_submit_results: Promise<any> | key_val = $state();
|
||||
|
||||
let val_json: key_val;
|
||||
let val_html: key_val;
|
||||
let val_md: key_val;
|
||||
interface Props {
|
||||
log_lvl?: number;
|
||||
expire_minutes?: number;
|
||||
@@ -73,6 +55,25 @@
|
||||
ds_loading_status = $bindable('starting'),
|
||||
val_sql = $bindable(null)
|
||||
}: Props = $props();
|
||||
|
||||
onMount(() => {
|
||||
console.log(
|
||||
`ae_e_data_store ${ds_code} account_id=${$ae_loc.account_id} for_type=${for_type} for_id=${for_id}`
|
||||
);
|
||||
});
|
||||
|
||||
// export let store: string = 'local';
|
||||
|
||||
let ae_promises: key_val = {};
|
||||
// let ae_tmp: key_val = {};
|
||||
// let ae_triggers: key_val = {};
|
||||
|
||||
let ds_get_results: Promise<any> | key_val | undefined = $state();
|
||||
let ds_submit_results: Promise<any> | key_val | undefined = $state();
|
||||
|
||||
let val_json: key_val;
|
||||
let val_html: key_val;
|
||||
let val_md: key_val;
|
||||
let val_text: string;
|
||||
|
||||
let ds_code_obj = {
|
||||
@@ -94,20 +95,27 @@
|
||||
chk_account_id: null
|
||||
};
|
||||
|
||||
let ae_ds_tmp: key_val = $state();
|
||||
if (browser && try_cache && localStorage.getItem(`ae_ds__${ds_code}`)) {
|
||||
if (log_lvl) {
|
||||
console.log(`ae_e_data_store: Found cached data for ${ds_code}`);
|
||||
let ae_ds_tmp: key_val | undefined = $state();
|
||||
|
||||
// Initialize ae_ds_tmp
|
||||
if (browser && try_cache) {
|
||||
const stored = localStorage.getItem(`ae_ds__${ds_code}`);
|
||||
if (stored) {
|
||||
if (log_lvl) {
|
||||
console.log(`ae_e_data_store: Found cached data for ${ds_code}`);
|
||||
}
|
||||
ae_ds_tmp = JSON.parse(stored);
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`ae_e_data_store cached: ${ds_code} account_id=${$ae_loc.account_id}`,
|
||||
ae_ds_tmp
|
||||
);
|
||||
}
|
||||
}
|
||||
ae_ds_tmp = JSON.parse(localStorage.getItem(`ae_ds__${ds_code}`) ?? '{}');
|
||||
if (log_lvl) {
|
||||
console.log(
|
||||
`ae_e_data_store cached: ${ds_code} account_id=${$ae_loc.account_id}`,
|
||||
ae_ds_tmp
|
||||
);
|
||||
}
|
||||
} else {
|
||||
ae_ds_tmp = ds_code_obj;
|
||||
}
|
||||
|
||||
if (!ae_ds_tmp) {
|
||||
ae_ds_tmp = { ...ds_code_obj };
|
||||
ds_loading_status = 'loading';
|
||||
}
|
||||
|
||||
@@ -200,36 +208,38 @@
|
||||
ds_loaded = true;
|
||||
ds_loading_status = 'loaded';
|
||||
|
||||
// Set the loaded_on datetime to the current time for reference later. This will be used to determine if the data store is stale.
|
||||
ae_ds_tmp.loaded_on = new Date().toISOString();
|
||||
// Set the chk_account_id as a backup check to make sure the data store belongs to the account for the current site. This should not be needed, but here we are...
|
||||
ae_ds_tmp.chk_account_id = $ae_loc.account_id;
|
||||
if (ae_ds_tmp) {
|
||||
// Set the loaded_on datetime to the current time for reference later. This will be used to determine if the data store is stale.
|
||||
ae_ds_tmp.loaded_on = new Date().toISOString();
|
||||
// Set the chk_account_id as a backup check to make sure the data store belongs to the account for the current site. This should not be needed, but here we are...
|
||||
ae_ds_tmp.chk_account_id = $ae_loc.account_id;
|
||||
|
||||
ae_ds_tmp.id = ds_results.data_store_id_random;
|
||||
ae_ds_tmp.account_id = ds_results.account_id_random;
|
||||
ae_ds_tmp.code = ds_results.code; // This will overwrite whatever was passed in.
|
||||
ae_ds_tmp.name = ds_results.name;
|
||||
ae_ds_tmp.type = ds_results.type; // This will overwrite whatever was passed in.
|
||||
if (type == 'html') {
|
||||
ae_ds_tmp.html = ds_results.text;
|
||||
val_html = ds_results.text;
|
||||
return ds_results.html;
|
||||
} else if (type == 'json') {
|
||||
ae_ds_tmp.json = ds_results.json;
|
||||
val_json = ds_results.json;
|
||||
return ds_results.json;
|
||||
} else if (type == 'md') {
|
||||
ae_ds_tmp.text = ds_results.text;
|
||||
val_md = ds_results.text;
|
||||
return ds_results.text;
|
||||
} else if (type == 'sql') {
|
||||
ae_ds_tmp.text = ds_results.text;
|
||||
val_sql = ds_results.text;
|
||||
return ds_results.text;
|
||||
} else {
|
||||
ae_ds_tmp.text = ds_results.text;
|
||||
val_text = ds_results.text;
|
||||
return ds_results.text;
|
||||
ae_ds_tmp.id = ds_results.data_store_id_random;
|
||||
ae_ds_tmp.account_id = ds_results.account_id_random;
|
||||
ae_ds_tmp.code = ds_results.code; // This will overwrite whatever was passed in.
|
||||
ae_ds_tmp.name = ds_results.name;
|
||||
ae_ds_tmp.type = ds_results.type; // This will overwrite whatever was passed in.
|
||||
if (type == 'html') {
|
||||
ae_ds_tmp.html = ds_results.text;
|
||||
val_html = ds_results.text;
|
||||
return ds_results.html;
|
||||
} else if (type == 'json') {
|
||||
ae_ds_tmp.json = ds_results.json;
|
||||
val_json = ds_results.json;
|
||||
return ds_results.json;
|
||||
} else if (type == 'md') {
|
||||
ae_ds_tmp.text = ds_results.text;
|
||||
val_md = ds_results.text;
|
||||
return ds_results.text;
|
||||
} else if (type == 'sql') {
|
||||
ae_ds_tmp.text = ds_results.text;
|
||||
val_sql = ds_results.text;
|
||||
return ds_results.text;
|
||||
} else {
|
||||
ae_ds_tmp.text = ds_results.text;
|
||||
val_text = ds_results.text;
|
||||
return ds_results.text;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ds_loaded = false;
|
||||
@@ -237,7 +247,7 @@
|
||||
}
|
||||
})
|
||||
.then(function () {
|
||||
if (browser && try_cache) {
|
||||
if (browser && try_cache && ae_ds_tmp) {
|
||||
if (log_lvl) {
|
||||
console.log(`ae_e_data_store: Caching data store ${code} in localStorage.`);
|
||||
}
|
||||
@@ -290,7 +300,7 @@
|
||||
}
|
||||
|
||||
// if (!$slct.data_store_id) {
|
||||
if (!ae_ds_tmp.id) {
|
||||
if (ae_ds_tmp && !ae_ds_tmp.id) {
|
||||
data_store_do['account_id_random'] = $ae_loc.account_id;
|
||||
}
|
||||
|
||||
@@ -372,7 +382,7 @@
|
||||
console.log(`ae_ Data Store data out:`, data_store_do);
|
||||
}
|
||||
|
||||
if (!ae_ds_tmp.id) {
|
||||
if (ae_ds_tmp && !ae_ds_tmp.id) {
|
||||
// Create
|
||||
console.log(`ae_ Data Store Create:`, data_store_do);
|
||||
ds_submit_results = handle_create__data_store({
|
||||
@@ -381,18 +391,17 @@
|
||||
})
|
||||
.then(function (ds_results) {
|
||||
console.log(`ae_ Data Store Create Results:`, ds_results);
|
||||
if (ds_results) {
|
||||
if (ds_results && ae_ds_tmp) {
|
||||
ae_ds_tmp.id = ds_results.data_store_id_random;
|
||||
ae_ds_tmp.updated_on = ds_results.updated_on;
|
||||
}
|
||||
return ds_results;
|
||||
})
|
||||
.finally(function (ds_val_result) {
|
||||
console.log(`ae_ ds_val_result = `, ds_val_result);
|
||||
.finally(function () {
|
||||
trigger = 'load__ds__code';
|
||||
$ae_sess.ds.submit_status = 'created';
|
||||
});
|
||||
} else {
|
||||
} else if (ae_ds_tmp) {
|
||||
// Update
|
||||
console.log(`ae_ Data Store Update:`, data_store_do);
|
||||
ds_submit_results = handle_update__data_store({
|
||||
@@ -402,7 +411,7 @@
|
||||
})
|
||||
.then(function (ds_results) {
|
||||
console.log(`ae_ Data Store Update Results:`, ds_results);
|
||||
if (ds_results) {
|
||||
if (ds_results && ae_ds_tmp) {
|
||||
ae_ds_tmp.updated_on = ds_results.updated_on;
|
||||
}
|
||||
return ds_results;
|
||||
@@ -453,9 +462,8 @@
|
||||
console.log(error);
|
||||
return false;
|
||||
})
|
||||
.finally(function (create__obj_result) {
|
||||
.finally(function () {
|
||||
$ae_sess.ds.create_status = 'finished';
|
||||
return create__obj_result;
|
||||
});
|
||||
|
||||
return ae_promises.api_create__data_store_obj;
|
||||
@@ -496,9 +504,8 @@
|
||||
console.log(error);
|
||||
return false;
|
||||
})
|
||||
.finally(function (update__obj_result) {
|
||||
.finally(function () {
|
||||
$ae_sess.ds.update_status = 'finished';
|
||||
return update__obj_result;
|
||||
});
|
||||
|
||||
return ae_promises.update__data_store_obj;
|
||||
@@ -518,7 +525,8 @@
|
||||
type: ds_type,
|
||||
for_type: for_type,
|
||||
for_id: for_id,
|
||||
try_cache: try_cache
|
||||
try_cache: try_cache,
|
||||
log_lvl: log_lvl
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -545,31 +553,21 @@
|
||||
</pre>
|
||||
{/if}
|
||||
|
||||
<!-- {#if show_edit} -->
|
||||
<!-- <section class="edit z-50"> -->
|
||||
|
||||
<!-- Main modal -->
|
||||
<Modal
|
||||
title="{ae_ds_tmp.name} - {ae_ds_tmp.code}"
|
||||
bind:open={show_edit}
|
||||
autoclose={false}
|
||||
size="xl"
|
||||
placement="top-center"
|
||||
class="
|
||||
bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 rounded-lg border-gray-200 dark:border-gray-700 divide-gray-200 dark:divide-gray-700 shadow-md
|
||||
relative flex flex-col
|
||||
mx-auto divide-y
|
||||
w-full
|
||||
max-w-6xl
|
||||
"
|
||||
class="bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 rounded-lg border-gray-200 dark:border-gray-700 divide-gray-200 dark:divide-gray-700 shadow-md relative flex flex-col mx-auto divide-y w-full max-w-6xl"
|
||||
>
|
||||
<form class="flex flex-col gap-1" onsubmit={preventDefault(handle_submit_form)}>
|
||||
<input type="hidden" name="ds_id_random" value={ae_ds_tmp.id} />
|
||||
|
||||
<div class="flex flex-row gap-1">
|
||||
{#if $ae_loc.trusted_access}
|
||||
<label for="ds_use_account_id" class="label text-xs inline"
|
||||
>Use Account ID
|
||||
<label for="ds_use_account_id" class="label text-xs inline">
|
||||
Use Account ID
|
||||
<input
|
||||
type="checkbox"
|
||||
name="ds_use_account_id"
|
||||
@@ -659,13 +657,11 @@
|
||||
/>
|
||||
{:else}
|
||||
Code: {ae_ds_tmp.code}
|
||||
<!-- Name: {ae_ds_tmp.name} -->
|
||||
Type: {ae_ds_tmp.type}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="">
|
||||
<!-- Handle HTML type -->
|
||||
{#if ae_ds_tmp.type == 'html' || ae_ds_tmp.type == null}
|
||||
<textarea
|
||||
name="ds_value"
|
||||
@@ -673,11 +669,8 @@
|
||||
cols="75"
|
||||
rows="25"
|
||||
placeholder="Enter the HTML here"
|
||||
>{ae_ds_tmp.type == 'html' && ae_ds_tmp.html
|
||||
? ae_ds_tmp.html
|
||||
: ''}</textarea
|
||||
>{ae_ds_tmp.type == 'html' && ae_ds_tmp.html ? ae_ds_tmp.html : ''}</textarea
|
||||
>
|
||||
<!-- Handle SQL type -->
|
||||
{:else if ae_ds_tmp.type == 'sql'}
|
||||
<textarea
|
||||
name="ds_value"
|
||||
@@ -685,12 +678,8 @@
|
||||
cols="75"
|
||||
rows="25"
|
||||
placeholder="Enter the SQL here"
|
||||
>{ae_ds_tmp.type == 'sql' && ae_ds_tmp.text
|
||||
? ae_ds_tmp.text
|
||||
: ''}</textarea
|
||||
>{ae_ds_tmp.type == 'sql' && ae_ds_tmp.text ? ae_ds_tmp.text : ''}</textarea
|
||||
>
|
||||
|
||||
<!-- Handle text type -->
|
||||
{:else if ae_ds_tmp.type == 'text'}
|
||||
<textarea
|
||||
name="ds_value"
|
||||
@@ -710,7 +699,6 @@
|
||||
onclick={() => {
|
||||
if (confirm('Are you sure you want to delete this data store?')) {
|
||||
trigger = 'delete__ds__code';
|
||||
// $slct_trigger = 'delete__ds__code';
|
||||
}
|
||||
show_edit = false;
|
||||
show_view = true;
|
||||
@@ -720,25 +708,12 @@
|
||||
Delete
|
||||
</button>
|
||||
|
||||
<!-- <button
|
||||
type="button"
|
||||
class="btn variant-soft-primary"
|
||||
on:click={() => {
|
||||
show_edit = false;
|
||||
show_view = true;
|
||||
}}
|
||||
>
|
||||
<span class="fas fa-times mx-1"></span>
|
||||
Close
|
||||
</button> -->
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="btn preset-tonal-primary border border-primary-500"
|
||||
disabled={ds_submit_results instanceof Promise && !ds_submit_results}
|
||||
onclick={() => {
|
||||
trigger = 'save__ds__code';
|
||||
// $slct_trigger = 'save__ds__code';
|
||||
}}
|
||||
>
|
||||
<span class="fas fa-save mx-1"></span>
|
||||
@@ -772,7 +747,6 @@
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => {
|
||||
console.log('Close modal edit data store.');
|
||||
show_edit = false;
|
||||
show_view = true;
|
||||
}}
|
||||
@@ -785,30 +759,11 @@
|
||||
{/snippet}
|
||||
</Modal>
|
||||
|
||||
<!-- </section> -->
|
||||
<!-- {/if} -->
|
||||
|
||||
<!-- {#if mode == 'view'} -->
|
||||
|
||||
{#if !ae_ds_tmp.type && !ae_ds_tmp.html && !ae_ds_tmp.json && !ae_ds_tmp.md && !ae_ds_tmp.text}
|
||||
{#if $ae_loc.manager_access}
|
||||
<span class="preset-tonal-warning"
|
||||
>No data found! Is the data store correct or new?</span
|
||||
>
|
||||
{:else}
|
||||
<!-- <span class="variant-soft">loading</span> -->
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if ae_ds_tmp.type == 'html' && ae_ds_tmp.html}
|
||||
{@html ae_ds_tmp.html}
|
||||
{:else if ae_ds_tmp.type == 'html'}
|
||||
{#if $ae_loc.manager_access}
|
||||
<span class="preset-tonal-warning"
|
||||
>No HTML found! Is the data store type correct?</span
|
||||
>
|
||||
{:else}
|
||||
<!-- <span class="variant-soft">loading</span> -->
|
||||
<span class="preset-tonal-warning">No HTML found! Is the data store type correct?</span>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -816,11 +771,7 @@
|
||||
{ae_ds_tmp.text}
|
||||
{:else if ae_ds_tmp.type == 'text'}
|
||||
{#if $ae_loc.manager_access}
|
||||
<span class="preset-tonal-warning"
|
||||
>No text found! Is the data store type correct?</span
|
||||
>
|
||||
{:else}
|
||||
<!-- <span class="variant-soft">loading</span> -->
|
||||
<span class="preset-tonal-warning">No text found! Is the data store type correct?</span>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -837,64 +788,23 @@
|
||||
show_edit = true;
|
||||
show_view = false;
|
||||
}}
|
||||
title="Double click to edit data store: {ds_code} with {ae_ds_tmp.account_id
|
||||
? `account ID=${ae_ds_tmp.account_id}`
|
||||
: 'no account ID'}"
|
||||
title="Double click to edit data store: {ds_code}"
|
||||
>
|
||||
<span class="fas fa-edit mx-1"></span>
|
||||
Edit
|
||||
</button>
|
||||
|
||||
<!-- {/if} -->
|
||||
{:else}
|
||||
<!-- Nothing to see yet -->
|
||||
{/if}
|
||||
|
||||
<!-- Text:
|
||||
<pre>
|
||||
{val_text}
|
||||
</pre> -->
|
||||
|
||||
<!-- JSON:
|
||||
<pre>
|
||||
{val_json}
|
||||
</pre> -->
|
||||
|
||||
{#await ds_get_results}
|
||||
<div
|
||||
class="modal-loading text-xs absolute bottom-0 left-0 opacity-30 hover:opacity-100 transition delay-700 hover:delay-200"
|
||||
>
|
||||
<div class="modal-loading text-xs absolute bottom-0 left-0 opacity-30 hover:opacity-100 transition delay-700 hover:delay-200">
|
||||
<span class="fas fa-spinner fa-spin"></span>
|
||||
<span class="loading-text"> Loading... </span>
|
||||
</div>
|
||||
{/await}
|
||||
|
||||
<!-- {ds_loading_status} -->
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
/* .ae_btn_edit__ds {
|
||||
opacity: .5;
|
||||
} */
|
||||
|
||||
/* The section.edit should be above the rest of the content and centered on the page */
|
||||
/*
|
||||
section.edit {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 100;
|
||||
background-color: hsla(0, 0%, 100%, .95);
|
||||
padding: 1rem;
|
||||
border-radius: .5rem;
|
||||
box-shadow: 0 0 1rem hsla(0, 0%, 0%, .5);
|
||||
|
||||
min-width: 80%;
|
||||
}
|
||||
*/
|
||||
|
||||
/* .hide {
|
||||
display: none;
|
||||
} */
|
||||
</style>
|
||||
.ae__elem__data_store {
|
||||
/* Base styles */
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user