fix: add missing each-block keys (svelte/require-each-key)
Fixed all 27 remaining instances across 19 files. Keys used: - Object ID fields where available (e.g. account_id_random, event_file_id) - index for logger lists with no reliable unique key - Property name for Object.entries() loops
This commit is contained in:
@@ -6,9 +6,9 @@
|
|||||||
* Supports General, AI, Performance, and IDAA-specific configurations.
|
* Supports General, AI, Performance, and IDAA-specific configurations.
|
||||||
*/
|
*/
|
||||||
import { Modal } from 'flowbite-svelte';
|
import { Modal } from 'flowbite-svelte';
|
||||||
import {
|
import {
|
||||||
Palette, Mail, Brain, Timer,
|
Palette, Mail, Brain, Timer,
|
||||||
ShieldCheck, CodeXml, Save,
|
ShieldCheck, CodeXml, Save,
|
||||||
Plus, Minus, Globe, ExternalLink
|
Plus, Minus, Globe, ExternalLink
|
||||||
} from 'lucide-svelte';
|
} from 'lucide-svelte';
|
||||||
import AE_Comp_Editor_CodeMirror from '$lib/elements/AE_Comp_Editor_CodeMirror.svelte';
|
import AE_Comp_Editor_CodeMirror from '$lib/elements/AE_Comp_Editor_CodeMirror.svelte';
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
|
|
||||||
<!-- Scrollable Content Area -->
|
<!-- Scrollable Content Area -->
|
||||||
<div class="grow overflow-y-auto p-1 pr-2 space-y-6 max-h-[60vh]">
|
<div class="grow overflow-y-auto p-1 pr-2 space-y-6 max-h-[60vh]">
|
||||||
|
|
||||||
{#if active_tab === 'visuals'}
|
{#if active_tab === 'visuals'}
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 animate-in fade-in duration-200">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 animate-in fade-in duration-200">
|
||||||
<label class="label">
|
<label class="label">
|
||||||
@@ -221,7 +221,7 @@
|
|||||||
{ key: 'novi_trusted_li', label: 'Novi Trusted', color: 'text-warning-500' },
|
{ key: 'novi_trusted_li', label: 'Novi Trusted', color: 'text-warning-500' },
|
||||||
{ key: 'novi_jitsi_mod_li', label: 'Jitsi Moderators', color: 'text-primary-500' },
|
{ key: 'novi_jitsi_mod_li', label: 'Jitsi Moderators', color: 'text-primary-500' },
|
||||||
{ key: 'novi_idaa_group_guid_li', label: 'Member Group GUIDs', color: 'text-secondary-500' }
|
{ key: 'novi_idaa_group_guid_li', label: 'Member Group GUIDs', color: 'text-secondary-500' }
|
||||||
] as list}
|
] as list (list.key)}
|
||||||
<div class="space-y-2 p-3 bg-surface-500/5 rounded-lg">
|
<div class="space-y-2 p-3 bg-surface-500/5 rounded-lg">
|
||||||
<header class="flex justify-between items-center">
|
<header class="flex justify-between items-center">
|
||||||
<span class="text-[10px] font-black uppercase tracking-wider {list.color}">{list.label}</span>
|
<span class="text-[10px] font-black uppercase tracking-wider {list.color}">{list.label}</span>
|
||||||
@@ -280,7 +280,7 @@
|
|||||||
|
|
||||||
{:else if active_tab === 'raw'}
|
{:else if active_tab === 'raw'}
|
||||||
<div class="h-[50vh] animate-in fade-in duration-200">
|
<div class="h-[50vh] animate-in fade-in duration-200">
|
||||||
<AE_Comp_Editor_CodeMirror
|
<AE_Comp_Editor_CodeMirror
|
||||||
content={raw_json_str}
|
content={raw_json_str}
|
||||||
bind:new_content={raw_json_str}
|
bind:new_content={raw_json_str}
|
||||||
language="json"
|
language="json"
|
||||||
|
|||||||
@@ -415,7 +415,7 @@
|
|||||||
<th>Hash</th>
|
<th>Hash</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
{#each input_file_list_processed as file_list_item, file_index}
|
{#each input_file_list_processed as file_list_item, file_index (file_index)}
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="file_remove">
|
<td class="file_remove">
|
||||||
|
|||||||
@@ -355,7 +355,7 @@
|
|||||||
<th>Hash</th>
|
<th>Hash</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
{#each processed_file_list as file_list_item, file_index}
|
{#each processed_file_list as file_list_item, file_index (file_index)}
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="file_remove">
|
<td class="file_remove">
|
||||||
|
|||||||
@@ -127,7 +127,7 @@
|
|||||||
<ol class="list-decimal list-inside">
|
<ol class="list-decimal list-inside">
|
||||||
{#each [...$lq__hosted_file_obj_li]
|
{#each [...$lq__hosted_file_obj_li]
|
||||||
.reverse()
|
.reverse()
|
||||||
.slice(0, max_file_count) as hosted_file_obj}
|
.slice(0, max_file_count) as hosted_file_obj (hosted_file_obj.hosted_file_id)}
|
||||||
<li>
|
<li>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
{#if obj != null && typeof obj == 'object'}
|
{#if obj != null && typeof obj == 'object'}
|
||||||
{#each Object.entries(obj) as [obj_prop_name, obj_prop_value]}
|
{#each Object.entries(obj) as [obj_prop_name, obj_prop_value] (obj_prop_name)}
|
||||||
<!-- NEED TO ADD A CHECK IF:
|
<!-- NEED TO ADD A CHECK IF:
|
||||||
NOTE and WARNING:
|
NOTE and WARNING:
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
let qry_str = $state('');
|
let qry_str = $state('');
|
||||||
|
|
||||||
let filtered_li = $derived(
|
let filtered_li = $derived(
|
||||||
qry_str
|
qry_str
|
||||||
? account_li.filter(a =>
|
? account_li.filter(a =>
|
||||||
a.name?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
a.name?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
||||||
a.code?.toLowerCase().includes(qry_str.toLowerCase())
|
a.code?.toLowerCase().includes(qry_str.toLowerCase())
|
||||||
)
|
)
|
||||||
: account_li
|
: account_li
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
if (!name) return;
|
if (!name) return;
|
||||||
|
|
||||||
const code = prompt('Enter account code (optional):');
|
const code = prompt('Enter account code (optional):');
|
||||||
|
|
||||||
const new_acct = await create_ae_obj__account({
|
const new_acct = await create_ae_obj__account({
|
||||||
api_cfg: $ae_api,
|
api_cfg: $ae_api,
|
||||||
data_kv: {
|
data_kv: {
|
||||||
@@ -81,11 +81,11 @@
|
|||||||
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
|
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
|
||||||
<Search size={18} class="opacity-50" />
|
<Search size={18} class="opacity-50" />
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
|
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
|
||||||
type="search"
|
type="search"
|
||||||
bind:value={qry_str}
|
bind:value={qry_str}
|
||||||
placeholder="Search by name or code..."
|
placeholder="Search by name or code..."
|
||||||
/>
|
/>
|
||||||
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_accounts} disabled={loading}>
|
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_accounts} disabled={loading}>
|
||||||
{#if loading}
|
{#if loading}
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{#each filtered_li as acct}
|
{#each filtered_li as acct (acct.account_id_random)}
|
||||||
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
|
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
|
||||||
<div class="absolute top-4 right-4 flex gap-1">
|
<div class="absolute top-4 right-4 flex gap-1">
|
||||||
{#if acct.hide}
|
{#if acct.hide}
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
<p class="text-[10px] uppercase font-bold opacity-50 font-mono tracking-tighter">Code: {acct.code || '--'}</p>
|
<p class="text-[10px] uppercase font-bold opacity-50 font-mono tracking-tighter">Code: {acct.code || '--'}</p>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="space-y-2 text-xs opacity-70">
|
<div class="space-y-2 text-xs opacity-70">
|
||||||
<div class="flex items-center gap-2 bg-black/5 p-2 rounded-lg">
|
<div class="flex items-center gap-2 bg-black/5 p-2 rounded-lg">
|
||||||
<Calendar size={14} class="text-primary-500 shrink-0" />
|
<Calendar size={14} class="text-primary-500 shrink-0" />
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
async function load_logs() {
|
async function load_logs() {
|
||||||
if (!$ae_loc.account_id) return;
|
if (!$ae_loc.account_id) return;
|
||||||
loading = true;
|
loading = true;
|
||||||
|
|
||||||
const results = await qry__activity_log({
|
const results = await qry__activity_log({
|
||||||
api_cfg: $ae_api,
|
api_cfg: $ae_api,
|
||||||
account_id: $ae_loc.account_id,
|
account_id: $ae_loc.account_id,
|
||||||
@@ -77,11 +77,11 @@
|
|||||||
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
|
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
|
||||||
<Search size={18} class="opacity-50" />
|
<Search size={18} class="opacity-50" />
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
|
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
|
||||||
type="search"
|
type="search"
|
||||||
bind:value={qry_str}
|
bind:value={qry_str}
|
||||||
placeholder="Action, name, description..."
|
placeholder="Action, name, description..."
|
||||||
/>
|
/>
|
||||||
<button type="submit" class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" disabled={loading}>
|
<button type="submit" class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" disabled={loading}>
|
||||||
<span class="whitespace-nowrap tracking-wide">Search</span>
|
<span class="whitespace-nowrap tracking-wide">Search</span>
|
||||||
@@ -131,7 +131,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each log_li as log}
|
{#each log_li as log, index (index)}
|
||||||
<tr class="transition-colors text-sm">
|
<tr class="transition-colors text-sm">
|
||||||
<!-- Date/Time -->
|
<!-- Date/Time -->
|
||||||
<td class="whitespace-nowrap">
|
<td class="whitespace-nowrap">
|
||||||
|
|||||||
@@ -11,9 +11,9 @@
|
|||||||
let show_add_form = $state(false);
|
let show_add_form = $state(false);
|
||||||
let qry_str = $state('');
|
let qry_str = $state('');
|
||||||
let filtered_li: any[] = $derived(
|
let filtered_li: any[] = $derived(
|
||||||
qry_str
|
qry_str
|
||||||
? address_li.filter(a =>
|
? address_li.filter(a =>
|
||||||
a.city?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
a.city?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
||||||
a.state_province?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
a.state_province?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
||||||
a.organization_name?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
a.organization_name?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
||||||
a.line_1?.toLowerCase().includes(qry_str.toLowerCase())
|
a.line_1?.toLowerCase().includes(qry_str.toLowerCase())
|
||||||
@@ -51,8 +51,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<h1 class="h2 font-black tracking-tight">Address Management</h1>
|
<h1 class="h2 font-black tracking-tight">Address Management</h1>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm variant-filled-primary font-bold shadow-lg"
|
class="btn btn-sm variant-filled-primary font-bold shadow-lg"
|
||||||
onclick={() => show_add_form = !show_add_form}
|
onclick={() => show_add_form = !show_add_form}
|
||||||
>
|
>
|
||||||
{#if show_add_form}
|
{#if show_add_form}
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
|
|
||||||
{#if show_add_form}
|
{#if show_add_form}
|
||||||
<div class="animate-fade-in">
|
<div class="animate-fade-in">
|
||||||
<Address_form
|
<Address_form
|
||||||
onSave={(new_addr) => {
|
onSave={(new_addr) => {
|
||||||
show_add_form = false;
|
show_add_form = false;
|
||||||
load_addresses();
|
load_addresses();
|
||||||
@@ -85,11 +85,11 @@
|
|||||||
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
|
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
|
||||||
<Search size={18} class="opacity-50" />
|
<Search size={18} class="opacity-50" />
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
|
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
|
||||||
type="search"
|
type="search"
|
||||||
bind:value={qry_str}
|
bind:value={qry_str}
|
||||||
placeholder="Search by city, state, organization, or street..."
|
placeholder="Search by city, state, organization, or street..."
|
||||||
/>
|
/>
|
||||||
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_addresses} disabled={loading}>
|
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_addresses} disabled={loading}>
|
||||||
{#if loading}
|
{#if loading}
|
||||||
@@ -119,9 +119,9 @@
|
|||||||
Linked Addresses
|
Linked Addresses
|
||||||
<span class="badge variant-soft-secondary ml-auto">{filtered_li.length} entries</span>
|
<span class="badge variant-soft-secondary ml-auto">{filtered_li.length} entries</span>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{#each filtered_li as addr}
|
{#each filtered_li as addr (addr.address_id_random)}
|
||||||
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
|
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
|
||||||
<div class="absolute top-4 right-4">
|
<div class="absolute top-4 right-4">
|
||||||
<span class="badge {addr.enable ? 'variant-filled-success' : 'variant-filled-error'} text-[8px] uppercase font-bold shadow-sm">
|
<span class="badge {addr.enable ? 'variant-filled-success' : 'variant-filled-error'} text-[8px] uppercase font-bold shadow-sm">
|
||||||
|
|||||||
@@ -74,7 +74,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each $lq_kv__person_obj_li as person_obj}
|
{#each $lq_kv__person_obj_li as person_obj (person_obj.person_id_random)}
|
||||||
<tr class:dim={person_obj?.hide}>
|
<tr class:dim={person_obj?.hide}>
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
<span class="fas fa-user"></span>
|
<span class="fas fa-user"></span>
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
let contact_li: any[] = $state([]);
|
let contact_li: any[] = $state([]);
|
||||||
let qry_str = $state('');
|
let qry_str = $state('');
|
||||||
let filtered_li: any[] = $derived(
|
let filtered_li: any[] = $derived(
|
||||||
qry_str
|
qry_str
|
||||||
? contact_li.filter(c =>
|
? contact_li.filter(c =>
|
||||||
c.name?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
c.name?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
||||||
c.title?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
c.title?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
||||||
c.email?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
c.email?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
||||||
c.phone_office?.toLowerCase().includes(qry_str.toLowerCase())
|
c.phone_office?.toLowerCase().includes(qry_str.toLowerCase())
|
||||||
@@ -51,8 +51,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<h1 class="h2 font-black tracking-tight">Contact Management</h1>
|
<h1 class="h2 font-black tracking-tight">Contact Management</h1>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm variant-filled-primary font-bold shadow-lg"
|
class="btn btn-sm variant-filled-primary font-bold shadow-lg"
|
||||||
onclick={() => show_add_form = !show_add_form}
|
onclick={() => show_add_form = !show_add_form}
|
||||||
>
|
>
|
||||||
{#if show_add_form}
|
{#if show_add_form}
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
|
|
||||||
{#if show_add_form}
|
{#if show_add_form}
|
||||||
<div class="animate-fade-in">
|
<div class="animate-fade-in">
|
||||||
<Contact_form
|
<Contact_form
|
||||||
onSave={(new_con) => {
|
onSave={(new_con) => {
|
||||||
show_add_form = false;
|
show_add_form = false;
|
||||||
load_contacts();
|
load_contacts();
|
||||||
@@ -85,11 +85,11 @@
|
|||||||
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
|
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
|
||||||
<Search size={18} class="opacity-50" />
|
<Search size={18} class="opacity-50" />
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
|
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
|
||||||
type="search"
|
type="search"
|
||||||
bind:value={qry_str}
|
bind:value={qry_str}
|
||||||
placeholder="Search by name, title, email, or phone..."
|
placeholder="Search by name, title, email, or phone..."
|
||||||
/>
|
/>
|
||||||
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_contacts} disabled={loading}>
|
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_contacts} disabled={loading}>
|
||||||
{#if loading}
|
{#if loading}
|
||||||
@@ -121,7 +121,7 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{#each filtered_li as con}
|
{#each filtered_li as con (con.contact_id_random)}
|
||||||
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
|
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
|
||||||
<div class="absolute top-4 right-4">
|
<div class="absolute top-4 right-4">
|
||||||
<span class="badge {con.enable ? 'variant-filled-success' : 'variant-filled-error'} text-[8px] uppercase font-bold shadow-sm">
|
<span class="badge {con.enable ? 'variant-filled-success' : 'variant-filled-error'} text-[8px] uppercase font-bold shadow-sm">
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
<p class="text-[10px] uppercase font-bold opacity-50 truncate">{con.title || 'Support Contact'}</p>
|
<p class="text-[10px] uppercase font-bold opacity-50 truncate">{con.title || 'Support Contact'}</p>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="space-y-2 text-xs opacity-70">
|
<div class="space-y-2 text-xs opacity-70">
|
||||||
<div class="flex items-center gap-2 bg-black/5 p-2 rounded-lg">
|
<div class="flex items-center gap-2 bg-black/5 p-2 rounded-lg">
|
||||||
<Mail size={14} class="text-primary-500 shrink-0" />
|
<Mail size={14} class="text-primary-500 shrink-0" />
|
||||||
|
|||||||
@@ -19,11 +19,11 @@
|
|||||||
const [countries, subdivisions, time_zones] = await Promise.all([
|
const [countries, subdivisions, time_zones] = await Promise.all([
|
||||||
api.get_ae_obj_li_for_lu({ api_cfg: $ae_api, for_lu_type: 'country', log_lvl: 1 }),
|
api.get_ae_obj_li_for_lu({ api_cfg: $ae_api, for_lu_type: 'country', log_lvl: 1 }),
|
||||||
api.get_ae_obj_li_for_lu({ api_cfg: $ae_api, for_lu_type: 'country_subdivision', log_lvl: 1 }),
|
api.get_ae_obj_li_for_lu({ api_cfg: $ae_api, for_lu_type: 'country_subdivision', log_lvl: 1 }),
|
||||||
api.get_ae_obj_li_for_lu({
|
api.get_ae_obj_li_for_lu({
|
||||||
api_cfg: $ae_api,
|
api_cfg: $ae_api,
|
||||||
for_lu_type: 'time_zone',
|
for_lu_type: 'time_zone',
|
||||||
only_priority: tz_only_priority,
|
only_priority: tz_only_priority,
|
||||||
log_lvl: 1
|
log_lvl: 1
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
Country Reference
|
Country Reference
|
||||||
<span class="badge variant-soft-secondary ml-auto text-[10px] uppercase font-bold">{lookups.countries.length} Records</span>
|
<span class="badge variant-soft-secondary ml-auto text-[10px] uppercase font-bold">{lookups.countries.length} Records</span>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="table-container max-h-[400px] overflow-auto border border-surface-500/10 rounded-lg">
|
<div class="table-container max-h-[400px] overflow-auto border border-surface-500/10 rounded-lg">
|
||||||
<table class="table table-hover table-compact">
|
<table class="table table-hover table-compact">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each lookups.countries as c}
|
{#each lookups.countries as c (c.alpha_2_code)}
|
||||||
<tr class="transition-colors">
|
<tr class="transition-colors">
|
||||||
<td class="font-bold">{c.name || c.english_short_name}</td>
|
<td class="font-bold">{c.name || c.english_short_name}</td>
|
||||||
<td class="text-center"><span class="badge variant-soft-surface font-mono text-primary-500">{c.alpha_2_code}</span></td>
|
<td class="text-center"><span class="badge variant-soft-surface font-mono text-primary-500">{c.alpha_2_code}</span></td>
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
Country Subdivisions (States/Provinces)
|
Country Subdivisions (States/Provinces)
|
||||||
<span class="badge variant-soft-secondary ml-auto text-[10px] uppercase font-bold">{lookups.subdivisions.length} Records</span>
|
<span class="badge variant-soft-secondary ml-auto text-[10px] uppercase font-bold">{lookups.subdivisions.length} Records</span>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="table-container max-h-[500px] overflow-auto border border-surface-500/10 rounded-lg">
|
<div class="table-container max-h-[500px] overflow-auto border border-surface-500/10 rounded-lg">
|
||||||
<table class="table table-hover table-compact">
|
<table class="table table-hover table-compact">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -130,7 +130,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each lookups.subdivisions as s}
|
{#each lookups.subdivisions as s, i (i)}
|
||||||
<tr class="transition-colors">
|
<tr class="transition-colors">
|
||||||
<td class="opacity-60">{s.country_alpha_2_code}</td>
|
<td class="opacity-60">{s.country_alpha_2_code}</td>
|
||||||
<td class="font-bold">{s.name}</td>
|
<td class="font-bold">{s.name}</td>
|
||||||
@@ -150,7 +150,7 @@
|
|||||||
Time Zone Reference
|
Time Zone Reference
|
||||||
<span class="badge variant-soft-secondary text-[10px] uppercase font-bold">{lookups.time_zones.length} Zones</span>
|
<span class="badge variant-soft-secondary text-[10px] uppercase font-bold">{lookups.time_zones.length} Zones</span>
|
||||||
</h3>
|
</h3>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm transition-all {tz_only_priority ? 'variant-filled-warning' : 'variant-soft-surface'}"
|
class="btn btn-sm transition-all {tz_only_priority ? 'variant-filled-warning' : 'variant-soft-surface'}"
|
||||||
onclick={toggle_tz_priority}
|
onclick={toggle_tz_priority}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
@@ -159,7 +159,7 @@
|
|||||||
{tz_only_priority ? 'Showing Priority' : 'Show Only Priority'}
|
{tz_only_priority ? 'Showing Priority' : 'Show Only Priority'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table-container max-h-[500px] overflow-auto border border-surface-500/10 rounded-lg">
|
<div class="table-container max-h-[500px] overflow-auto border border-surface-500/10 rounded-lg">
|
||||||
<table class="table table-hover table-compact">
|
<table class="table table-hover table-compact">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -169,7 +169,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each lookups.time_zones as tz}
|
{#each lookups.time_zones as tz (tz.name)}
|
||||||
<tr class="transition-colors">
|
<tr class="transition-colors">
|
||||||
<td class="font-bold">{tz.name}</td>
|
<td class="font-bold">{tz.name}</td>
|
||||||
<td class="text-right"><span class="badge variant-soft-surface font-mono">{tz.offset_seconds / 3600}h</span></td>
|
<td class="text-right"><span class="badge variant-soft-surface font-mono">{tz.offset_seconds / 3600}h</span></td>
|
||||||
|
|||||||
@@ -289,7 +289,7 @@
|
|||||||
<p class="text-center py-4 italic opacity-60 border border-dashed border-surface-500/30">No unlinked user accounts found.</p>
|
<p class="text-center py-4 italic opacity-60 border border-dashed border-surface-500/30">No unlinked user accounts found.</p>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">
|
||||||
{#each available_users as user}
|
{#each available_users as user (user.user_id)}
|
||||||
<button
|
<button
|
||||||
class="card p-3 variant-soft-primary hover:variant-filled-primary text-left transition-all flex flex-col gap-1"
|
class="card p-3 variant-soft-primary hover:variant-filled-primary text-left transition-all flex flex-col gap-1"
|
||||||
onclick={() => handle_link_user(user.user_id)}
|
onclick={() => handle_link_user(user.user_id)}
|
||||||
@@ -335,7 +335,7 @@
|
|||||||
<p class="text-sm italic opacity-50">No related events found.</p>
|
<p class="text-sm italic opacity-50">No related events found.</p>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
{#each related_events as ev}
|
{#each related_events as ev (ev.event_id)}
|
||||||
<a href="/events/{ev.event_id}" class="card p-3 variant-soft flex flex-col gap-1 hover:variant-soft-primary transition-all">
|
<a href="/events/{ev.event_id}" class="card p-3 variant-soft flex flex-col gap-1 hover:variant-soft-primary transition-all">
|
||||||
<span class="font-bold text-sm">{ev.name}</span>
|
<span class="font-bold text-sm">{ev.name}</span>
|
||||||
<span class="text-[10px] opacity-60">{new Date(ev.start_datetime).toLocaleDateString()}</span>
|
<span class="text-[10px] opacity-60">{new Date(ev.start_datetime).toLocaleDateString()}</span>
|
||||||
@@ -356,7 +356,7 @@
|
|||||||
<p class="text-sm italic opacity-50">No related posts found.</p>
|
<p class="text-sm italic opacity-50">No related posts found.</p>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
{#each related_posts as post}
|
{#each related_posts as post (post.post_id)}
|
||||||
<a href="/idaa/bb/{post.post_id}" class="card p-3 variant-soft flex flex-col gap-1 hover:variant-soft-primary transition-all">
|
<a href="/idaa/bb/{post.post_id}" class="card p-3 variant-soft flex flex-col gap-1 hover:variant-soft-primary transition-all">
|
||||||
<span class="font-bold text-sm">{post.title}</span>
|
<span class="font-bold text-sm">{post.title}</span>
|
||||||
<div class="flex justify-between items-center text-[10px] opacity-60">
|
<div class="flex justify-between items-center text-[10px] opacity-60">
|
||||||
@@ -380,7 +380,7 @@
|
|||||||
<p class="text-sm italic opacity-50">No recent activity logs.</p>
|
<p class="text-sm italic opacity-50">No recent activity logs.</p>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
{#each related_activity_logs as log}
|
{#each related_activity_logs as log, index (index)}
|
||||||
<div class="card p-3 variant-soft flex flex-col gap-1">
|
<div class="card p-3 variant-soft flex flex-col gap-1">
|
||||||
<div class="flex justify-between items-start gap-2">
|
<div class="flex justify-between items-start gap-2">
|
||||||
<span class="badge variant-filled-surface text-[9px] uppercase tracking-tighter">{log.action}</span>
|
<span class="badge variant-filled-surface text-[9px] uppercase tracking-tighter">{log.action}</span>
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
let qry_str = $state('');
|
let qry_str = $state('');
|
||||||
|
|
||||||
let filtered_li = $derived(
|
let filtered_li = $derived(
|
||||||
qry_str
|
qry_str
|
||||||
? site_li.filter(s =>
|
? site_li.filter(s =>
|
||||||
s.name?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
s.name?.toLowerCase().includes(qry_str.toLowerCase()) ||
|
||||||
s.code?.toLowerCase().includes(qry_str.toLowerCase())
|
s.code?.toLowerCase().includes(qry_str.toLowerCase())
|
||||||
)
|
)
|
||||||
: site_li
|
: site_li
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
if (!name) return;
|
if (!name) return;
|
||||||
|
|
||||||
const code = prompt('Enter site code (optional):');
|
const code = prompt('Enter site code (optional):');
|
||||||
|
|
||||||
const new_site = await create_ae_obj__site({
|
const new_site = await create_ae_obj__site({
|
||||||
api_cfg: $ae_api,
|
api_cfg: $ae_api,
|
||||||
account_id: $ae_loc.account_id,
|
account_id: $ae_loc.account_id,
|
||||||
@@ -84,11 +84,11 @@
|
|||||||
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
|
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
|
||||||
<Search size={18} class="opacity-50" />
|
<Search size={18} class="opacity-50" />
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
|
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
|
||||||
type="search"
|
type="search"
|
||||||
bind:value={qry_str}
|
bind:value={qry_str}
|
||||||
placeholder="Search by name or code..."
|
placeholder="Search by name or code..."
|
||||||
/>
|
/>
|
||||||
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_sites} disabled={loading}>
|
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_sites} disabled={loading}>
|
||||||
{#if loading}
|
{#if loading}
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{#each filtered_li as site}
|
{#each filtered_li as site (site.site_id_random)}
|
||||||
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
|
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group relative">
|
||||||
<div class="absolute top-4 right-4 flex gap-1">
|
<div class="absolute top-4 right-4 flex gap-1">
|
||||||
{#if site.hide}
|
{#if site.hide}
|
||||||
@@ -161,7 +161,7 @@
|
|||||||
<p class="text-[10px] uppercase font-bold opacity-50 font-mono tracking-tighter">Code: {site.code || '--'}</p>
|
<p class="text-[10px] uppercase font-bold opacity-50 font-mono tracking-tighter">Code: {site.code || '--'}</p>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="space-y-2 text-xs opacity-70">
|
<div class="space-y-2 text-xs opacity-70">
|
||||||
<div class="flex items-center gap-2 bg-black/5 p-2 rounded-lg">
|
<div class="flex items-center gap-2 bg-black/5 p-2 rounded-lg">
|
||||||
<Calendar size={14} class="text-primary-500 shrink-0" />
|
<Calendar size={14} class="text-primary-500 shrink-0" />
|
||||||
|
|||||||
@@ -166,9 +166,9 @@
|
|||||||
<h3 class="h4 font-bold border-b border-surface-500/30 pb-2 flex items-center gap-2">
|
<h3 class="h4 font-bold border-b border-surface-500/30 pb-2 flex items-center gap-2">
|
||||||
<Database size={18} class="text-warning-500" /> Site Settings (cfg_json)
|
<Database size={18} class="text-warning-500" /> Site Settings (cfg_json)
|
||||||
</h3>
|
</h3>
|
||||||
<AE_Comp_Site_Config_Editor
|
<AE_Comp_Site_Config_Editor
|
||||||
bind:cfg_json={site.cfg_json}
|
bind:cfg_json={site.cfg_json}
|
||||||
on_save={handle_save_site}
|
on_save={handle_save_site}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@
|
|||||||
<p class="text-sm opacity-60 text-center py-8 bg-surface-500/5 rounded-lg border-2 border-dashed border-surface-500/20">No domains configured.</p>
|
<p class="text-sm opacity-60 text-center py-8 bg-surface-500/5 rounded-lg border-2 border-dashed border-surface-500/20">No domains configured.</p>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="space-y-3">
|
<div class="space-y-3">
|
||||||
{#each domain_li as dom}
|
{#each domain_li as dom (dom.site_domain_id_random)}
|
||||||
<div class="card p-3 variant-soft shadow-sm border border-surface-500/10 flex justify-between items-center group">
|
<div class="card p-3 variant-soft shadow-sm border border-surface-500/10 flex justify-between items-center group">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<span class="font-bold text-sm flex items-center gap-1">
|
<span class="font-bold text-sm flex items-center gap-1">
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
async function load_users() {
|
async function load_users() {
|
||||||
loading = true;
|
loading = true;
|
||||||
|
|
||||||
let for_obj_id: string | null = $ae_loc.account_id;
|
let for_obj_id: string | null = $ae_loc.account_id;
|
||||||
let include_global = true;
|
let include_global = true;
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
const username = prompt('Enter new username:');
|
const username = prompt('Enter new username:');
|
||||||
if (!username) return;
|
if (!username) return;
|
||||||
const email = prompt('Enter email address:');
|
const email = prompt('Enter email address:');
|
||||||
|
|
||||||
// Link to account if scope is 'account' or 'all', otherwise create global user
|
// Link to account if scope is 'account' or 'all', otherwise create global user
|
||||||
const account_id = qry_account_scope === 'global' ? undefined : $ae_loc.account_id;
|
const account_id = qry_account_scope === 'global' ? undefined : $ae_loc.account_id;
|
||||||
|
|
||||||
@@ -87,12 +87,12 @@
|
|||||||
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
|
<div class="flex items-center justify-center px-4 bg-surface-300-600-token border-r border-surface-500/20">
|
||||||
<Search size={18} class="opacity-50" />
|
<Search size={18} class="opacity-50" />
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
|
class="bg-transparent border-0 ring-0 focus:ring-0 p-3 grow placeholder:opacity-50"
|
||||||
type="search"
|
type="search"
|
||||||
bind:value={qry_str}
|
bind:value={qry_str}
|
||||||
placeholder="Search username or email..."
|
placeholder="Search username or email..."
|
||||||
onkeydown={(e) => e.key === 'Enter' && load_users()}
|
onkeydown={(e) => e.key === 'Enter' && load_users()}
|
||||||
/>
|
/>
|
||||||
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_users} disabled={loading}>
|
<button class="variant-filled-primary font-bold px-10 py-3 hover:brightness-110 transition-all border-l border-surface-500/20 flex items-center justify-center min-w-[100px]" onclick={load_users} disabled={loading}>
|
||||||
{#if loading}
|
{#if loading}
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{#each user_li as user}
|
{#each user_li as user (user.user_id_random)}
|
||||||
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group">
|
<div class="card p-5 space-y-4 variant-soft-surface shadow-md border border-surface-500/10 hover:border-primary-500/30 transition-all group">
|
||||||
<header class="flex justify-between items-start">
|
<header class="flex justify-between items-start">
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
@@ -174,7 +174,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<div class="flex items-center gap-2 text-xs opacity-70 bg-black/5 p-2 rounded-lg">
|
<div class="flex items-center gap-2 text-xs opacity-70 bg-black/5 p-2 rounded-lg">
|
||||||
<Mail size={14} class="text-primary-500" />
|
<Mail size={14} class="text-primary-500" />
|
||||||
|
|||||||
@@ -56,11 +56,11 @@
|
|||||||
let lq__event_file_obj_li = $derived(
|
let lq__event_file_obj_li = $derived(
|
||||||
liveQuery(async () => {
|
liveQuery(async () => {
|
||||||
if (!slct__event_session_id) return [];
|
if (!slct__event_session_id) return [];
|
||||||
|
|
||||||
if (log_lvl > 1) {
|
if (log_lvl > 1) {
|
||||||
console.log(`[LQ] Fetching files for session: ${slct__event_session_id}`);
|
console.log(`[LQ] Fetching files for session: ${slct__event_session_id}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await db_events.file
|
return await db_events.file
|
||||||
.where('for_id')
|
.where('for_id')
|
||||||
.equals(slct__event_session_id)
|
.equals(slct__event_session_id)
|
||||||
@@ -283,7 +283,7 @@
|
|||||||
{/if} -->
|
{/if} -->
|
||||||
</div>
|
</div>
|
||||||
<ul class="space-y-1">
|
<ul class="space-y-1">
|
||||||
{#each $lq__event_file_obj_li as event_file_obj, index}
|
{#each $lq__event_file_obj_li as event_file_obj (event_file_obj.event_file_id)}
|
||||||
<li
|
<li
|
||||||
class="flex flex-row flex-wrap gap-1 items-center justify-center"
|
class="flex flex-row flex-wrap gap-1 items-center justify-center"
|
||||||
class:hidden={!$events_loc.launcher
|
class:hidden={!$events_loc.launcher
|
||||||
@@ -357,7 +357,7 @@
|
|||||||
|
|
||||||
<!-- Maybe set max with? max-w-(--breakpoint-md) -->
|
<!-- Maybe set max with? max-w-(--breakpoint-md) -->
|
||||||
<ul class="event_presentation_list max-w-full space-y-2">
|
<ul class="event_presentation_list max-w-full space-y-2">
|
||||||
{#each $lq__event_presentation_obj_li as event_presentation_obj}
|
{#each $lq__event_presentation_obj_li as event_presentation_obj (event_presentation_obj.event_presentation_id)}
|
||||||
<li
|
<li
|
||||||
class="border-b-2 border-gray-300 my-1 py-1 text-center md:text-left"
|
class="border-b-2 border-gray-300 my-1 py-1 text-center md:text-left"
|
||||||
>
|
>
|
||||||
@@ -384,7 +384,7 @@
|
|||||||
|
|
||||||
<!-- Yes, this is kind of inefficient, but it works for now. -->
|
<!-- Yes, this is kind of inefficient, but it works for now. -->
|
||||||
{#if $lq__event_presenter_obj_li && type_code == 'poster'}
|
{#if $lq__event_presenter_obj_li && type_code == 'poster'}
|
||||||
{#each $lq__event_presenter_obj_li as event_presenter_obj, index}
|
{#each $lq__event_presenter_obj_li as event_presenter_obj, index (event_presenter_obj.event_presenter_id)}
|
||||||
{#if event_presenter_obj.event_presentation_id == event_presentation_obj.event_presentation_id}
|
{#if event_presenter_obj.event_presentation_id == event_presentation_obj.event_presentation_id}
|
||||||
<span
|
<span
|
||||||
class="event_presentation_single_presenter italic text-sm text-gray-500"
|
class="event_presentation_single_presenter italic text-sm text-gray-500"
|
||||||
@@ -427,7 +427,7 @@
|
|||||||
|
|
||||||
{#if $lq__event_presenter_obj_li && $lq__event_presenter_obj_li.length}
|
{#if $lq__event_presenter_obj_li && $lq__event_presenter_obj_li.length}
|
||||||
<ul class="event_presentation_presenter_list">
|
<ul class="event_presentation_presenter_list">
|
||||||
{#each $lq__event_presenter_obj_li as event_presenter_obj, index}
|
{#each $lq__event_presenter_obj_li as event_presenter_obj (event_presenter_obj.event_presenter_id)}
|
||||||
{#if event_presenter_obj.event_presentation_id == event_presentation_obj.event_presentation_id}
|
{#if event_presenter_obj.event_presentation_id == event_presentation_obj.event_presentation_id}
|
||||||
<li
|
<li
|
||||||
class="
|
class="
|
||||||
|
|||||||
@@ -6,17 +6,17 @@
|
|||||||
import { get_object } from '$lib/ae_api/api_get_object';
|
import { get_object } from '$lib/ae_api/api_get_object';
|
||||||
import { post_object } from '$lib/ae_api/api_post_object';
|
import { post_object } from '$lib/ae_api/api_post_object';
|
||||||
import { patch_object } from '$lib/ae_api/api_patch_object';
|
import { patch_object } from '$lib/ae_api/api_patch_object';
|
||||||
import {
|
import {
|
||||||
Database,
|
Database,
|
||||||
Server,
|
Server,
|
||||||
User,
|
User,
|
||||||
Users,
|
Users,
|
||||||
UserCheck,
|
UserCheck,
|
||||||
Building2,
|
Building2,
|
||||||
MapPin,
|
MapPin,
|
||||||
Contact,
|
Contact,
|
||||||
ShieldCheck,
|
ShieldCheck,
|
||||||
Globe,
|
Globe,
|
||||||
RefreshCcw,
|
RefreshCcw,
|
||||||
Trash2,
|
Trash2,
|
||||||
Bug,
|
Bug,
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
test_result = 'loading...';
|
test_result = 'loading...';
|
||||||
const endpoint = '/v3/crud/journal/';
|
const endpoint = '/v3/crud/journal/';
|
||||||
const params: Record<string, any> = { limit: 1 };
|
const params: Record<string, any> = { limit: 1 };
|
||||||
|
|
||||||
const custom_headers: Record<string, string> = {};
|
const custom_headers: Record<string, string> = {};
|
||||||
const active_key = trace_use_agent_key ? trace_agent_key : $ae_api.api_secret_key;
|
const active_key = trace_use_agent_key ? trace_agent_key : $ae_api.api_secret_key;
|
||||||
custom_headers['x-aether-api-key'] = active_key;
|
custom_headers['x-aether-api-key'] = active_key;
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
try {
|
try {
|
||||||
const url = new URL(endpoint, $ae_api.base_url);
|
const url = new URL(endpoint, $ae_api.base_url);
|
||||||
Object.keys(params).forEach(k => url.searchParams.append(k, String(params[k])));
|
Object.keys(params).forEach(k => url.searchParams.append(k, String(params[k])));
|
||||||
|
|
||||||
const response = await fetch(url.toString(), {
|
const response = await fetch(url.toString(), {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: custom_headers
|
headers: custom_headers
|
||||||
@@ -152,11 +152,11 @@
|
|||||||
|
|
||||||
const test_whoami = () => run_test('Who Am I? (JWT Test)', async () => {
|
const test_whoami = () => run_test('Who Am I? (JWT Test)', async () => {
|
||||||
if (!$ae_loc.user_id) throw new Error('No user_id found in session.');
|
if (!$ae_loc.user_id) throw new Error('No user_id found in session.');
|
||||||
return await load_ae_obj_id__user({
|
return await load_ae_obj_id__user({
|
||||||
api_cfg: $ae_api,
|
api_cfg: $ae_api,
|
||||||
user_id: $ae_loc.user_id,
|
user_id: $ae_loc.user_id,
|
||||||
try_cache: false,
|
try_cache: false,
|
||||||
log_lvl: 1
|
log_lvl: 1
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -183,74 +183,74 @@
|
|||||||
// Capture current state at test time
|
// Capture current state at test time
|
||||||
const current_ae_api = $ae_api;
|
const current_ae_api = $ae_api;
|
||||||
const current_ae_loc = $ae_loc;
|
const current_ae_loc = $ae_loc;
|
||||||
|
|
||||||
const endpoint = `/v3/crud/account/${current_ae_loc.account_id || 'ghost'}`;
|
const endpoint = `/v3/crud/account/${current_ae_loc.account_id || 'ghost'}`;
|
||||||
const data = {
|
const data = {
|
||||||
name: current_ae_loc.account_name,
|
name: current_ae_loc.account_name,
|
||||||
_non_existent_field: 'This should be ignored by the API'
|
_non_existent_field: 'This should be ignored by the API'
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('Permissive Mode: Starting PATCH test...', { endpoint, headers: current_ae_api.headers });
|
console.log('Permissive Mode: Starting PATCH test...', { endpoint, headers: current_ae_api.headers });
|
||||||
|
|
||||||
const result = await patch_object({
|
const result = await patch_object({
|
||||||
api_cfg: current_ae_api,
|
api_cfg: current_ae_api,
|
||||||
endpoint,
|
endpoint,
|
||||||
data,
|
data,
|
||||||
log_lvl: 1
|
log_lvl: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!result) throw new Error('API returned false. Check console for 401/403/500 errors.');
|
if (!result) throw new Error('API returned false. Check console for 401/403/500 errors.');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message: 'SUCCESS: API accepted request with unknown field (Permissive Mode Active)',
|
message: 'SUCCESS: API accepted request with unknown field (Permissive Mode Active)',
|
||||||
account_id: result.account_id,
|
account_id: result.account_id,
|
||||||
id_vision: typeof result.account_id === 'string' ? 'V3 (String)' : 'LEGACY (Integer)',
|
id_vision: typeof result.account_id === 'string' ? 'V3 (String)' : 'LEGACY (Integer)',
|
||||||
returned_data: result
|
returned_data: result
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const test_structured_error = () => run_test('Structured Error Validation (Deliberate 400)', async () => {
|
const test_structured_error = () => run_test('Structured Error Validation (Deliberate 400)', async () => {
|
||||||
const current_ae_api = $ae_api;
|
const current_ae_api = $ae_api;
|
||||||
|
|
||||||
// Use the exact Recovery Meetings search pattern to verify why it's throwing 403
|
// Use the exact Recovery Meetings search pattern to verify why it's throwing 403
|
||||||
const endpoint = `/v3/crud/event/search`;
|
const endpoint = `/v3/crud/event/search`;
|
||||||
const search_query = {
|
const search_query = {
|
||||||
and: [
|
and: [
|
||||||
{ field: "conference", op: "eq", value: 0 },
|
{ field: "conference", op: "eq", value: 0 },
|
||||||
{ field: "trigger_schema_violation_400", op: "eq", value: "fail" }
|
{ field: "trigger_schema_violation_400", op: "eq", value: "fail" }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('Structured Error: Starting deliberate 400 test with Recovery filters...', { endpoint });
|
console.log('Structured Error: Starting deliberate 400 test with Recovery filters...', { endpoint });
|
||||||
|
|
||||||
const result = await post_object({
|
const result = await post_object({
|
||||||
api_cfg: current_ae_api,
|
api_cfg: current_ae_api,
|
||||||
endpoint,
|
endpoint,
|
||||||
data: search_query,
|
data: search_query,
|
||||||
log_lvl: 1
|
log_lvl: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
// In Structured Error Mode, the helper returns the JSON object if it contains meta.details
|
// In Structured Error Mode, the helper returns the JSON object if it contains meta.details
|
||||||
if (result?.meta?.details) {
|
if (result?.meta?.details) {
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: 'PASS: Successfully extracted rich error metadata',
|
message: 'PASS: Successfully extracted rich error metadata',
|
||||||
source: result.meta.details.category === 'validation' ? 'FastAPI Detail (Wrapped)' : 'V3 Meta Envelope',
|
source: result.meta.details.category === 'validation' ? 'FastAPI Detail (Wrapped)' : 'V3 Meta Envelope',
|
||||||
details: result.meta.details
|
details: result.meta.details
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: 'FAIL: API returned an error but the helper could not extract metadata.',
|
message: 'FAIL: API returned an error but the helper could not extract metadata.',
|
||||||
raw_result: result
|
raw_result: result
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Environment Diagnostics
|
// Environment Diagnostics
|
||||||
let is_native = $derived(typeof window !== 'undefined' && !!(window as any).native_app);
|
let is_native = $derived(typeof window !== 'undefined' && !!(window as any).native_app);
|
||||||
let app_mode = $derived($events_loc?.launcher?.app_mode || 'web');
|
let app_mode = $derived($events_loc?.launcher?.app_mode || 'web');
|
||||||
|
|
||||||
// Derived state for Header Inspection - dynamically reconstruct standard request headers
|
// Derived state for Header Inspection - dynamically reconstruct standard request headers
|
||||||
let active_headers = $derived({
|
let active_headers = $derived({
|
||||||
...($ae_api.headers || {}),
|
...($ae_api.headers || {}),
|
||||||
@@ -291,7 +291,7 @@
|
|||||||
|
|
||||||
<div class="grid grid-cols-1 xl:grid-cols-[1fr_400px] gap-8">
|
<div class="grid grid-cols-1 xl:grid-cols-[1fr_400px] gap-8">
|
||||||
<main class="space-y-6">
|
<main class="space-y-6">
|
||||||
|
|
||||||
<!-- Environment & Bridge Card -->
|
<!-- Environment & Bridge Card -->
|
||||||
<div class="card p-6 variant-soft-tertiary space-y-4 border border-gray-500 shadow-lg">
|
<div class="card p-6 variant-soft-tertiary space-y-4 border border-gray-500 shadow-lg">
|
||||||
<header class="flex justify-between items-center border-b border-gray-500 pb-3">
|
<header class="flex justify-between items-center border-b border-gray-500 pb-3">
|
||||||
@@ -332,7 +332,7 @@
|
|||||||
<span class="text-[10px] font-mono opacity-50 uppercase tracking-tighter">Real-time API Store View</span>
|
<span class="text-[10px] font-mono opacity-50 uppercase tracking-tighter">Real-time API Store View</span>
|
||||||
</header>
|
</header>
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
{#each Object.entries(active_headers) as [key, value]}
|
{#each Object.entries(active_headers) as [key, value] (key)}
|
||||||
<div class="flex justify-between items-center p-3 bg-gray-500/10 rounded border border-gray-500/20">
|
<div class="flex justify-between items-center p-3 bg-gray-500/10 rounded border border-gray-500/20">
|
||||||
<span class="text-[10px] font-mono font-bold opacity-70">{key}</span>
|
<span class="text-[10px] font-mono font-bold opacity-70">{key}</span>
|
||||||
<span class="text-xs font-mono {key === 'x-ae-ignore-extra-fields' ? 'text-success-500 font-bold' : ''}">
|
<span class="text-xs font-mono {key === 'x-ae-ignore-extra-fields' ? 'text-success-500 font-bold' : ''}">
|
||||||
@@ -426,10 +426,10 @@
|
|||||||
Sync Status <span class="text-secondary-500"><Info size={10} /></span>
|
Sync Status <span class="text-secondary-500"><Info size={10} /></span>
|
||||||
</span>
|
</span>
|
||||||
<div class="card p-2 text-center text-xs font-bold border border-gray-500 shadow-sm flex items-center justify-center h-[46px] bg-transparent">
|
<div class="card p-2 text-center text-xs font-bold border border-gray-500 shadow-sm flex items-center justify-center h-[46px] bg-transparent">
|
||||||
{#if $ae_api.jwt === $ae_loc.jwt}
|
{#if $ae_api.jwt === $ae_loc.jwt}
|
||||||
<span class="text-success-600 dark:text-success-400 flex items-center gap-1"><ShieldCheck size={14}/> HANDSHAKE OK</span>
|
<span class="text-success-600 dark:text-success-400 flex items-center gap-1"><ShieldCheck size={14}/> HANDSHAKE OK</span>
|
||||||
{:else}
|
{:else}
|
||||||
<span class="text-error-600 dark:text-error-400 flex items-center gap-1"><ShieldAlert size={14}/> MISMATCH</span>
|
<span class="text-error-600 dark:text-error-400 flex items-center gap-1"><ShieldAlert size={14}/> MISMATCH</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
@@ -468,7 +468,7 @@
|
|||||||
<span class="text-secondary-600 font-bold underline decoration-dotted">Use Agent Key</span>
|
<span class="text-secondary-600 font-bold underline decoration-dotted">Use Agent Key</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-6 pt-3 border-t border-gray-500 mt-2" title="Section 6: JWT can be sent via Header (standard) or URL Parameter (for direct links/downloads).">
|
<div class="flex flex-wrap gap-6 pt-3 border-t border-gray-500 mt-2" title="Section 6: JWT can be sent via Header (standard) or URL Parameter (for direct links/downloads).">
|
||||||
<span class="text-[10px] uppercase font-bold opacity-50 flex items-center gap-1">JWT Method <span class="text-secondary-500"><Info size={10} /></span>:</span>
|
<span class="text-[10px] uppercase font-bold opacity-50 flex items-center gap-1">JWT Method <span class="text-secondary-500"><Info size={10} /></span>:</span>
|
||||||
<label class="flex items-center gap-3 cursor-pointer">
|
<label class="flex items-center gap-3 cursor-pointer">
|
||||||
@@ -481,7 +481,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<button class="btn variant-filled-secondary p-4 font-bold shadow-lg transition-all hover:brightness-110 active:scale-95 flex items-center justify-center gap-2" onclick={run_trace_test} title="Initiate GET request to /v3/crud/journal/ and capture headers.">
|
<button class="btn variant-filled-secondary p-4 font-bold shadow-lg transition-all hover:brightness-110 active:scale-95 flex items-center justify-center gap-2" onclick={run_trace_test} title="Initiate GET request to /v3/crud/journal/ and capture headers.">
|
||||||
<ArrowRightLeft size={16} /> RUN TRACE
|
<ArrowRightLeft size={16} /> RUN TRACE
|
||||||
@@ -511,8 +511,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<p class="font-bold opacity-70 tracking-widest uppercase">📥 Received</p>
|
<p class="font-bold opacity-70 tracking-widest uppercase">📥 Received</p>
|
||||||
<div class="bg-black/20 p-4 rounded shadow-inner border border-black/10 overflow-auto max-h-[400px] border-l-4"
|
<div class="bg-black/20 p-4 rounded shadow-inner border border-black/10 overflow-auto max-h-[400px] border-l-4"
|
||||||
class:border-l-success-500={test_result?.success}
|
class:border-l-success-500={test_result?.success}
|
||||||
class:border-l-error-500={!test_result?.success}>
|
class:border-l-error-500={!test_result?.success}>
|
||||||
<pre>{JSON.stringify(trace_details.response || trace_details.response_error, null, 2)}</pre>
|
<pre>{JSON.stringify(trace_details.response || trace_details.response_error, null, 2)}</pre>
|
||||||
</div>
|
</div>
|
||||||
@@ -579,12 +579,12 @@
|
|||||||
{:else} <span class="badge variant-soft-surface opacity-50 italic uppercase">Idle</span> {/if}
|
{:else} <span class="badge variant-soft-surface opacity-50 italic uppercase">Idle</span> {/if}
|
||||||
</header>
|
</header>
|
||||||
<div class="flex-1 overflow-auto bg-black/20 rounded p-4 font-mono text-xs shadow-inner border border-black/10">
|
<div class="flex-1 overflow-auto bg-black/20 rounded p-4 font-mono text-xs shadow-inner border border-black/10">
|
||||||
{#if test_result === 'loading...'}
|
{#if test_result === 'loading...'}
|
||||||
<div class="flex flex-col items-center justify-center h-full gap-4 opacity-30"><RefreshCcw size={32} class="animate-spin"/><p class="italic uppercase">Auditing...</p></div>
|
<div class="flex flex-col items-center justify-center h-full gap-4 opacity-30"><RefreshCcw size={32} class="animate-spin"/><p class="italic uppercase">Auditing...</p></div>
|
||||||
{:else if test_result}
|
{:else if test_result}
|
||||||
<pre class="whitespace-pre-wrap leading-relaxed text-blue-600 dark:text-blue-400">{JSON.stringify(test_result, null, 2)}</pre>
|
<pre class="whitespace-pre-wrap leading-relaxed text-blue-600 dark:text-blue-400">{JSON.stringify(test_result, null, 2)}</pre>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="flex flex-col items-center justify-center h-full opacity-20 py-20 text-center"><Zap size={64} class="mb-4" /><p class="font-bold uppercase tracking-widest">Select test to begin</p></div>
|
<div class="flex flex-col items-center justify-center h-full opacity-20 py-20 text-center"><Zap size={64} class="mb-4" /><p class="font-bold uppercase tracking-widest">Select test to begin</p></div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
async function nukeServiceWorkers() {
|
async function nukeServiceWorkers() {
|
||||||
log('Starting Service Worker cleanup...');
|
log('Starting Service Worker cleanup...');
|
||||||
|
|
||||||
if (!('serviceWorker' in navigator)) {
|
if (!('serviceWorker' in navigator)) {
|
||||||
log('Service Workers not supported in this browser.');
|
log('Service Workers not supported in this browser.');
|
||||||
return;
|
return;
|
||||||
@@ -55,14 +55,14 @@
|
|||||||
<div class="p-8 max-w-2xl mx-auto font-mono">
|
<div class="p-8 max-w-2xl mx-auto font-mono">
|
||||||
<h1 class="text-2xl font-bold mb-4 text-red-600">Service Worker Reset Tool</h1>
|
<h1 class="text-2xl font-bold mb-4 text-red-600">Service Worker Reset Tool</h1>
|
||||||
<p class="mb-4">Attempting to unregister all service workers and clear caches to fix the TypeError loop.</p>
|
<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="bg-gray-100 p-4 rounded border border-gray-300 min-h-[200px]">
|
||||||
{#each status as line}
|
{#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 last:border-0 py-1">{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 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
|
||||||
onclick={() => window.location.reload()}
|
onclick={() => window.location.reload()}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -150,7 +150,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
{#each hosted_files as file}
|
{#each hosted_files as file (file.id)}
|
||||||
<div class="card p-4 variant-soft-secondary space-y-4">
|
<div class="card p-4 variant-soft-secondary space-y-4">
|
||||||
<div class="flex justify-between items-start">
|
<div class="flex justify-between items-start">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
Reference in New Issue
Block a user