Other areas of the AE SvelteKit primary routes.

This commit is contained in:
Scott Idem
2026-03-24 12:18:27 -04:00
parent 6018a94499
commit e1338b1a72
13 changed files with 1607 additions and 1026 deletions

View File

@@ -6,14 +6,17 @@ import type { RequestHandler } from './$types';
* Used by Docker and Nginx to verify the service is running. * Used by Docker and Nginx to verify the service is running.
*/ */
export const GET: RequestHandler = async () => { export const GET: RequestHandler = async () => {
return json({ return json(
status: 'healthy', {
timestamp: new Date().toISOString(), status: 'healthy',
service: 'aether-app-sveltekit', timestamp: new Date().toISOString(),
node_env: process.env.NODE_ENV || 'development' service: 'aether-app-sveltekit',
}, { node_env: process.env.NODE_ENV || 'development'
headers: { },
'Cache-Control': 'no-cache' {
headers: {
'Cache-Control': 'no-cache'
}
} }
}); );
}; };

View File

@@ -1,34 +1,34 @@
<script lang="ts"> <script lang="ts">
/** @type {import('./$types').LayoutData} */
let log_lvl: number = 1;
// *** Import Svelte specific
// import { browser } from '$app/environment';
// *** Import other supporting libraries
import { Brain, House, Library, RefreshCw, Satellite } from '@lucide/svelte';
// *** Import Aether specific variables and functions
// import type { key_val } from '$lib/ae_stores';
// import { ae_util } from '$lib/ae_utils/ae_utils';
import {
ae_snip,
ae_loc,
ae_sess,
ae_api,
ae_trig,
slct,
slct_trigger
} from '$lib/stores/ae_stores';
// import Element_data_store from '$lib/elements/element_data_store.svelte';
interface Props {
/** @type {import('./$types').LayoutData} */ /** @type {import('./$types').LayoutData} */
let log_lvl: number = 1; data: any;
children?: import('svelte').Snippet;
}
// *** Import Svelte specific let { data, children }: Props = $props();
// import { browser } from '$app/environment';
// *** Import other supporting libraries
import { Brain, House, Library, RefreshCw, Satellite } from '@lucide/svelte';
// *** Import Aether specific variables and functions
// import type { key_val } from '$lib/ae_stores';
// import { ae_util } from '$lib/ae_utils/ae_utils';
import {
ae_snip,
ae_loc,
ae_sess,
ae_api,
ae_trig,
slct,
slct_trigger
} from '$lib/stores/ae_stores';
// import Element_data_store from '$lib/elements/element_data_store.svelte';
interface Props {
/** @type {import('./$types').LayoutData} */
data: any;
children?: import('svelte').Snippet;
}
let { data, children }: Props = $props();
</script> </script>
<svelte:head> <svelte:head>
@@ -40,11 +40,10 @@
class:iframe={$ae_loc?.iframe} class:iframe={$ae_loc?.iframe}
class=" class="
ae_hosted_files ae_hosted_files
h-full max-h-full max-w-6xl overflow-auto m-auto flex h-full max-h-full
flex flex-col gap-1 max-w-6xl flex-col gap-1
m-auto overflow-auto
" ">
>
<nav <nav
class=" class="
submenu submenu
@@ -55,8 +54,7 @@
p-1 p-1
px-2 px-2
pb-2 pb-2
" ">
>
<span class="justify-self-start"> <span class="justify-self-start">
<!-- Be sure to explain what &AElig; (Aether) means in the title text or similar! --> <!-- Be sure to explain what &AElig; (Aether) means in the title text or similar! -->
<Satellite size="1.5em" class="mx-1 inline-block text-gray-500" /> <Satellite size="1.5em" class="mx-1 inline-block text-gray-500" />
@@ -68,14 +66,15 @@
/> --> /> -->
<a <a
href="/" href="/"
class="btn btn-sm preset-tonal-surface border border-surface-500 hover:preset-filled-success-500" class="btn btn-sm preset-tonal-surface border-surface-500 hover:preset-filled-success-500 border">
>
<House /> <House />
<span class="hidden md:inline"> Home </span> <span class="hidden md:inline"> Home </span>
</a> </a>
</nav> </nav>
<section class:iframe={$ae_loc?.iframe} class="main_content grow px-1 md:px-2 pb-28"> <section
class:iframe={$ae_loc?.iframe}
class="main_content grow px-1 pb-28 md:px-2">
{@render children?.()} {@render children?.()}
</section> </section>
</div> </div>

View File

@@ -27,7 +27,9 @@ export async function load({ params, parent, url }) {
const qry_limit = parseInt(url.searchParams.get('limit') ?? '19'); const qry_limit = parseInt(url.searchParams.get('limit') ?? '19');
if (!qry_limit) { if (!qry_limit) {
console.log(`qry_limit +page.ts: The qry_limit was not found in the params!!!`); console.log(
`qry_limit +page.ts: The qry_limit was not found in the params!!!`
);
} }
ae_acct.slct.qry_limit = qry_limit; ae_acct.slct.qry_limit = qry_limit;

View File

@@ -1,90 +1,96 @@
<script lang="ts"> <script lang="ts">
// console.log(`ae_ Svelte Hosted Files +page data:`, data); // console.log(`ae_ Svelte Hosted Files +page data:`, data);
import { onMount } from 'svelte'; import { onMount } from 'svelte';
// import { api } from '$lib/api.js'; // import { api } from '$lib/api.js';
import { ae_loc, ae_sess, ae_api, slct, slct_trigger } from '$lib/stores/ae_stores'; import {
// import { ae_util } from '$lib/ae_utils/ae_utils'; ae_loc,
import type { key_val } from '$lib/stores/ae_stores'; ae_sess,
ae_api,
slct,
slct_trigger
} from '$lib/stores/ae_stores';
// import { ae_util } from '$lib/ae_utils/ae_utils';
import type { key_val } from '$lib/stores/ae_stores';
import Element_manage_hosted_file_li_wrap from '$lib/elements/element_manage_hosted_file_li_all.svelte'; import Element_manage_hosted_file_li_wrap from '$lib/elements/element_manage_hosted_file_li_all.svelte';
import { Video } from '@lucide/svelte'; import { Video } from '@lucide/svelte';
let { data } = $props(); let { data } = $props();
let log_lvl = 0; let log_lvl = 0;
let ae_promises: key_val = {}; let ae_promises: key_val = {};
// export let container_class_li = []; // export let container_class_li = [];
let file_uploads_post_promise; let file_uploads_post_promise;
let download_src; let download_src;
let download_filename; let download_filename;
if (!$ae_loc.files) { if (!$ae_loc.files) {
$ae_loc.files = {}; $ae_loc.files = {};
$ae_loc.files.processed_file_kv = {}; $ae_loc.files.processed_file_kv = {};
$ae_loc.files.uploaded_file_kv = {}; $ae_loc.files.uploaded_file_kv = {};
$ae_loc.files.video_clip_file_kv = {}; $ae_loc.files.video_clip_file_kv = {};
// $ae_loc.files.uploaded_file_list = []; // $ae_loc.files.uploaded_file_list = [];
// $ae_loc.files.video_clip_file_list = []; // $ae_loc.files.video_clip_file_list = [];
} }
if (!$ae_loc.files.processed_file_kv) { if (!$ae_loc.files.processed_file_kv) {
$ae_loc.files.processed_file_kv = {}; $ae_loc.files.processed_file_kv = {};
}
$effect(() => {
// if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_li) {
// // Append this list to the $ae_loc.files.uploaded_file_li list
// $ae_loc.files.uploaded_file_li = [
// ...$ae_loc.files.uploaded_file_li,
// ...$ae_sess.files.uploaded_file_li
// ];
// }
if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_kv) {
// Add this key-value pair to the $ae_loc.files.uploaded_file_kv object
$ae_loc.files.uploaded_file_kv = {
...$ae_loc.files.uploaded_file_kv,
...$ae_sess.files.uploaded_file_kv
};
$ae_sess.files.upload_complete = false;
} }
$effect(() => { if ($ae_sess.files.clip_complete && $ae_sess.files.video_clip_file_kv) {
// if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_li) { // Add this key-value pair to the $ae_loc.files.video_clip_file_kv object
// // Append this list to the $ae_loc.files.uploaded_file_li list $ae_loc.files.video_clip_file_kv = {
// $ae_loc.files.uploaded_file_li = [ ...$ae_loc.files.video_clip_file_kv,
// ...$ae_loc.files.uploaded_file_li, ...$ae_sess.files.video_clip_file_kv
// ...$ae_sess.files.uploaded_file_li };
// ]; $ae_sess.files.clip_complete = false;
// } }
});
if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_kv) { // $effect(() => {
// Add this key-value pair to the $ae_loc.files.uploaded_file_kv object // if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_kv) {
$ae_loc.files.uploaded_file_kv = { // // Add this key-value pair to the $ae_loc.files.uploaded_file_kv object
...$ae_loc.files.uploaded_file_kv, // $ae_loc.files.uploaded_file_kv = {
...$ae_sess.files.uploaded_file_kv // ...$ae_loc.files.uploaded_file_kv,
}; // ...$ae_sess.files.uploaded_file_kv
$ae_sess.files.upload_complete = false; // };
} // }
// });
if ($ae_sess.files.clip_complete && $ae_sess.files.video_clip_file_kv) { // $effect(() => {
// Add this key-value pair to the $ae_loc.files.video_clip_file_kv object // if ($ae_sess.files.clip_complete && $ae_sess.files.video_clip_file_kv) {
$ae_loc.files.video_clip_file_kv = { // // Add this key-value pair to the $ae_loc.files.video_clip_file_kv object
...$ae_loc.files.video_clip_file_kv, // $ae_loc.files.video_clip_file_kv = {
...$ae_sess.files.video_clip_file_kv // ...$ae_loc.files.video_clip_file_kv,
}; // ...$ae_sess.files.video_clip_file_kv
$ae_sess.files.clip_complete = false; // };
} // }
}); // });
// $effect(() => { onMount(() => {
// if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_kv) { console.log('Hosted Files: AV Utilities +page.svelte');
// // Add this key-value pair to the $ae_loc.files.uploaded_file_kv object });
// $ae_loc.files.uploaded_file_kv = {
// ...$ae_loc.files.uploaded_file_kv,
// ...$ae_sess.files.uploaded_file_kv
// };
// }
// });
// $effect(() => {
// if ($ae_sess.files.clip_complete && $ae_sess.files.video_clip_file_kv) {
// // Add this key-value pair to the $ae_loc.files.video_clip_file_kv object
// $ae_loc.files.video_clip_file_kv = {
// ...$ae_loc.files.video_clip_file_kv,
// ...$ae_sess.files.video_clip_file_kv
// };
// }
// });
onMount(() => {
console.log('Hosted Files: AV Utilities +page.svelte');
});
</script> </script>
<!-- <section <!-- <section
@@ -123,8 +129,7 @@
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={'max-h-full'} class_li={'max-h-full'} />
/>
<!-- </div> --> <!-- </div> -->

View File

@@ -1,123 +1,129 @@
<script lang="ts"> <script lang="ts">
import { run } from 'svelte/legacy'; import { run } from 'svelte/legacy';
// console.log(`ae_ Svelte Hosted Files +page data:`, data); // console.log(`ae_ Svelte Hosted Files +page data:`, data);
import { onMount } from 'svelte'; import { onMount } from 'svelte';
// import { api } from '$lib/api.js'; // import { api } from '$lib/api.js';
import { ae_loc, ae_sess, ae_api, slct, slct_trigger } from '$lib/stores/ae_stores'; import {
// import { ae_util } from '$lib/ae_utils/ae_utils'; ae_loc,
import type { key_val } from '$lib/stores/ae_stores'; ae_sess,
ae_api,
slct,
slct_trigger
} from '$lib/stores/ae_stores';
// import { ae_util } from '$lib/ae_utils/ae_utils';
import type { key_val } from '$lib/stores/ae_stores';
import Comp_hosted_files_upload from '$lib/ae_core/ae_comp__hosted_files_upload.svelte'; import Comp_hosted_files_upload from '$lib/ae_core/ae_comp__hosted_files_upload.svelte';
import Comp_hosted_files_clip_video from '$lib/ae_core/ae_comp__hosted_files_clip_video.svelte'; import Comp_hosted_files_clip_video from '$lib/ae_core/ae_comp__hosted_files_clip_video.svelte';
import Comp_hosted_files_clip_video_li from '$lib/ae_core/ae_comp__hosted_files_clip_video_li.svelte'; import Comp_hosted_files_clip_video_li from '$lib/ae_core/ae_comp__hosted_files_clip_video_li.svelte';
import Element_manage_hosted_file_li_wrap from '$lib/elements/element_manage_hosted_file_li_all.svelte'; import Element_manage_hosted_file_li_wrap from '$lib/elements/element_manage_hosted_file_li_all.svelte';
import { ArrowLeftRight, Trash2, Upload } from '@lucide/svelte'; import { ArrowLeftRight, Trash2, Upload } from '@lucide/svelte';
let { data } = $props(); let { data } = $props();
let log_lvl = 1; let log_lvl = 1;
let ae_promises: key_val = {}; let ae_promises: key_val = {};
// export let container_class_li = []; // export let container_class_li = [];
let file_uploads_post_promise; let file_uploads_post_promise;
let download_src; let download_src;
let download_filename; let download_filename;
let file_uploads_clip_post_promise; let file_uploads_clip_post_promise;
let download_clip_src; let download_clip_src;
let download_clip_filename; let download_clip_filename;
let hosted_file_upload: key_val = $state({ let hosted_file_upload: key_val = $state({
// link_to_type: 'account', // link_to_type: 'account',
// link_to_id: ae_loc.account_id, // link_to_id: ae_loc.account_id,
hosted_file_id_li: [], hosted_file_id_li: [],
hosted_file_obj_li: [], hosted_file_obj_li: [],
clip_complete: false, clip_complete: false,
upload_complete: false, upload_complete: false,
submit_status: null submit_status: null
}); });
let hosted_file_clip: key_val = $state({ let hosted_file_clip: key_val = $state({
video_clip_file_kv: {}, video_clip_file_kv: {},
clip_complete: false, clip_complete: false,
submit_status: null submit_status: null
}); });
if (!$ae_loc.files) { if (!$ae_loc.files) {
$ae_loc.files = {}; $ae_loc.files = {};
$ae_loc.files.processed_file_kv = {}; $ae_loc.files.processed_file_kv = {};
$ae_loc.files.uploaded_file_kv = {}; $ae_loc.files.uploaded_file_kv = {};
$ae_loc.files.video_clip_file_kv = {}; $ae_loc.files.video_clip_file_kv = {};
// $ae_loc.files.uploaded_file_list = []; // $ae_loc.files.uploaded_file_list = [];
// $ae_loc.files.video_clip_file_list = []; // $ae_loc.files.video_clip_file_list = [];
} }
if (!$ae_loc.files.processed_file_kv) { if (!$ae_loc.files.processed_file_kv) {
$ae_loc.files.processed_file_kv = {}; $ae_loc.files.processed_file_kv = {};
} }
if (!$ae_sess.files) { if (!$ae_sess.files) {
$ae_sess.files = {}; $ae_sess.files = {};
} }
if (typeof $ae_sess.files.upload_complete === 'undefined') { if (typeof $ae_sess.files.upload_complete === 'undefined') {
$ae_sess.files.upload_complete = false;
}
$effect(() => {
// if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_li) {
// // Append this list to the $ae_loc.files.uploaded_file_li list
// $ae_loc.files.uploaded_file_li = [
// ...$ae_loc.files.uploaded_file_li,
// ...$ae_sess.files.uploaded_file_li
// ];
// }
if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_kv) {
// Add this key-value pair to the $ae_loc.files.uploaded_file_kv object
$ae_loc.files.uploaded_file_kv = {
...$ae_loc.files.uploaded_file_kv,
...$ae_sess.files.uploaded_file_kv
};
$ae_sess.files.upload_complete = false; $ae_sess.files.upload_complete = false;
} }
$effect(() => { if ($ae_sess.files.clip_complete && $ae_sess.files.video_clip_file_kv) {
// if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_li) { // Add this key-value pair to the $ae_loc.files.video_clip_file_kv object
// // Append this list to the $ae_loc.files.uploaded_file_li list $ae_loc.files.video_clip_file_kv = {
// $ae_loc.files.uploaded_file_li = [ ...$ae_loc.files.video_clip_file_kv,
// ...$ae_loc.files.uploaded_file_li, ...$ae_sess.files.video_clip_file_kv
// ...$ae_sess.files.uploaded_file_li };
// ]; $ae_sess.files.clip_complete = false;
// } }
});
if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_kv) { // $effect(() => {
// Add this key-value pair to the $ae_loc.files.uploaded_file_kv object // if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_kv) {
$ae_loc.files.uploaded_file_kv = { // // Add this key-value pair to the $ae_loc.files.uploaded_file_kv object
...$ae_loc.files.uploaded_file_kv, // $ae_loc.files.uploaded_file_kv = {
...$ae_sess.files.uploaded_file_kv // ...$ae_loc.files.uploaded_file_kv,
}; // ...$ae_sess.files.uploaded_file_kv
$ae_sess.files.upload_complete = false; // };
} // }
// });
if ($ae_sess.files.clip_complete && $ae_sess.files.video_clip_file_kv) { // $effect(() => {
// Add this key-value pair to the $ae_loc.files.video_clip_file_kv object // if ($ae_sess.files.clip_complete && $ae_sess.files.video_clip_file_kv) {
$ae_loc.files.video_clip_file_kv = { // // Add this key-value pair to the $ae_loc.files.video_clip_file_kv object
...$ae_loc.files.video_clip_file_kv, // $ae_loc.files.video_clip_file_kv = {
...$ae_sess.files.video_clip_file_kv // ...$ae_loc.files.video_clip_file_kv,
}; // ...$ae_sess.files.video_clip_file_kv
$ae_sess.files.clip_complete = false; // };
} // }
}); // });
// $effect(() => { onMount(() => {
// if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_kv) { console.log('Hosted Files: AV Utilities +page.svelte');
// // Add this key-value pair to the $ae_loc.files.uploaded_file_kv object });
// $ae_loc.files.uploaded_file_kv = {
// ...$ae_loc.files.uploaded_file_kv,
// ...$ae_sess.files.uploaded_file_kv
// };
// }
// });
// $effect(() => {
// if ($ae_sess.files.clip_complete && $ae_sess.files.video_clip_file_kv) {
// // Add this key-value pair to the $ae_loc.files.video_clip_file_kv object
// $ae_loc.files.video_clip_file_kv = {
// ...$ae_loc.files.video_clip_file_kv,
// ...$ae_sess.files.video_clip_file_kv
// };
// }
// });
onMount(() => {
console.log('Hosted Files: AV Utilities +page.svelte');
});
</script> </script>
<!-- <section <!-- <section
@@ -140,10 +146,11 @@
<h1 class="h1">Clip and Scale Video Files</h1> <h1 class="h1">Clip and Scale Video Files</h1>
<p> <p>
This AV utility will take an mp4 video file and create a clipped mp4 video file. By default, This AV utility will take an mp4 video file and create a clipped mp4 video
videos will be scaled down to 1920x1080. This process takes at least 30 seconds, but it can file. By default, videos will be scaled down to 1920x1080. This process
easily take a handful of minutes. The scaling option requires that the video be re-encoded. takes at least 30 seconds, but it can easily take a handful of minutes. The
Please be patient while it is processing. scaling option requires that the video be re-encoded. Please be patient
while it is processing.
</p> </p>
<h2 class="h2"> <h2 class="h2">
@@ -151,7 +158,7 @@
<button <button
type="button" type="button"
class="btn btn-sm preset-tonal-warning border border-warning-500 hover:preset-filled-warning-500 float-right" class="btn btn-sm preset-tonal-warning border-warning-500 hover:preset-filled-warning-500 float-right border"
title="Toggle between Upload and Select from Hosted Files" title="Toggle between Upload and Select from Hosted Files"
onclick={() => { onclick={() => {
if ($ae_sess.files.add_to_use_files_method == 'upload') { if ($ae_sess.files.add_to_use_files_method == 'upload') {
@@ -159,8 +166,7 @@
} else { } else {
$ae_sess.files.add_to_use_files_method = 'upload'; $ae_sess.files.add_to_use_files_method = 'upload';
} }
}} }}>
>
<ArrowLeftRight size="1em" class="m-1" /> <ArrowLeftRight size="1em" class="m-1" />
Upload/Select Upload/Select
</button> </button>
@@ -175,15 +181,15 @@
bind:hosted_file_obj_li={hosted_file_upload.hosted_file_obj_li} bind:hosted_file_obj_li={hosted_file_upload.hosted_file_obj_li}
bind:hosted_file_obj_kv={$ae_sess.files.uploaded_file_kv} bind:hosted_file_obj_kv={$ae_sess.files.uploaded_file_kv}
bind:upload_complete={$ae_sess.files.upload_complete} bind:upload_complete={$ae_sess.files.upload_complete}
{log_lvl} {log_lvl}>
>
{#snippet label()} {#snippet label()}
<span> <span>
<div class="flex items-center gap-2 mb-1"> <div class="mb-1 flex items-center gap-2">
<Upload size="1em" class="text-primary-500" /> <Upload size="1em" class="text-primary-500" />
<strong class="preset-tonal-success px-3 py-1 rounded-full">Upload video files</strong> <strong class="preset-tonal-success rounded-full px-3 py-1"
>Upload video files</strong>
</div> </div>
<span class="text-sm opacity-70 italic"> <span class="text-sm italic opacity-70">
<strong>Aether hosted files only</strong><br /> <strong>Aether hosted files only</strong><br />
Recommended: video (mp4, mkv)<br /> Recommended: video (mp4, mkv)<br />
</span> </span>
@@ -200,8 +206,7 @@
allow_moderator={true} allow_moderator={true}
class_li={''} class_li={''}
max_file_count={39} max_file_count={39}
file_type={'video'} file_type={'video'} />
/>
</div> </div>
<hr /> <hr />
@@ -214,8 +219,7 @@
onclick={() => { onclick={() => {
$ae_loc.files.uploaded_file_kv = {}; $ae_loc.files.uploaded_file_kv = {};
}} }}
class="btn btn-sm preset-tonal-warning border border-warning-500 hover:preset-filled-warning-500 float-right" class="btn btn-sm preset-tonal-warning border-warning-500 hover:preset-filled-warning-500 float-right border">
>
<Trash2 size="1em" class="m-1" /> <Trash2 size="1em" class="m-1" />
Clear Upload History Clear Upload History
</button> </button>
@@ -229,8 +233,7 @@
bind:video_clip_file_kv={$ae_loc.files.video_clip_file_kv} bind:video_clip_file_kv={$ae_loc.files.video_clip_file_kv}
bind:clip_complete={$ae_sess.files.clip_complete} bind:clip_complete={$ae_sess.files.clip_complete}
bind:submit_status={hosted_file_clip.submit_status} bind:submit_status={hosted_file_clip.submit_status}
{log_lvl} {log_lvl}></Comp_hosted_files_clip_video>
></Comp_hosted_files_clip_video>
{:else} {:else}
<p>Upload a video file to clip first.</p> <p>Upload a video file to clip first.</p>
{/if} {/if}
@@ -245,8 +248,7 @@
onclick={() => { onclick={() => {
$ae_loc.files.video_clip_file_kv = {}; $ae_loc.files.video_clip_file_kv = {};
}} }}
class="btn btn-sm preset-tonal-warning border border-warning-500 hover:preset-filled-warning-500 float-right" class="btn btn-sm preset-tonal-warning border-warning-500 hover:preset-filled-warning-500 float-right border">
>
<Trash2 size="1em" class="m-1" /> <Trash2 size="1em" class="m-1" />
Clear Clip History Clear Clip History
</button> </button>
@@ -257,8 +259,7 @@
link_to_type="account" link_to_type="account"
link_to_id={$ae_loc.account_id} link_to_id={$ae_loc.account_id}
bind:video_clip_file_kv={$ae_loc.files.video_clip_file_kv} bind:video_clip_file_kv={$ae_loc.files.video_clip_file_kv}
{log_lvl} {log_lvl}></Comp_hosted_files_clip_video_li>
></Comp_hosted_files_clip_video_li>
{:else} {:else}
<p>Clip a video file first.</p> <p>Clip a video file first.</p>
{/if} {/if}

View File

@@ -1,54 +1,61 @@
<script lang="ts"> <script lang="ts">
// import { api } from '$lib/api.js'; // import { api } from '$lib/api.js';
import { ae_loc, ae_sess, ae_api, slct, slct_trigger } from '$lib/stores/ae_stores'; import {
// import { ae_util } from '$lib/ae_utils/ae_utils'; ae_loc,
import type { key_val } from '$lib/stores/ae_stores'; ae_sess,
ae_api,
slct,
slct_trigger
} from '$lib/stores/ae_stores';
// import { ae_util } from '$lib/ae_utils/ae_utils';
import type { key_val } from '$lib/stores/ae_stores';
import Comp_hosted_files_upload from '$lib/ae_core/ae_comp__hosted_files_upload.svelte'; import Comp_hosted_files_upload from '$lib/ae_core/ae_comp__hosted_files_upload.svelte';
import Comp_hosted_files_clip_video from '$lib/ae_core/ae_comp__hosted_files_clip_video.svelte'; import Comp_hosted_files_clip_video from '$lib/ae_core/ae_comp__hosted_files_clip_video.svelte';
import Comp_hosted_files_clip_video_li from '$lib/ae_core/ae_comp__hosted_files_clip_video_li.svelte'; import Comp_hosted_files_clip_video_li from '$lib/ae_core/ae_comp__hosted_files_clip_video_li.svelte';
import Element_manage_hosted_file_li_wrap from '$lib/elements/element_manage_hosted_file_li_all.svelte'; import Element_manage_hosted_file_li_wrap from '$lib/elements/element_manage_hosted_file_li_all.svelte';
import { ArrowLeftRight, Trash2, Upload } from '@lucide/svelte'; import { ArrowLeftRight, Trash2, Upload } from '@lucide/svelte';
let log_lvl = 1; let log_lvl = 1;
let ae_promises: key_val = {}; let ae_promises: key_val = {};
// export let container_class_li = []; // export let container_class_li = [];
let file_uploads_post_promise; let file_uploads_post_promise;
let download_src; let download_src;
let download_filename; let download_filename;
let file_uploads_clip_post_promise; let file_uploads_clip_post_promise;
let download_clip_src; let download_clip_src;
let download_clip_filename; let download_clip_filename;
let hosted_file_upload: key_val = $state({ let hosted_file_upload: key_val = $state({
// link_to_type: 'account', // link_to_type: 'account',
// link_to_id: ae_loc.account_id, // link_to_id: ae_loc.account_id,
hosted_file_id_li: [], hosted_file_id_li: [],
hosted_file_obj_li: [], hosted_file_obj_li: [],
clip_complete: false, clip_complete: false,
upload_complete: false, upload_complete: false,
submit_status: null submit_status: null
}); });
let hosted_file_clip: key_val = $state({ let hosted_file_clip: key_val = $state({
video_clip_file_kv: {}, video_clip_file_kv: {},
clip_complete: false, clip_complete: false,
submit_status: null submit_status: null
}); });
</script> </script>
<section class="ae__hosted_files__av_util container space-y-4 pb-20"> <section class="ae__hosted_files__av_util container space-y-4 pb-20">
<div class="border border-gray-200 p-2 rounded-lg"> <div class="rounded-lg border border-gray-200 p-2">
<h1 class="h1">Clip and Scale Video Files</h1> <h1 class="h1">Clip and Scale Video Files</h1>
<p> <p>
This AV utility will take an mp4 video file and create a clipped mp4 video file. By This AV utility will take an mp4 video file and create a clipped mp4
default, videos will be scaled down to 1920x1080. This process takes at least 30 video file. By default, videos will be scaled down to 1920x1080.
seconds, but it can easily take a handful of minutes. The scaling option requires that This process takes at least 30 seconds, but it can easily take a
the video be re-encoded. Please be patient while it is processing. handful of minutes. The scaling option requires that the video be
re-encoded. Please be patient while it is processing.
</p> </p>
<h2 class="h2"> <h2 class="h2">
@@ -56,7 +63,7 @@
<button <button
type="button" type="button"
class="btn btn-sm preset-tonal-warning border border-warning-500 hover:preset-filled-warning-500 float-right" class="btn btn-sm preset-tonal-warning border-warning-500 hover:preset-filled-warning-500 float-right border"
title="Toggle between Upload and Select from Hosted Files" title="Toggle between Upload and Select from Hosted Files"
onclick={() => { onclick={() => {
if ($ae_sess.files.add_to_use_files_method == 'upload') { if ($ae_sess.files.add_to_use_files_method == 'upload') {
@@ -64,8 +71,7 @@
} else { } else {
$ae_sess.files.add_to_use_files_method = 'upload'; $ae_sess.files.add_to_use_files_method = 'upload';
} }
}} }}>
>
<ArrowLeftRight size="1em" class="m-1" /> <ArrowLeftRight size="1em" class="m-1" />
Upload/Select Upload/Select
</button> </button>
@@ -80,15 +86,16 @@
bind:hosted_file_obj_li={hosted_file_upload.hosted_file_obj_li} bind:hosted_file_obj_li={hosted_file_upload.hosted_file_obj_li}
bind:hosted_file_obj_kv={$ae_sess.files.uploaded_file_kv} bind:hosted_file_obj_kv={$ae_sess.files.uploaded_file_kv}
bind:upload_complete={$ae_sess.files.upload_complete} bind:upload_complete={$ae_sess.files.upload_complete}
{log_lvl} {log_lvl}>
>
{#snippet label()} {#snippet label()}
<span> <span>
<div> <div>
<Upload size="1em" /> <Upload size="1em" />
<strong class="bg-green-100 p-1">Upload video files</strong> <strong class="bg-green-100 p-1"
>Upload video files</strong>
</div> </div>
<span class="text-sm text-gray-600 dark:text-gray-400 italic"> <span
class="text-sm text-gray-600 italic dark:text-gray-400">
<strong>Aether hosted files only</strong><br /> <strong>Aether hosted files only</strong><br />
Recommended: video (mp4, mkv)<br /> Recommended: video (mp4, mkv)<br />
</span> </span>
@@ -97,14 +104,15 @@
</Comp_hosted_files_upload> </Comp_hosted_files_upload>
</div> </div>
<div class:hidden={$ae_sess.files.add_to_use_files_method == 'select'} class=""> <div
class:hidden={$ae_sess.files.add_to_use_files_method == 'select'}
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={''} />
/>
</div> </div>
<hr /> <hr />
@@ -117,8 +125,7 @@
onclick={() => { onclick={() => {
$ae_loc.files.uploaded_file_kv = {}; $ae_loc.files.uploaded_file_kv = {};
}} }}
class="btn btn-sm preset-tonal-warning border border-warning-500 hover:preset-filled-warning-500 float-right" class="btn btn-sm preset-tonal-warning border-warning-500 hover:preset-filled-warning-500 float-right border">
>
<Trash2 size="1em" class="m-1" /> <Trash2 size="1em" class="m-1" />
Clear Upload History Clear Upload History
</button> </button>
@@ -132,8 +139,7 @@
bind:video_clip_file_kv={$ae_loc.files.video_clip_file_kv} bind:video_clip_file_kv={$ae_loc.files.video_clip_file_kv}
bind:clip_complete={$ae_sess.files.clip_complete} bind:clip_complete={$ae_sess.files.clip_complete}
bind:submit_status={hosted_file_clip.submit_status} bind:submit_status={hosted_file_clip.submit_status}
{log_lvl} {log_lvl}></Comp_hosted_files_clip_video>
></Comp_hosted_files_clip_video>
{:else} {:else}
<p>Upload a video file to clip first.</p> <p>Upload a video file to clip first.</p>
{/if} {/if}
@@ -146,8 +152,7 @@
onclick={() => { onclick={() => {
$ae_loc.files.video_clip_file_kv = {}; $ae_loc.files.video_clip_file_kv = {};
}} }}
class="btn btn-sm preset-tonal-warning border border-warning-500 hover:preset-filled-warning-500 float-right" class="btn btn-sm preset-tonal-warning border-warning-500 hover:preset-filled-warning-500 float-right border">
>
<Trash2 size="1em" class="m-1" /> <Trash2 size="1em" class="m-1" />
Clear Clip History Clear Clip History
</button> </button>
@@ -158,8 +163,7 @@
link_to_type="account" link_to_type="account"
link_to_id={$ae_loc.account_id} link_to_id={$ae_loc.account_id}
bind:video_clip_file_kv={$ae_loc.files.video_clip_file_kv} bind:video_clip_file_kv={$ae_loc.files.video_clip_file_kv}
{log_lvl} {log_lvl}></Comp_hosted_files_clip_video_li>
></Comp_hosted_files_clip_video_li>
{:else} {:else}
<p>Clip a video file first.</p> <p>Clip a video file first.</p>
{/if} {/if}

View File

@@ -50,64 +50,131 @@ export const GET: RequestHandler = async ({ url, fetch }) => {
} }
// Default branding // Default branding
const branding_name = site_domain?.account_name || site_domain?.name || "Aether"; const branding_name =
site_domain?.account_name || site_domain?.name || 'Aether';
const name = `One Sky IT - ${branding_name} Aether PWA`; const name = `One Sky IT - ${branding_name} Aether PWA`;
const short_name = `${site_domain?.account_code || site_domain?.code || 'Aether'} PWA`; const short_name = `${site_domain?.account_code || site_domain?.code || 'Aether'} PWA`;
const background_color = site_domain?.cfg_json?.pwa_background_color || "hsl(220, 65%, 31%)"; const background_color =
const theme_color = "#3a5997"; site_domain?.cfg_json?.pwa_background_color || 'hsl(220, 65%, 31%)';
const theme_color = '#3a5997';
const manifest = { const manifest = {
"id": `ae-pwa-${fqdn}`, // Unique ID for this installation id: `ae-pwa-${fqdn}`, // Unique ID for this installation
"name": name, name: name,
"short_name": short_name, short_name: short_name,
"description": `The ${name} platform for unified event and documentation management.`, description: `The ${name} platform for unified event and documentation management.`,
"start_url": "/", start_url: '/',
"scope": "/", scope: '/',
"display": "fullscreen", display: 'fullscreen',
"background_color": background_color, background_color: background_color,
"theme_color": theme_color, theme_color: theme_color,
"orientation": "any", orientation: 'any',
"categories": ["business", "productivity", "utilities"], categories: ['business', 'productivity', 'utilities'],
"icons": [ icons: [
// Standard Icons (Small/Med) // Standard Icons (Small/Med)
{ "sizes": "24x24", "src": "https://static.oneskyit.com/images/OSIT_logo_2022_24px.png", "type": "image/png" }, {
{ "sizes": "48x48", "src": "https://static.oneskyit.com/images/OSIT_logo_2022_48px.png", "type": "image/png" }, sizes: '24x24',
{ "sizes": "96x96", "src": "https://static.oneskyit.com/images/OSIT_logo_2022_96px.png", "type": "image/png" }, src: 'https://static.oneskyit.com/images/OSIT_logo_2022_24px.png',
{ "sizes": "144x144", "src": "https://static.oneskyit.com/images/OSIT_logo_2022_144px.png", "type": "image/png" }, type: 'image/png'
{ "sizes": "180x180", "src": "https://static.oneskyit.com/images/OSIT_logo_2022_180px.png", "type": "image/png" }, },
{
sizes: '48x48',
src: 'https://static.oneskyit.com/images/OSIT_logo_2022_48px.png',
type: 'image/png'
},
{
sizes: '96x96',
src: 'https://static.oneskyit.com/images/OSIT_logo_2022_96px.png',
type: 'image/png'
},
{
sizes: '144x144',
src: 'https://static.oneskyit.com/images/OSIT_logo_2022_144px.png',
type: 'image/png'
},
{
sizes: '180x180',
src: 'https://static.oneskyit.com/images/OSIT_logo_2022_180px.png',
type: 'image/png'
},
// High-res Maskable Icons (WebP preferred for efficiency) // High-res Maskable Icons (WebP preferred for efficiency)
{ "sizes": "192x192", "src": "https://static.oneskyit.com/images/OSIT_logo_2022_192px.webp", "type": "image/webp", "purpose": "any maskable" },
{ "sizes": "192x192", "src": "https://static.oneskyit.com/images/OSIT_logo_2022_192px.png", "type": "image/png", "purpose": "any maskable" },
{ "sizes": "512x512", "src": "https://static.oneskyit.com/images/OSIT_logo_2022_512px.webp", "type": "image/webp", "purpose": "any maskable" },
{ "sizes": "512x512", "src": "https://static.oneskyit.com/images/OSIT_logo_2022_512px.png", "type": "image/png", "purpose": "any maskable" },
{ "sizes": "1024x1024", "src": "https://static.oneskyit.com/images/OSIT_logo_2022_1024px.webp", "type": "image/webp", "purpose": "any maskable" },
{ "sizes": "1024x1024", "src": "https://static.oneskyit.com/images/OSIT_logo_2022_1024px.png", "type": "image/png", "purpose": "any maskable" }
],
// App Shortcuts (Long-press icon features)
"shortcuts": [
{ {
"name": "Journals", sizes: '192x192',
"short_name": "Journals", src: 'https://static.oneskyit.com/images/OSIT_logo_2022_192px.webp',
"description": "View and manage journal entries", type: 'image/webp',
"url": "/journals", purpose: 'any maskable'
"icons": [{ "src": "https://static.oneskyit.com/images/OSIT_logo_2022_192px.png", "sizes": "192x192" }]
}, },
{ {
"name": "Events", sizes: '192x192',
"short_name": "Events", src: 'https://static.oneskyit.com/images/OSIT_logo_2022_192px.png',
"description": "Access active event management", type: 'image/png',
"url": "/events", purpose: 'any maskable'
"icons": [{ "src": "https://static.oneskyit.com/images/OSIT_logo_2022_192px.png", "sizes": "192x192" }]
}, },
{ {
"name": "Testing", sizes: '512x512',
"short_name": "Testing", src: 'https://static.oneskyit.com/images/OSIT_logo_2022_512px.webp',
"description": "System diagnostic dashboard", type: 'image/webp',
"url": "/testing", purpose: 'any maskable'
"icons": [{ "src": "https://static.oneskyit.com/images/OSIT_logo_2022_192px.png", "sizes": "192x192" }] },
{
sizes: '512x512',
src: 'https://static.oneskyit.com/images/OSIT_logo_2022_512px.png',
type: 'image/png',
purpose: 'any maskable'
},
{
sizes: '1024x1024',
src: 'https://static.oneskyit.com/images/OSIT_logo_2022_1024px.webp',
type: 'image/webp',
purpose: 'any maskable'
},
{
sizes: '1024x1024',
src: 'https://static.oneskyit.com/images/OSIT_logo_2022_1024px.png',
type: 'image/png',
purpose: 'any maskable'
} }
], ],
"testing": "One Sky IT" // App Shortcuts (Long-press icon features)
shortcuts: [
{
name: 'Journals',
short_name: 'Journals',
description: 'View and manage journal entries',
url: '/journals',
icons: [
{
src: 'https://static.oneskyit.com/images/OSIT_logo_2022_192px.png',
sizes: '192x192'
}
]
},
{
name: 'Events',
short_name: 'Events',
description: 'Access active event management',
url: '/events',
icons: [
{
src: 'https://static.oneskyit.com/images/OSIT_logo_2022_192px.png',
sizes: '192x192'
}
]
},
{
name: 'Testing',
short_name: 'Testing',
description: 'System diagnostic dashboard',
url: '/testing',
icons: [
{
src: 'https://static.oneskyit.com/images/OSIT_logo_2022_192px.png',
sizes: '192x192'
}
]
}
],
testing: 'One Sky IT'
}; };
return json(manifest, { return json(manifest, {
@@ -116,4 +183,4 @@ export const GET: RequestHandler = async ({ url, fetch }) => {
'Cache-Control': 'public, max-age=3600' 'Cache-Control': 'public, max-age=3600'
} }
}); });
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -1,85 +1,100 @@
<script lang="ts"> <script lang="ts">
import AE_Obj_Field_Editor_V3 from '$lib/elements/element_ae_obj_field_editor.svelte'; import AE_Obj_Field_Editor_V3 from '$lib/elements/element_ae_obj_field_editor.svelte';
import { ae_loc, ae_api } from '$lib/stores/ae_stores'; import { ae_loc, ae_api } from '$lib/stores/ae_stores';
import { liveQuery } from 'dexie'; import { liveQuery } from 'dexie';
import { db_journals } from '$lib/ae_journals/db_journals'; import { db_journals } from '$lib/ae_journals/db_journals';
import { load_ae_obj_id__journal } from '$lib/ae_journals/ae_journals__journal'; import { load_ae_obj_id__journal } from '$lib/ae_journals/ae_journals__journal';
import { load_ae_obj_id__journal_entry } from '$lib/ae_journals/ae_journals__journal_entry'; import { load_ae_obj_id__journal_entry } from '$lib/ae_journals/ae_journals__journal_entry';
import { Database, FileText, LoaderCircle, RefreshCw } from '@lucide/svelte'; import { Database, FileText, LoaderCircle, RefreshCw } from '@lucide/svelte';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
let log_lvl = $state(1); let log_lvl = $state(1);
// Provided Test IDs // Provided Test IDs
let test_journal_id = $state('SWFK-48-89-90'); // 'BVYE-94-46-29' let test_journal_id = $state('SWFK-48-89-90'); // 'BVYE-94-46-29'
let test_journal_entry_id = $state('xRx-Y4-h3-fU'); let test_journal_entry_id = $state('xRx-Y4-h3-fU');
// Fetch objects from API on mount to ensure local DB is populated // Fetch objects from API on mount to ensure local DB is populated
onMount(async () => { onMount(async () => {
if (log_lvl) console.log('Test Page: Initializing data from server...'); if (log_lvl) console.log('Test Page: Initializing data from server...');
try { try {
await Promise.all([ await Promise.all([
load_ae_obj_id__journal({ load_ae_obj_id__journal({
api_cfg: $ae_api, api_cfg: $ae_api,
journal_id: test_journal_id, journal_id: test_journal_id,
log_lvl log_lvl
}), }),
load_ae_obj_id__journal_entry({ load_ae_obj_id__journal_entry({
api_cfg: $ae_api, api_cfg: $ae_api,
journal_entry_id: test_journal_entry_id, journal_entry_id: test_journal_entry_id,
log_lvl log_lvl
}) })
]); ]);
} catch (e) { } catch (e) {
console.error('Test Page: Error loading initial data', e); console.error('Test Page: Error loading initial data', e);
}
});
// Dexie LiveQueries
let lq__test_journal = $derived(
liveQuery(async () => {
return await db_journals.journal.get(test_journal_id);
})
);
let lq__test_journal_entry = $derived(
liveQuery(async () => {
return await db_journals.journal_entry.get(test_journal_entry_id);
})
);
function handle_success(data: any) {
console.log('Test Page: Patch Success!', data);
} }
});
// Dexie LiveQueries
let lq__test_journal = $derived(
liveQuery(async () => {
return await db_journals.journal.get(test_journal_id);
})
);
let lq__test_journal_entry = $derived(
liveQuery(async () => {
return await db_journals.journal_entry.get(test_journal_entry_id);
})
);
function handle_success(data: any) {
console.log('Test Page: Patch Success!', data);
}
</script> </script>
<div class="p-8 space-y-8 max-w-6xl mx-auto h-full overflow-y-auto"> <div class="mx-auto h-full max-w-6xl space-y-8 overflow-y-auto p-8">
<header class="border-b border-surface-500/30 pb-4 flex justify-between items-center"> <header
class="border-surface-500/30 flex items-center justify-between border-b pb-4">
<div> <div>
<h1 class="h1">AE Obj Field Editor V3 Test</h1> <h1 class="h1">AE Obj Field Editor V3 Test</h1>
<p class="opacity-70 font-mono text-xs">IDs: Journal={test_journal_id} | Entry={test_journal_entry_id}</p> <p class="font-mono text-xs opacity-70">
IDs: Journal={test_journal_id} | Entry={test_journal_entry_id}
</p>
</div> </div>
<div class="flex items-center gap-4"> <div class="flex items-center gap-4">
<label class="flex items-center gap-2 cursor-pointer bg-surface-200 dark:bg-surface-800 px-3 py-1.5 rounded-full shadow-inner"> <label
<span class="text-xs font-bold uppercase opacity-70">Edit Mode</span> class="bg-surface-200 dark:bg-surface-800 flex cursor-pointer items-center gap-2 rounded-full px-3 py-1.5 shadow-inner">
<input type="checkbox" bind:checked={$ae_loc.edit_mode} class="checkbox" /> <span class="text-xs font-bold uppercase opacity-70"
>Edit Mode</span>
<input
type="checkbox"
bind:checked={$ae_loc.edit_mode}
class="checkbox" />
</label> </label>
<button class="btn variant-filled-primary" onclick={() => window.location.reload()}> <button
class="btn variant-filled-primary"
onclick={() => window.location.reload()}>
<RefreshCw size="1em" class="mr-2" /> Reload Page <RefreshCw size="1em" class="mr-2" /> Reload Page
</button> </button>
</div> </div>
</header> </header>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> <div class="grid grid-cols-1 gap-8 lg:grid-cols-2">
<!-- COLUMN 1: JOURNAL TEST --> <!-- COLUMN 1: JOURNAL TEST -->
<div class="space-y-8"> <div class="space-y-8">
<h2 class="h2 flex items-center gap-2"><Database /> Journal Properties</h2> <h2 class="h2 flex items-center gap-2">
<Database /> Journal Properties
</h2>
{#if $lq__test_journal} {#if $lq__test_journal}
<section class="card p-6 space-y-6 variant-soft-primary shadow-lg border border-primary-500/20"> <section
class="card variant-soft-primary border-primary-500/20 space-y-6 border p-6 shadow-lg">
<div class="field_group"> <div class="field_group">
<label for="j_name" class="label text-xs font-bold opacity-50 mb-1 uppercase tracking-tighter">Journal Name</label> <label
for="j_name"
class="label mb-1 text-xs font-bold tracking-tighter uppercase opacity-50"
>Journal Name</label>
<AE_Obj_Field_Editor_V3 <AE_Obj_Field_Editor_V3
id="j_name" id="j_name"
object_type="journal" object_type="journal"
@@ -88,12 +103,14 @@
bind:current_value={$lq__test_journal.name} bind:current_value={$lq__test_journal.name}
field_type="text" field_type="text"
{log_lvl} {log_lvl}
on_success={handle_success} on_success={handle_success} />
/>
</div> </div>
<div class="field_group"> <div class="field_group">
<label for="j_type" class="label text-xs font-bold opacity-50 mb-1 uppercase tracking-tighter">Type Code</label> <label
for="j_type"
class="label mb-1 text-xs font-bold tracking-tighter uppercase opacity-50"
>Type Code</label>
<AE_Obj_Field_Editor_V3 <AE_Obj_Field_Editor_V3
id="j_type" id="j_type"
object_type="journal" object_type="journal"
@@ -102,17 +119,19 @@
bind:current_value={$lq__test_journal.type_code} bind:current_value={$lq__test_journal.type_code}
field_type="select" field_type="select"
select_options={{ select_options={{
'personal': 'Personal Journal', personal: 'Personal Journal',
'work': 'Work Log', work: 'Work Log',
'shared': 'Shared Notes', shared: 'Shared Notes',
'ai_brain': 'AI Context' ai_brain: 'AI Context'
}} }}
{log_lvl} {log_lvl} />
/>
</div> </div>
<div class="field_group"> <div class="field_group">
<label for="j_summary" class="label text-xs font-bold opacity-50 mb-1 uppercase tracking-tighter">Summary</label> <label
for="j_summary"
class="label mb-1 text-xs font-bold tracking-tighter uppercase opacity-50"
>Summary</label>
<AE_Obj_Field_Editor_V3 <AE_Obj_Field_Editor_V3
id="j_summary" id="j_summary"
object_type="journal" object_type="journal"
@@ -121,26 +140,34 @@
bind:current_value={$lq__test_journal.summary} bind:current_value={$lq__test_journal.summary}
field_type="textarea" field_type="textarea"
display_block={true} display_block={true}
{log_lvl} {log_lvl} />
/>
</div> </div>
</section> </section>
{:else} {:else}
<div class="card p-10 flex flex-col items-center justify-center opacity-50 gap-4 variant-soft-surface"> <div
class="card variant-soft-surface flex flex-col items-center justify-center gap-4 p-10 opacity-50">
<LoaderCircle size="32" class="animate-spin" /> <LoaderCircle size="32" class="animate-spin" />
<p class="text-sm font-bold">Loading Journal {test_journal_id}...</p> <p class="text-sm font-bold">
Loading Journal {test_journal_id}...
</p>
</div> </div>
{/if} {/if}
</div> </div>
<!-- COLUMN 2: JOURNAL ENTRY TEST --> <!-- COLUMN 2: JOURNAL ENTRY TEST -->
<div class="space-y-8"> <div class="space-y-8">
<h2 class="h2 flex items-center gap-2"><FileText /> Journal Entry Properties</h2> <h2 class="h2 flex items-center gap-2">
<FileText /> Journal Entry Properties
</h2>
{#if $lq__test_journal_entry} {#if $lq__test_journal_entry}
<section class="card p-6 space-y-6 variant-soft-secondary shadow-lg border border-secondary-500/20"> <section
class="card variant-soft-secondary border-secondary-500/20 space-y-6 border p-6 shadow-lg">
<div class="field_group"> <div class="field_group">
<label for="e_name" class="label text-xs font-bold opacity-50 mb-1 uppercase tracking-tighter">Entry Title</label> <label
for="e_name"
class="label mb-1 text-xs font-bold tracking-tighter uppercase opacity-50"
>Entry Title</label>
<AE_Obj_Field_Editor_V3 <AE_Obj_Field_Editor_V3
id="e_name" id="e_name"
object_type="journal_entry" object_type="journal_entry"
@@ -148,39 +175,49 @@
field_name="name" field_name="name"
bind:current_value={$lq__test_journal_entry.name} bind:current_value={$lq__test_journal_entry.name}
field_type="text" field_type="text"
{log_lvl} {log_lvl} />
/>
</div> </div>
<div class="grid grid-cols-2 gap-4"> <div class="grid grid-cols-2 gap-4">
<div class="field_group"> <div class="field_group">
<label for="e_enabled" class="label text-xs font-bold opacity-50 mb-1 uppercase tracking-tighter">Status</label> <label
for="e_enabled"
class="label mb-1 text-xs font-bold tracking-tighter uppercase opacity-50"
>Status</label>
<AE_Obj_Field_Editor_V3 <AE_Obj_Field_Editor_V3
id="e_enabled" id="e_enabled"
object_type="journal_entry" object_type="journal_entry"
object_id={test_journal_entry_id} object_id={test_journal_entry_id}
field_name="enable" field_name="enable"
bind:current_value={$lq__test_journal_entry.enable} bind:current_value={
$lq__test_journal_entry.enable
}
field_type="checkbox" field_type="checkbox"
{log_lvl} {log_lvl} />
/>
</div> </div>
<div class="field_group"> <div class="field_group">
<label for="e_priority" class="label text-xs font-bold opacity-50 mb-1 uppercase tracking-tighter">Priority</label> <label
for="e_priority"
class="label mb-1 text-xs font-bold tracking-tighter uppercase opacity-50"
>Priority</label>
<AE_Obj_Field_Editor_V3 <AE_Obj_Field_Editor_V3
id="e_priority" id="e_priority"
object_type="journal_entry" object_type="journal_entry"
object_id={test_journal_entry_id} object_id={test_journal_entry_id}
field_name="priority" field_name="priority"
bind:current_value={$lq__test_journal_entry.priority} bind:current_value={
$lq__test_journal_entry.priority
}
field_type="checkbox" field_type="checkbox"
{log_lvl} {log_lvl} />
/>
</div> </div>
</div> </div>
<div class="field_group"> <div class="field_group">
<p class="label text-xs font-bold opacity-50 mb-1 uppercase tracking-tighter">Content (TipTap)</p> <p
class="label mb-1 text-xs font-bold tracking-tighter uppercase opacity-50">
Content (TipTap)
</p>
<AE_Obj_Field_Editor_V3 <AE_Obj_Field_Editor_V3
object_type="journal_entry" object_type="journal_entry"
object_id={test_journal_entry_id} object_id={test_journal_entry_id}
@@ -188,34 +225,40 @@
bind:current_value={$lq__test_journal_entry.content} bind:current_value={$lq__test_journal_entry.content}
field_type="tiptap" field_type="tiptap"
display_block={true} display_block={true}
{log_lvl} {log_lvl} />
/>
</div> </div>
</section> </section>
{:else} {:else}
<div class="card p-10 flex flex-col items-center justify-center opacity-50 gap-4 variant-soft-surface"> <div
class="card variant-soft-surface flex flex-col items-center justify-center gap-4 p-10 opacity-50">
<LoaderCircle size="32" class="animate-spin" /> <LoaderCircle size="32" class="animate-spin" />
<p class="text-sm font-bold">Loading Entry {test_journal_entry_id}...</p> <p class="text-sm font-bold">
Loading Entry {test_journal_entry_id}...
</p>
</div> </div>
{/if} {/if}
</div> </div>
</div> </div>
<!-- DEBUG FOOTER --> <!-- DEBUG FOOTER -->
<section class="card p-4 space-y-4"> <section class="card space-y-4 p-4">
<h2 class="h3">Debug Context</h2> <h2 class="h3">Debug Context</h2>
<div class="grid grid-cols-2 lg:grid-cols-4 gap-4 text-xs font-mono"> <div class="grid grid-cols-2 gap-4 font-mono text-xs lg:grid-cols-4">
<div class="bg-surface-900 text-success-500 p-2 rounded"> <div class="bg-surface-900 text-success-500 rounded p-2">
<strong>Edit Mode:</strong> {$ae_loc.edit_mode} <strong>Edit Mode:</strong>
{$ae_loc.edit_mode}
</div> </div>
<div class="bg-surface-900 text-success-500 p-2 rounded"> <div class="bg-surface-900 text-success-500 rounded p-2">
<strong>Account ID:</strong> {$ae_loc.account_id} <strong>Account ID:</strong>
{$ae_loc.account_id}
</div> </div>
<div class="bg-surface-900 text-success-500 p-2 rounded"> <div class="bg-surface-900 text-success-500 rounded p-2">
<strong>Journal Status:</strong> {$lq__test_journal ? 'Cached' : 'Pending'} <strong>Journal Status:</strong>
{$lq__test_journal ? 'Cached' : 'Pending'}
</div> </div>
<div class="bg-surface-900 text-success-500 p-2 rounded"> <div class="bg-surface-900 text-success-500 rounded p-2">
<strong>Entry Status:</strong> {$lq__test_journal_entry ? 'Cached' : 'Pending'} <strong>Entry Status:</strong>
{$lq__test_journal_entry ? 'Cached' : 'Pending'}
</div> </div>
</div> </div>
</section> </section>

View File

@@ -1,122 +1,141 @@
<script lang="ts"> <script lang="ts">
import AE_Element_Data_Store from '$lib/elements/element_data_store.svelte'; import AE_Element_Data_Store from '$lib/elements/element_data_store.svelte';
import { ae_loc } from '$lib/stores/ae_stores'; import { ae_loc } from '$lib/stores/ae_stores';
import { db_core } from '$lib/ae_core/db_core'; import { db_core } from '$lib/ae_core/db_core';
import { RefreshCw, Trash2 } from '@lucide/svelte'; import { RefreshCw, Trash2 } from '@lucide/svelte';
// let test_code_global = 'hub__site__root_page_header'; // Expected to be a global default // let test_code_global = 'hub__site__root_page_header'; // Expected to be a global default
// let test_name_global = 'Global Header Test - hub__site__root_page_header'; // let test_name_global = 'Global Header Test - hub__site__root_page_header';
// let test_code_account = 'hub__site__root_page_header'; // let test_code_account = 'hub__site__root_page_header';
// let test_name_account = 'Account Header Test - hub__site__root_page_header'; // let test_name_account = 'Account Header Test - hub__site__root_page_header';
// let test_code_specific = 'event_launcher_main_info'; // let test_code_specific = 'event_launcher_main_info';
// let test_name_specific = 'Event Specific Test - event_launcher_main_info'; // let test_name_specific = 'Event Specific Test - event_launcher_main_info';
let test_null_act_and_for = 'events__leads__overview'; // Expecting the Global Default
let test_code_account = 'hub__site__root_page_header'; // Expecting the Account Default
let test_code_and_for = 'event_launcher_main_info'; // Expecting the Specific Record (Event ID)
let testing_event_id = 'pjrcghqwert'; // Per README test data
let test_null_act_and_for = 'events__leads__overview'; // Expecting the Global Default let log_lvl = $state(0);
let test_code_account = 'hub__site__root_page_header'; // Expecting the Account Default let refresh_trigger = $state(0);
let test_code_and_for = 'event_launcher_main_info'; // Expecting the Specific Record (Event ID)
let testing_event_id = 'pjrcghqwert'; // Per README test data
async function clear_cache() {
if (log_lvl) console.log('Asking to confirm clearing Data Store cache...');
let log_lvl = $state(0); if (confirm('Are you sure you want to clear the local Data Store cache?')) {
let refresh_trigger = $state(0); await db_core.data_store.clear();
refresh_trigger++;
async function clear_cache() { alert('Cache cleared.');
if (log_lvl) console.log('Asking to confirm clearing Data Store cache...');
if (confirm('Are you sure you want to clear the local Data Store cache?')) {
await db_core.data_store.clear();
refresh_trigger++;
alert('Cache cleared.');
}
} }
}
</script> </script>
<div class="p-8 space-y-8 max-w-4xl mx-auto h-full overflow-y-auto"> <div class="mx-auto h-full max-w-4xl space-y-8 overflow-y-auto p-8">
<header class="border-b border-surface-500/30 pb-4 flex justify-between items-center"> <header
class="border-surface-500/30 flex items-center justify-between border-b pb-4">
<div> <div>
<h1 class="h1">Data Store V3 Test Page</h1> <h1 class="h1">Data Store V3 Test Page</h1>
<p class="opacity-70">Testing cascading lookup: Specific &rarr; Account &rarr; Global</p> <p class="opacity-70">
Testing cascading lookup: Specific &rarr; Account &rarr; Global
</p>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
<button class="btn variant-filled-warning" onclick={clear_cache}> <button class="btn variant-filled-warning" onclick={clear_cache}>
<Trash2 size="1em" class="mr-2" /> Clear Cache <Trash2 size="1em" class="mr-2" /> Clear Cache
</button> </button>
<button class="btn variant-filled-primary" onclick={() => refresh_trigger++}> <button
class="btn variant-filled-primary"
onclick={() => refresh_trigger++}>
<RefreshCw size="1em" class="mr-2" /> Force Refresh <RefreshCw size="1em" class="mr-2" /> Force Refresh
</button> </button>
</div> </div>
</header> </header>
{#key refresh_trigger} {#key refresh_trigger}
<section class="card p-4 space-y-4 variant-soft-primary"> <section class="card variant-soft-primary space-y-4 p-4">
<h2 class="h3">Scenario 1: Global Default</h2> <h2 class="h3">Scenario 1: Global Default</h2>
<p class="text-sm">Fetching code <code>{test_null_act_and_for}</code>. Should fall back to <code>account_id = NULL</code> if not found for account.</p> <p class="text-sm">
<div class="bg-surface-100 dark:bg-surface-800 p-4 rounded-lg border border-surface-500/20"> Fetching code <code>{test_null_act_and_for}</code>. Should fall
<AE_Element_Data_Store back to <code>account_id = NULL</code> if not found for account.
ds_code={test_null_act_and_for} </p>
ds_name={'Global Default Test'} <div
{log_lvl} class="bg-surface-100 dark:bg-surface-800 border-surface-500/20 rounded-lg border p-4">
debug={true} <AE_Element_Data_Store
/> ds_code={test_null_act_and_for}
</div> ds_name={'Global Default Test'}
</section> {log_lvl}
debug={true} />
</div>
</section>
<section class="card p-4 space-y-4 variant-soft-secondary"> <section class="card variant-soft-secondary space-y-4 p-4">
<h2 class="h3">Scenario 2: Account Default</h2> <h2 class="h3">Scenario 2: Account Default</h2>
<p class="text-sm">Fetching code <code>{test_code_account}</code> for Account ID: <code>{$ae_loc.account_id}</code>.</p> <p class="text-sm">
<div class="bg-surface-100 dark:bg-surface-800 p-4 rounded-lg border border-surface-500/20"> Fetching code <code>{test_code_account}</code> for Account ID:
<AE_Element_Data_Store <code>{$ae_loc.account_id}</code>.
ds_code={test_code_account} </p>
ds_name={'Account Default Test'} <div
{log_lvl} class="bg-surface-100 dark:bg-surface-800 border-surface-500/20 rounded-lg border p-4">
debug={true} <AE_Element_Data_Store
/> ds_code={test_code_account}
</div> ds_name={'Account Default Test'}
</section> {log_lvl}
debug={true} />
</div>
</section>
<section class="card p-4 space-y-4 variant-soft-tertiary"> <section class="card variant-soft-tertiary space-y-4 p-4">
<h2 class="h3">Scenario 3: Specific Record (Event Override)</h2> <h2 class="h3">Scenario 3: Specific Record (Event Override)</h2>
<p class="text-sm">Fetching code <code>{test_code_and_for}</code> linked to <code>for_type: event</code> and <code>for_id: {testing_event_id}</code>.</p> <p class="text-sm">
<div class="bg-surface-100 dark:bg-surface-800 p-4 rounded-lg border border-surface-500/20"> Fetching code <code>{test_code_and_for}</code> linked to
<AE_Element_Data_Store <code>for_type: event</code>
ds_code={test_code_and_for} and <code>for_id: {testing_event_id}</code>.
ds_name={'Specific Record Test'} </p>
for_type="event" <div
for_id={testing_event_id} class="bg-surface-100 dark:bg-surface-800 border-surface-500/20 rounded-lg border p-4">
{log_lvl} <AE_Element_Data_Store
debug={true} ds_code={test_code_and_for}
/> ds_name={'Specific Record Test'}
</div> for_type="event"
</section> for_id={testing_event_id}
{log_lvl}
debug={true} />
</div>
</section>
<section class="card p-4 space-y-4 variant-soft-tertiary"> <section class="card variant-soft-tertiary space-y-4 p-4">
<h2 class="h3">Scenario 4: Change Props Passed</h2> <h2 class="h3">Scenario 4: Change Props Passed</h2>
<p class="text-sm">Fetching code <code>{test_code_and_for}</code> linked to <code>for_type: event</code> and <code>for_id: {testing_event_id}</code>.</p> <p class="text-sm">
<div class="bg-surface-100 dark:bg-surface-800 p-4 rounded-lg border border-surface-500/20"> Fetching code <code>{test_code_and_for}</code> linked to
<AE_Element_Data_Store <code>for_type: event</code>
ds_code={test_code_and_for} and <code>for_id: {testing_event_id}</code>.
ds_name={'Specific Record Test'} </p>
ds_type="html" <div
for_type="event" class="bg-surface-100 dark:bg-surface-800 border-surface-500/20 rounded-lg border p-4">
for_id={testing_event_id} <AE_Element_Data_Store
class_li="w-fit max-w-(--breakpoint-lg) text-xl text-red-500 font-bold text-center p-1 m-1 border border-red-200 rounded-md bg-red-100" ds_code={test_code_and_for}
show_edit={false} ds_name={'Specific Record Test'}
show_edit_btn={true} ds_type="html"
{log_lvl} for_type="event"
debug={true} for_id={testing_event_id}
/> class_li="w-fit max-w-(--breakpoint-lg) text-xl text-red-500 font-bold text-center p-1 m-1 border border-red-200 rounded-md bg-red-100"
</div> show_edit={false}
</section> show_edit_btn={true}
{log_lvl}
debug={true} />
</div>
</section>
{/key} {/key}
<section class="card p-4 space-y-4"> <section class="card space-y-4 p-4">
<h2 class="h3">Current Context</h2> <h2 class="h3">Current Context</h2>
<div class="grid grid-cols-2 gap-4 text-xs font-mono"> <div class="grid grid-cols-2 gap-4 font-mono text-xs">
<div class="bg-surface-900 text-success-500 p-2 rounded"> <div class="bg-surface-900 text-success-500 rounded p-2">
<strong>Account ID:</strong> {$ae_loc.account_id || 'NULL'} <strong>Account ID:</strong>
{$ae_loc.account_id || 'NULL'}
</div> </div>
<div class="bg-surface-900 text-success-500 p-2 rounded"> <div class="bg-surface-900 text-success-500 rounded p-2">
<strong>Edit Mode:</strong> {$ae_loc.edit_mode} <strong>Edit Mode:</strong>
{$ae_loc.edit_mode}
</div> </div>
</div> </div>
</section> </section>

View File

@@ -1,20 +1,24 @@
<script lang="ts"> <script lang="ts">
import AE_Comp_Editor_TipTap from '$lib/elements/element_editor_tiptap.svelte'; import AE_Comp_Editor_TipTap from '$lib/elements/element_editor_tiptap.svelte';
import AE_Comp_Editor_CodeMirror from '$lib/elements/element_editor_codemirror.svelte'; import AE_Comp_Editor_CodeMirror from '$lib/elements/element_editor_codemirror.svelte';
import { Code, Eye } from '@lucide/svelte'; import { Code, Eye } from '@lucide/svelte';
let test_content = $state('<h2>Welcome to the Visual Editor Test</h2><p>This editor uses <strong>native browser rich text</strong> capabilities.</p><ul><li>No library conflicts</li><li>Uses existing <em>.tiptap</em> styles</li><li>Instant performance</li></ul>'); let test_content = $state(
let log_lvl = 1; '<h2>Welcome to the Visual Editor Test</h2><p>This editor uses <strong>native browser rich text</strong> capabilities.</p><ul><li>No library conflicts</li><li>Uses existing <em>.tiptap</em> styles</li><li>Instant performance</li></ul>'
);
let log_lvl = 1;
</script> </script>
<div class="p-8 space-y-8 max-w-5xl mx-auto h-full overflow-y-auto"> <div class="mx-auto h-full max-w-5xl space-y-8 overflow-y-auto p-8">
<header class="border-b border-surface-500/30 pb-4"> <header class="border-surface-500/30 border-b pb-4">
<h1 class="h1">Rich Text Editor Test</h1> <h1 class="h1">Rich Text Editor Test</h1>
<p class="opacity-70">Testing the Zero-Dependency "TipTap" replacement.</p> <p class="opacity-70">
Testing the Zero-Dependency "TipTap" replacement.
</p>
</header> </header>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8"> <div class="grid grid-cols-1 gap-8 lg:grid-cols-2">
<!-- Visual Editor --> <!-- Visual Editor -->
<section class="card p-4 space-y-4 variant-soft-primary"> <section class="card variant-soft-primary space-y-4 p-4">
<h2 class="h3 flex items-center gap-2"> <h2 class="h3 flex items-center gap-2">
<Eye size="1em" class="text-primary-500" /> <Eye size="1em" class="text-primary-500" />
Visual Editor (AE_Comp_Editor_TipTap) Visual Editor (AE_Comp_Editor_TipTap)
@@ -22,30 +26,33 @@
<div class="bg-surface-100 dark:bg-surface-800 rounded-lg"> <div class="bg-surface-100 dark:bg-surface-800 rounded-lg">
<AE_Comp_Editor_TipTap <AE_Comp_Editor_TipTap
bind:content={test_content} bind:content={test_content}
placeholder="Try writing something pretty..." placeholder="Try writing something pretty..." />
/>
</div> </div>
</section> </section>
<!-- Source Code View --> <!-- Source Code View -->
<section class="card p-4 space-y-4 variant-soft-tertiary"> <section class="card variant-soft-tertiary space-y-4 p-4">
<h2 class="h3 flex items-center gap-2"> <h2 class="h3 flex items-center gap-2">
<Code size="1em" class="text-tertiary-500" /> <Code size="1em" class="text-tertiary-500" />
Source View (AE_Comp_Editor_CodeMirror) Source View (AE_Comp_Editor_CodeMirror)
</h2> </h2>
<div class="bg-surface-100 dark:bg-surface-800 rounded-lg h-[250px]"> <div
class="bg-surface-100 dark:bg-surface-800 h-[250px] rounded-lg">
<AE_Comp_Editor_CodeMirror <AE_Comp_Editor_CodeMirror
bind:content={test_content} bind:content={test_content}
language="html" language="html"
show_line_numbers={true} show_line_numbers={true} />
/>
</div> </div>
</section> </section>
</div> </div>
<!-- HTML Preview --> <!-- HTML Preview -->
<section class="card p-4 space-y-4 bg-surface-900 text-green-400 font-mono text-xs overflow-auto max-h-96 shadow-2xl border border-white/10"> <section
<h2 class="text-sm font-bold opacity-50 uppercase tracking-widest border-b border-white/10 pb-2">Raw Bound Content (Saved to DB)</h2> class="card bg-surface-900 max-h-96 space-y-4 overflow-auto border border-white/10 p-4 font-mono text-xs text-green-400 shadow-2xl">
<h2
class="border-b border-white/10 pb-2 text-sm font-bold tracking-widest uppercase opacity-50">
Raw Bound Content (Saved to DB)
</h2>
<pre class="whitespace-pre">{test_content}</pre> <pre class="whitespace-pre">{test_content}</pre>
</section> </section>
</div> </div>

View File

@@ -1,71 +1,76 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; import { onMount } from 'svelte';
let status: string[] = $state([]); let status: string[] = $state([]);
function log(msg: string) { function log(msg: string) {
status = [...status, `${new Date().toLocaleTimeString()} - ${msg}`]; status = [...status, `${new Date().toLocaleTimeString()} - ${msg}`];
console.log(`[FIX-SW] ${msg}`); console.log(`[FIX-SW] ${msg}`);
}
async function nukeServiceWorkers() {
log('Starting Service Worker cleanup...');
if (!('serviceWorker' in navigator)) {
log('Service Workers not supported in this browser.');
return;
} }
async function nukeServiceWorkers() { try {
log('Starting Service Worker cleanup...'); const registrations = await navigator.serviceWorker.getRegistrations();
log(`Found ${registrations.length} registrations.`);
if (!('serviceWorker' in navigator)) { for (const registration of registrations) {
log('Service Workers not supported in this browser.'); const scope = registration.scope;
return; log(`Unregistering SW at scope: ${scope}`);
const success = await registration.unregister();
log(`Unregister success: ${success}`);
} }
try { if (registrations.length === 0) {
const registrations = await navigator.serviceWorker.getRegistrations(); log('No active Service Workers found.');
log(`Found ${registrations.length} registrations.`);
for (const registration of registrations) {
const scope = registration.scope;
log(`Unregistering SW at scope: ${scope}`);
const success = await registration.unregister();
log(`Unregister success: ${success}`);
}
if (registrations.length === 0) {
log('No active Service Workers found.');
}
log('Clearing Cache Storage...');
const cacheKeys = await caches.keys();
for (const key of cacheKeys) {
log(`Deleting cache: ${key}`);
await caches.delete(key);
}
log('Cache storage cleared.');
log('DONE. Please reload the application now.');
} catch (err: any) {
log(`ERROR: ${err.message}`);
console.error(err);
} }
log('Clearing Cache Storage...');
const cacheKeys = await caches.keys();
for (const key of cacheKeys) {
log(`Deleting cache: ${key}`);
await caches.delete(key);
}
log('Cache storage cleared.');
log('DONE. Please reload the application now.');
} catch (err: any) {
log(`ERROR: ${err.message}`);
console.error(err);
} }
}
onMount(() => { onMount(() => {
nukeServiceWorkers(); nukeServiceWorkers();
}); });
</script> </script>
<div class="p-8 max-w-2xl mx-auto font-mono"> <div class="mx-auto max-w-2xl p-8 font-mono">
<h1 class="text-2xl font-bold mb-4 text-red-600">Service Worker Reset Tool</h1> <h1 class="mb-4 text-2xl font-bold text-red-600">
<p class="mb-4">Attempting to unregister all service workers and clear caches to fix the TypeError loop.</p> Service Worker Reset Tool
</h1>
<p class="mb-4">
Attempting to unregister all service workers and clear caches to fix the
TypeError loop.
</p>
<div class="bg-gray-100 p-4 rounded border border-gray-300 min-h-[200px]"> <div class="min-h-[200px] rounded border border-gray-300 bg-gray-100 p-4">
{#each status as line, i (i)} {#each status as line, i (i)}
<div class="border-b border-gray-200 last:border-0 py-1">{line}</div> <div class="border-b border-gray-200 py-1 last:border-0">
{line}
</div>
{/each} {/each}
</div> </div>
<button <button
class="mt-4 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700" class="mt-4 rounded bg-blue-600 px-4 py-2 text-white hover:bg-blue-700"
onclick={() => window.location.reload()} onclick={() => window.location.reload()}>
>
Reload Page Reload Page
</button> </button>
</div> </div>

View File

@@ -1,128 +1,151 @@
<script lang="ts"> <script lang="ts">
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { ae_api, ae_loc } from '$lib/stores/ae_stores'; import { ae_api, ae_loc } from '$lib/stores/ae_stores';
import { load_ae_obj_id__hosted_file } from '$lib/ae_core/core__hosted_files'; import { load_ae_obj_id__hosted_file } from '$lib/ae_core/core__hosted_files';
import AE_Comp_Hosted_Files_Download_Button from '$lib/ae_core/ae_comp__hosted_files_download_button.svelte'; import AE_Comp_Hosted_Files_Download_Button from '$lib/ae_core/ae_comp__hosted_files_download_button.svelte';
import * as Lucide from 'lucide-svelte'; import * as Lucide from 'lucide-svelte';
let hosted_files: any[] = $state([]); let hosted_files: any[] = $state([]);
let large_file_obj: any = $state(null); let large_file_obj: any = $state(null);
let loading = $state(true); let loading = $state(true);
// Testing Toggles // Testing Toggles
let test_direct_download = $state(false); let test_direct_download = $state(false);
const LARGE_FILE_ID = 'sPw1he_RGCW'; const LARGE_FILE_ID = 'sPw1he_RGCW';
const test_ids = [ const test_ids = [
'QpyZNtEb2LQBmNJPQU_aOA', // small.mp4 'QpyZNtEb2LQBmNJPQU_aOA', // small.mp4
'ZmMTrrqx8nTTY0Cj0wvA3Q', // Test PowerPoint video.pptx 'ZmMTrrqx8nTTY0Cj0wvA3Q', // Test PowerPoint video.pptx
'e7NcV-275YPLQLoFMWuUZw', // Test PDF.pdf 'e7NcV-275YPLQLoFMWuUZw', // Test PDF.pdf
'INVALID_ID_TEST' 'INVALID_ID_TEST'
]; ];
onMount(async () => { onMount(async () => {
// Load the large file specifically first // Load the large file specifically first
large_file_obj = await load_ae_obj_id__hosted_file({ large_file_obj = await load_ae_obj_id__hosted_file({
api_cfg: $ae_api, api_cfg: $ae_api,
hosted_file_id: LARGE_FILE_ID, hosted_file_id: LARGE_FILE_ID,
log_lvl: 1 log_lvl: 1
});
// Fallback for large file if API doesn't have it (for UI testing)
if (!large_file_obj) {
large_file_obj = {
id: LARGE_FILE_ID,
hosted_file_id: LARGE_FILE_ID,
filename: 'Large_Test_File_Fallback.zip',
extension: 'zip',
hash_sha256: 'pending...'
};
}
const promises = test_ids.map(id =>
load_ae_obj_id__hosted_file({
api_cfg: $ae_api,
hosted_file_id: id,
log_lvl: 1
})
);
const results = await Promise.all(promises);
hosted_files = results.filter((f: any) => f !== null) as any[];
// Add a fake object for the invalid ID test
hosted_files.push({
id: 'INVALID_ID_TEST',
hosted_file_id: 'INVALID_ID_TEST',
filename: 'non_existent_file.txt',
extension: 'txt',
hash_sha256: '0000000000'
});
loading = false;
}); });
// Fallback for large file if API doesn't have it (for UI testing)
if (!large_file_obj) {
large_file_obj = {
id: LARGE_FILE_ID,
hosted_file_id: LARGE_FILE_ID,
filename: 'Large_Test_File_Fallback.zip',
extension: 'zip',
hash_sha256: 'pending...'
};
}
const promises = test_ids.map((id) =>
load_ae_obj_id__hosted_file({
api_cfg: $ae_api,
hosted_file_id: id,
log_lvl: 1
})
);
const results = await Promise.all(promises);
hosted_files = results.filter((f: any) => f !== null) as any[];
// Add a fake object for the invalid ID test
hosted_files.push({
id: 'INVALID_ID_TEST',
hosted_file_id: 'INVALID_ID_TEST',
filename: 'non_existent_file.txt',
extension: 'txt',
hash_sha256: '0000000000'
});
loading = false;
});
</script> </script>
<!-- Outer wrapper to enable scrolling if parent is overflow-hidden --> <!-- Outer wrapper to enable scrolling if parent is overflow-hidden -->
<div class="h-full w-full overflow-y-auto overflow-x-hidden bg-transparent"> <div class="h-full w-full overflow-x-hidden overflow-y-auto bg-transparent">
<div class="container mx-auto p-4 space-y-8 pb-20"> <div class="container mx-auto space-y-8 p-4 pb-20">
<header class="flex flex-col md:flex-row justify-between items-start md:items-center bg-surface-50-900-token p-6 rounded-container shadow-xl border border-gray-500 gap-4"> <header
class="bg-surface-50-900-token rounded-container flex flex-col items-start justify-between gap-4 border border-gray-500 p-6 shadow-xl md:flex-row md:items-center">
<div class="space-y-1"> <div class="space-y-1">
<h1 class="h1 flex items-center gap-3"> <h1 class="h1 flex items-center gap-3">
<Lucide.Download class="text-primary-500" /> Hosted Files Testing <Lucide.Download class="text-primary-500" /> Hosted Files Testing
</h1> </h1>
<p class="opacity-60 text-sm">Testing the AE_Comp_Hosted_Files_Download_Button component</p> <p class="text-sm opacity-60">
Testing the AE_Comp_Hosted_Files_Download_Button component
</p>
</div> </div>
<div class="flex flex-wrap gap-3 items-center bg-black/20 p-3 rounded-lg border border-white/10"> <div
<div class="flex items-center gap-2 pr-3 border-r border-white/10"> class="flex flex-wrap items-center gap-3 rounded-lg border border-white/10 bg-black/20 p-3">
<span class="text-[10px] font-bold uppercase opacity-50">Edit Mode</span> <div
<span class="badge {$ae_loc.edit_mode ? 'variant-filled-success' : 'variant-filled-surface'}"> class="flex items-center gap-2 border-r border-white/10 pr-3">
<span class="text-[10px] font-bold uppercase opacity-50"
>Edit Mode</span>
<span
class="badge {$ae_loc.edit_mode
? 'variant-filled-success'
: 'variant-filled-surface'}">
{$ae_loc.edit_mode ? 'ON' : 'OFF'} {$ae_loc.edit_mode ? 'ON' : 'OFF'}
</span> </span>
</div> </div>
<div class="flex items-center gap-3"> <div class="flex items-center gap-3">
<span class="text-[10px] font-bold uppercase opacity-50">Direct Download</span> <span class="text-[10px] font-bold uppercase opacity-50"
>Direct Download</span>
<button <button
class="btn btn-sm {test_direct_download ? 'variant-filled-primary' : 'variant-soft-surface'}" class="btn btn-sm {test_direct_download
onclick={() => test_direct_download = !test_direct_download} ? 'variant-filled-primary'
> : 'variant-soft-surface'}"
{test_direct_download ? 'Anchor Mode (<a>)' : 'Action Mode (<button>)'} onclick={() =>
(test_direct_download = !test_direct_download)}>
{test_direct_download
? 'Anchor Mode (<a>)'
: 'Action Mode (<button>)'}
</button> </button>
</div> </div>
</div> </div>
</header> </header>
<!-- Dedicated Large File Section --> <!-- Dedicated Large File Section -->
<div class="card p-6 variant-soft-primary border-2 border-primary-500 shadow-xl space-y-4"> <div
<header class="flex justify-between items-center border-b border-primary-500/30 pb-2"> class="card variant-soft-primary border-primary-500 space-y-4 border-2 p-6 shadow-xl">
<header
class="border-primary-500/30 flex items-center justify-between border-b pb-2">
<h2 class="h2 flex items-center gap-2"> <h2 class="h2 flex items-center gap-2">
<Lucide.Zap class="text-warning-500" /> Large File Progress Test <Lucide.Zap class="text-warning-500" /> Large File Progress Test
</h2> </h2>
<div class="flex gap-2"> <div class="flex gap-2">
<span class="badge variant-filled-warning animate-pulse">Testing Percentage</span> <span class="badge variant-filled-warning animate-pulse"
>Testing Percentage</span>
{#if test_direct_download} {#if test_direct_download}
<span class="badge variant-filled-secondary">Direct Link</span> <span class="badge variant-filled-secondary"
>Direct Link</span>
{/if} {/if}
</div> </div>
</header> </header>
<p class="text-sm opacity-80 italic"> <p class="text-sm italic opacity-80">
Use this file to verify the <strong>percentage counter</strong> and <strong>loading spinner</strong>. Use this file to verify the <strong>percentage counter</strong>
This file is ~100MB+, which should provide ample time to observe the progress state. and <strong>loading spinner</strong>. This file is ~100MB+,
which should provide ample time to observe the progress state.
</p> </p>
{#if large_file_obj} {#if large_file_obj}
<div class="bg-black/20 p-4 rounded-container border border-primary-500/20 flex flex-col md:flex-row justify-between items-center gap-4"> <div
class="rounded-container border-primary-500/20 flex flex-col items-center justify-between gap-4 border bg-black/20 p-4 md:flex-row">
<div class="flex items-center gap-4"> <div class="flex items-center gap-4">
<div class="p-3 bg-primary-500/20 rounded-lg"> <div class="bg-primary-500/20 rounded-lg p-3">
<Lucide.FileArchive size={32} /> <Lucide.FileArchive size={32} />
</div> </div>
<div> <div>
<h3 class="font-bold text-lg">{large_file_obj.filename}</h3> <h3 class="text-lg font-bold">
<p class="text-xs font-mono opacity-50">ID: {LARGE_FILE_ID}</p> {large_file_obj.filename}
</h3>
<p class="font-mono text-xs opacity-50">
ID: {LARGE_FILE_ID}
</p>
</div> </div>
</div> </div>
@@ -133,95 +156,112 @@
show_direct_download={test_direct_download} show_direct_download={test_direct_download}
variant="filled" variant="filled"
color="primary" color="primary"
classes="w-full md:min-w-64 py-4" classes="w-full md:min-w-64 py-4" />
/>
</div> </div>
</div> </div>
{/if} {/if}
</div> </div>
<div class="card p-6 variant-soft-surface space-y-4 border border-gray-500 shadow-lg"> <div
class="card variant-soft-surface space-y-4 border border-gray-500 p-6 shadow-lg">
<h2 class="h2">Style & Variant Trials</h2> <h2 class="h2">Style & Variant Trials</h2>
{#if loading} {#if loading}
<div class="flex items-center gap-2 py-10 justify-center"> <div class="flex items-center justify-center gap-2 py-10">
<Lucide.LoaderCircle class="animate-spin" /> <Lucide.LoaderCircle class="animate-spin" />
<span>Loading test metadata gallery...</span> <span>Loading test metadata gallery...</span>
</div> </div>
{:else} {:else}
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> <div class="grid grid-cols-1 gap-6 md:grid-cols-2">
{#each hosted_files as file (file.id)} {#each hosted_files as file (file.id)}
<div class="card p-4 variant-soft-secondary space-y-4"> <div class="card variant-soft-secondary space-y-4 p-4">
<div class="flex justify-between items-start"> <div class="flex items-start justify-between">
<div> <div>
<h3 class="font-bold">{file.filename}</h3> <h3 class="font-bold">{file.filename}</h3>
<p class="text-xs opacity-60 font-mono">ID: {file.id}</p> <p class="font-mono text-xs opacity-60">
ID: {file.id}
</p>
</div> </div>
<span class="badge variant-filled-primary uppercase">{file.extension}</span> <span
class="badge variant-filled-primary uppercase"
>{file.extension}</span>
</div> </div>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4 pt-2"> <div
class="grid grid-cols-1 gap-4 pt-2 sm:grid-cols-2">
<div class="space-y-1"> <div class="space-y-1">
<p class="text-[10px] opacity-50 uppercase font-bold">Variant: Tonal</p> <p
class="text-[10px] font-bold uppercase opacity-50">
Variant: Tonal
</p>
<AE_Comp_Hosted_Files_Download_Button <AE_Comp_Hosted_Files_Download_Button
hosted_file_id={file.id} hosted_file_id={file.id}
hosted_file_obj={file} hosted_file_obj={file}
show_direct_download={test_direct_download} show_direct_download={test_direct_download}
variant="tonal" variant="tonal"
color="primary" color="primary"
classes="w-full" classes="w-full" />
/>
</div> </div>
<div class="space-y-1"> <div class="space-y-1">
<p class="text-[10px] opacity-50 uppercase font-bold">Variant: Filled</p> <p
class="text-[10px] font-bold uppercase opacity-50">
Variant: Filled
</p>
<AE_Comp_Hosted_Files_Download_Button <AE_Comp_Hosted_Files_Download_Button
hosted_file_id={file.id} hosted_file_id={file.id}
hosted_file_obj={file} hosted_file_obj={file}
show_direct_download={test_direct_download} show_direct_download={test_direct_download}
variant="filled" variant="filled"
color="secondary" color="secondary"
classes="w-full" classes="w-full" />
/>
</div> </div>
<div class="space-y-1"> <div class="space-y-1">
<p class="text-[10px] opacity-50 uppercase font-bold">Variant: Outline</p> <p
class="text-[10px] font-bold uppercase opacity-50">
Variant: Outline
</p>
<AE_Comp_Hosted_Files_Download_Button <AE_Comp_Hosted_Files_Download_Button
hosted_file_id={file.id} hosted_file_id={file.id}
hosted_file_obj={file} hosted_file_obj={file}
show_direct_download={test_direct_download} show_direct_download={test_direct_download}
variant="outline" variant="outline"
color="tertiary" color="tertiary"
classes="w-full" classes="w-full" />
/>
</div> </div>
<div class="space-y-1"> <div class="space-y-1">
<p class="text-[10px] opacity-50 uppercase font-bold">Variant: Ghost</p> <p
class="text-[10px] font-bold uppercase opacity-50">
Variant: Ghost
</p>
<AE_Comp_Hosted_Files_Download_Button <AE_Comp_Hosted_Files_Download_Button
hosted_file_id={file.id} hosted_file_id={file.id}
hosted_file_obj={file} hosted_file_obj={file}
show_direct_download={test_direct_download} show_direct_download={test_direct_download}
variant="ghost" variant="ghost"
color="surface" color="surface"
classes="w-full" classes="w-full" />
/>
</div> </div>
</div> </div>
<div class="pt-2 border-t border-surface-500/20"> <div class="border-surface-500/20 border-t pt-2">
<p class="text-[10px] opacity-50 uppercase font-bold">Custom Label Snippet:</p> <p
class="text-[10px] font-bold uppercase opacity-50">
Custom Label Snippet:
</p>
<AE_Comp_Hosted_Files_Download_Button <AE_Comp_Hosted_Files_Download_Button
hosted_file_id={file.id} hosted_file_id={file.id}
hosted_file_obj={file} hosted_file_obj={file}
show_direct_download={test_direct_download} show_direct_download={test_direct_download}
variant="tonal" variant="tonal"
color="success" color="success"
classes="w-full mt-1" classes="w-full mt-1">
>
{#snippet label()} {#snippet label()}
<Lucide.FileArchive size={16} class="mr-2" /> <Lucide.FileArchive
size={16}
class="mr-2" />
<span>Download Source</span> <span>Download Source</span>
{/snippet} {/snippet}
</AE_Comp_Hosted_Files_Download_Button> </AE_Comp_Hosted_Files_Download_Button>
@@ -232,18 +272,20 @@
{/if} {/if}
</div> </div>
<div class="card p-6 variant-soft-warning border border-warning-500 shadow-lg"> <div
<h3 class="h3 font-bold text-warning-700 dark:text-warning-500 flex items-center gap-2"> class="card variant-soft-warning border-warning-500 border p-6 shadow-lg">
<h3
class="h3 text-warning-700 dark:text-warning-500 flex items-center gap-2 font-bold">
<Lucide.AlertTriangle size={20} /> Edge Case: Missing Metadata <Lucide.AlertTriangle size={20} /> Edge Case: Missing Metadata
</h3> </h3>
<p class="text-sm opacity-80 mt-2"> <p class="mt-2 text-sm opacity-80">
Testing the component when <code>hosted_file_id</code> or <code>hosted_file_obj</code> is missing. Testing the component when <code>hosted_file_id</code> or
<code>hosted_file_obj</code> is missing.
</p> </p>
<div class="flex gap-4 mt-4"> <div class="mt-4 flex gap-4">
<AE_Comp_Hosted_Files_Download_Button <AE_Comp_Hosted_Files_Download_Button
hosted_file_id={null} hosted_file_id={null}
hosted_file_obj={null} hosted_file_obj={null} />
/>
</div> </div>
</div> </div>
</div> </div>