Last round of prettier: npx prettier --write src/

This commit is contained in:
Scott Idem
2026-03-24 13:27:40 -04:00
parent 23d25bf65a
commit a8f3c29b9f
146 changed files with 13201 additions and 9277 deletions

View File

@@ -1,125 +1,140 @@
<script lang="ts">
/**
* AE_AITools.svelte
* GENERIC Aether AI Toolset (Runes/Svelte 5)
* Extracted logic from Journals module to be system-wide.
*/
import OpenAI from 'openai';
import { Modal } from 'flowbite-svelte';
import {
Bot, BotMessageSquare, Loader, FileText,
Save, FilePenLine, RotateCcw, Settings,
RefreshCcw, Globe, Copy
} from '@lucide/svelte';
import { ae_loc, ae_api } from '$lib/stores/ae_stores';
import AE_Comp_Editor_CodeMirror from '$lib/elements/element_editor_codemirror.svelte';
/**
* AE_AITools.svelte
* GENERIC Aether AI Toolset (Runes/Svelte 5)
* Extracted logic from Journals module to be system-wide.
*/
import OpenAI from 'openai';
import { Modal } from 'flowbite-svelte';
import {
Bot,
BotMessageSquare,
Loader,
FileText,
Save,
FilePenLine,
RotateCcw,
Settings,
RefreshCcw,
Globe,
Copy
} from '@lucide/svelte';
import { ae_loc, ae_api } from '$lib/stores/ae_stores';
import AE_Comp_Editor_CodeMirror from '$lib/elements/element_editor_codemirror.svelte';
interface Props {
// Core Props
content: string; // The text to summarize/analyze
summary: string; // The result (bindable)
// Configuration (Bindable for global settings persistence)
model?: string;
baseUrl?: string;
token?: string;
systemPrompt?: string;
maxTokens?: number;
temperature?: number;
// Callbacks
onSave?: (newSummary: string) => void;
onSyncConfig?: () => void; // Optional: callback to sync from global site config
// UI Customization
buttonClass?: string;
log_lvl?: number;
interface Props {
// Core Props
content: string; // The text to summarize/analyze
summary: string; // The result (bindable)
// Configuration (Bindable for global settings persistence)
model?: string;
baseUrl?: string;
token?: string;
systemPrompt?: string;
maxTokens?: number;
temperature?: number;
// Callbacks
onSave?: (newSummary: string) => void;
onSyncConfig?: () => void; // Optional: callback to sync from global site config
// UI Customization
buttonClass?: string;
log_lvl?: number;
}
let {
content,
summary = $bindable(),
model = $bindable(),
baseUrl = $bindable(),
token = $bindable(),
systemPrompt = $bindable(),
maxTokens = $bindable(),
temperature = $bindable(),
onSave,
onSyncConfig,
buttonClass = 'btn btn-sm preset-tonal-primary shadow-lg hover:scale-105 transition-all',
log_lvl = 0
}: Props = $props();
// Apply defaults if undefined (Safe for Svelte 5 Runes)
if (model === undefined) model = 'dgrzone-deepseek-8b-quick';
if (baseUrl === undefined) baseUrl = 'https://ai.dgrzone.com/api';
if (token === undefined) token = '';
if (systemPrompt === undefined) systemPrompt = 'You are a helpful assistant.';
if (maxTokens === undefined) maxTokens = 512;
if (temperature === undefined) temperature = 0.7;
// Internal State
let ae_promises: any = $state(null);
let show_modal = $state(false);
let active_tab: 'result' | 'settings' = $state('result');
let tmp_summary = $state('');
async function generate_ai_result() {
if (!content) {
alert('No content available to analyze.');
return;
}
let {
content,
summary = $bindable(),
model = $bindable(),
baseUrl = $bindable(),
token = $bindable(),
systemPrompt = $bindable(),
maxTokens = $bindable(),
temperature = $bindable(),
onSave,
onSyncConfig,
buttonClass = "btn btn-sm preset-tonal-primary shadow-lg hover:scale-105 transition-all",
log_lvl = 0
}: Props = $props();
active_tab = 'result';
// Apply defaults if undefined (Safe for Svelte 5 Runes)
if (model === undefined) model = 'dgrzone-deepseek-8b-quick';
if (baseUrl === undefined) baseUrl = 'https://ai.dgrzone.com/api';
if (token === undefined) token = '';
if (systemPrompt === undefined) systemPrompt = 'You are a helpful assistant.';
if (maxTokens === undefined) maxTokens = 512;
if (temperature === undefined) temperature = 0.7;
// Internal State
let ae_promises: any = $state(null);
let show_modal = $state(false);
let active_tab: 'result' | 'settings' = $state('result');
let tmp_summary = $state('');
async function generate_ai_result() {
if (!content) {
alert('No content available to analyze.');
return;
}
active_tab = 'result';
// If no token is provided, trigger a "Demo Mode" placeholder after a fake delay
if (!token || token === '') {
console.log('AE_AITools: No token provided. Entering Demo Mode.');
ae_promises = new Promise((resolve) => {
setTimeout(() => {
tmp_summary = `### AI Summary (DEMO MODE)\n\nThis is a placeholder summary because no API token was provided in the settings. \n\n**Original Content Length:** ${content.length} characters.\n\n**System Prompt:** ${systemPrompt}\n\n**Model:** ${model}`;
show_modal = true;
resolve(true);
}, 1500);
});
return;
}
const ai_client = new OpenAI({
apiKey: token,
baseURL: baseUrl,
dangerouslyAllowBrowser: true
// If no token is provided, trigger a "Demo Mode" placeholder after a fake delay
if (!token || token === '') {
console.log('AE_AITools: No token provided. Entering Demo Mode.');
ae_promises = new Promise((resolve) => {
setTimeout(() => {
tmp_summary = `### AI Summary (DEMO MODE)\n\nThis is a placeholder summary because no API token was provided in the settings. \n\n**Original Content Length:** ${content.length} characters.\n\n**System Prompt:** ${systemPrompt}\n\n**Model:** ${model}`;
show_modal = true;
resolve(true);
}, 1500);
});
return;
}
try {
ae_promises = ai_client.chat.completions.create({
const ai_client = new OpenAI({
apiKey: token,
baseURL: baseUrl,
dangerouslyAllowBrowser: true
});
try {
ae_promises = ai_client.chat.completions
.create({
model: model || 'dgrzone-deepseek-8b-quick',
max_tokens: maxTokens,
temperature: temperature,
messages: [
{ role: 'system', content: systemPrompt || 'You are a helpful assistant.' },
{
role: 'system',
content: systemPrompt || 'You are a helpful assistant.'
},
{ role: 'user', content: content }
]
}).then((resp) => {
const result = resp?.choices?.[0]?.message?.content || 'No result generated.';
})
.then((resp) => {
const result =
resp?.choices?.[0]?.message?.content ||
'No result generated.';
tmp_summary = result;
show_modal = true;
});
} catch (err: any) {
console.error('AE_AITools: AI Error:', err);
// Even on error, show the modal with the error message so the UI can be inspected
tmp_summary = `### AI Error\n\nFailed to connect to the AI service.\n\n**Error:** ${err.message}\n\nCheck your Settings tab for Base URL and Token configuration.`;
show_modal = true;
ae_promises = Promise.resolve();
}
} catch (err: any) {
console.error('AE_AITools: AI Error:', err);
// Even on error, show the modal with the error message so the UI can be inspected
tmp_summary = `### AI Error\n\nFailed to connect to the AI service.\n\n**Error:** ${err.message}\n\nCheck your Settings tab for Base URL and Token configuration.`;
show_modal = true;
ae_promises = Promise.resolve();
}
}
function handle_save() {
summary = tmp_summary;
if (onSave) onSave(tmp_summary);
show_modal = false;
}
function handle_save() {
summary = tmp_summary;
if (onSave) onSave(tmp_summary);
show_modal = false;
}
</script>
<div class="ae-ai-tools-wrapper inline-flex items-center gap-1">
@@ -128,13 +143,12 @@
type="button"
onclick={generate_ai_result}
class={buttonClass}
title="Generate AI summary/analysis"
>
title="Generate AI summary/analysis">
{#await ae_promises}
<Loader class="inline-block mr-1 animate-spin" size="1.2em" />
<Loader class="mr-1 inline-block animate-spin" size="1.2em" />
<span class="text-sm">Processing...</span>
{:then}
<BotMessageSquare class="inline-block mr-1" size="1.2em" />
<BotMessageSquare class="mr-1 inline-block" size="1.2em" />
<span class="text-sm">Summarize</span>
{:catch}
<span class="text-sm text-red-500">Error</span>
@@ -149,8 +163,7 @@
show_modal = true;
}}
class="btn btn-sm variant-soft-surface shadow-md"
title="AI Settings"
>
title="AI Settings">
<Settings size="1.2em" />
</button>
@@ -160,32 +173,37 @@
title="Aether AI Assistant"
bind:open={show_modal}
size="lg"
class="bg-white dark:bg-gray-800"
>
class="bg-white dark:bg-gray-800">
<div class="space-y-4 p-2">
<!-- Tab Navigation -->
<div class="flex gap-1 border-b border-surface-500/20 pb-2">
<button
class="btn btn-sm {active_tab === 'result' ? 'variant-filled-primary' : 'variant-soft-surface'}"
onclick={() => active_tab = 'result'}
>
<div class="border-surface-500/20 flex gap-1 border-b pb-2">
<button
class="btn btn-sm {active_tab === 'result'
? 'variant-filled-primary'
: 'variant-soft-surface'}"
onclick={() => (active_tab = 'result')}>
<Bot size="1.1em" class="mr-1" /> Result
</button>
<button
class="btn btn-sm {active_tab === 'settings' ? 'variant-filled-secondary' : 'variant-soft-surface'}"
onclick={() => active_tab = 'settings'}
>
<button
class="btn btn-sm {active_tab === 'settings'
? 'variant-filled-secondary'
: 'variant-soft-surface'}"
onclick={() => (active_tab = 'settings')}>
<Settings size="1.1em" class="mr-1" /> Settings
</button>
</div>
{#if active_tab === 'result'}
<div class="space-y-4 animate-in fade-in duration-200">
<div class="flex gap-2 justify-start">
<button class="btn btn-sm variant-filled-success" onclick={handle_save}>
<div class="animate-in fade-in space-y-4 duration-200">
<div class="flex justify-start gap-2">
<button
class="btn btn-sm variant-filled-success"
onclick={handle_save}>
<Save size="1.1em" class="mr-1" /> Save Result
</button>
<button class="btn btn-sm variant-ghost-primary" onclick={generate_ai_result}>
<button
class="btn btn-sm variant-ghost-primary"
onclick={generate_ai_result}>
<RotateCcw size="1.1em" class="mr-1" /> Re-run
</button>
</div>
@@ -195,57 +213,84 @@
bind:new_content={tmp_summary}
theme_mode={$ae_loc.theme_mode}
placeholder="AI Result will appear here..."
class_li="p-2 border rounded-lg h-96 shadow-inner bg-surface-500/5"
/>
class_li="p-2 border rounded-lg h-96 shadow-inner bg-surface-500/5" />
</div>
{:else}
<div class="space-y-6 animate-in slide-in-from-left-4 duration-200">
<div
class="animate-in slide-in-from-left-4 space-y-6 duration-200">
<!-- Connection Settings -->
<div class="space-y-4">
<h3 class="text-sm font-bold uppercase tracking-widest text-surface-500 flex items-center gap-2">
<h3
class="text-surface-500 flex items-center gap-2 text-sm font-bold tracking-widest uppercase">
<Globe size="1.1em" /> API Connection
</h3>
{#if onSyncConfig}
<button class="btn btn-sm variant-soft-primary" onclick={onSyncConfig}>
<Copy size="1.1em" class="mr-1" /> Sync Global Defaults
<button
class="btn btn-sm variant-soft-primary"
onclick={onSyncConfig}>
<Copy size="1.1em" class="mr-1" /> Sync Global
Defaults
</button>
{/if}
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
<label class="label">
<span>Base URL</span>
<input type="text" bind:value={baseUrl} class="input input-sm" />
<input
type="text"
bind:value={baseUrl}
class="input input-sm" />
</label>
<label class="label">
<span>Model</span>
<input type="text" bind:value={model} class="input input-sm" />
<input
type="text"
bind:value={model}
class="input input-sm" />
</label>
</div>
<label class="label">
<span>API Token</span>
<input type="password" bind:value={token} class="input input-sm font-mono" />
<input
type="password"
bind:value={token}
class="input input-sm font-mono" />
</label>
</div>
<!-- Model Parameters -->
<div class="space-y-4 pt-4 border-t border-surface-500/10">
<h3 class="text-sm font-bold uppercase tracking-widest text-surface-500 flex items-center gap-2">
<div
class="border-surface-500/10 space-y-4 border-t pt-4">
<h3
class="text-surface-500 flex items-center gap-2 text-sm font-bold tracking-widest uppercase">
<FilePenLine size="1.1em" /> Inference Parameters
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
<label class="label">
<span>Temperature ({temperature})</span>
<input type="range" bind:value={temperature} min="0" max="1" step="0.1" class="range" />
<input
type="range"
bind:value={temperature}
min="0"
max="1"
step="0.1"
class="range" />
</label>
<label class="label">
<span>Max Tokens</span>
<input type="number" bind:value={maxTokens} class="input input-sm" />
<input
type="number"
bind:value={maxTokens}
class="input input-sm" />
</label>
</div>
<label class="label">
<span>System Prompt</span>
<textarea bind:value={systemPrompt} class="textarea h-24 text-xs font-mono"></textarea>
<textarea
bind:value={systemPrompt}
class="textarea h-24 font-mono text-xs"
></textarea>
</label>
</div>
</div>
@@ -253,4 +298,4 @@
</div>
</Modal>
{/if}
</div>
</div>

View File

@@ -1,58 +1,64 @@
<script lang="ts">
/**
* AE_ObjectFlags.svelte
* GENERIC Aether Object Flags & Visibility Toggles
* Manages: alert, private, public, personal, professional, template
*/
import {
Siren, MessageSquareWarning, Fingerprint,
Globe, BookHeart, BriefcaseBusiness, NotepadTextDashed,
Settings
} from '@lucide/svelte';
import { ae_loc } from '$lib/stores/ae_stores';
/**
* AE_ObjectFlags.svelte
* GENERIC Aether Object Flags & Visibility Toggles
* Manages: alert, private, public, personal, professional, template
*/
import {
Siren,
MessageSquareWarning,
Fingerprint,
Globe,
BookHeart,
BriefcaseBusiness,
NotepadTextDashed,
Settings
} from '@lucide/svelte';
import { ae_loc } from '$lib/stores/ae_stores';
interface Props {
// The object containing the flags (bindable)
obj: any;
interface Props {
// The object containing the flags (bindable)
obj: any;
// Visibility configuration (optional overrides)
show_labels?: boolean;
hide_alert?: boolean;
hide_private?: boolean;
hide_public?: boolean;
hide_personal?: boolean;
hide_professional?: boolean;
hide_template?: boolean;
// Visibility configuration (optional overrides)
show_labels?: boolean;
hide_alert?: boolean;
hide_private?: boolean;
hide_public?: boolean;
hide_personal?: boolean;
hide_professional?: boolean;
hide_template?: boolean;
// Callbacks
on_toggle?: (prop: string, newValue: boolean) => void;
// Callbacks
on_toggle?: (prop: string, newValue: boolean) => void;
// Styling
container_class?: string;
}
// Styling
container_class?: string;
}
let {
obj = $bindable(),
show_labels = true,
hide_alert: hide_alert = false,
hide_private: hide_private = false,
hide_public: hide_public = false,
hide_personal: hide_personal = false,
hide_professional: hide_professional = false,
hide_template: hide_template = false,
on_toggle: onToggle,
container_class = "flex flex-row flex-wrap gap-1 items-center justify-evenly py-2 border-y border-surface-500/10"
}: Props = $props();
let {
obj = $bindable(),
show_labels = true,
hide_alert: hide_alert = false,
hide_private: hide_private = false,
hide_public: hide_public = false,
hide_personal: hide_personal = false,
hide_professional: hide_professional = false,
hide_template: hide_template = false,
on_toggle: onToggle,
container_class = 'flex flex-row flex-wrap gap-1 items-center justify-evenly py-2 border-y border-surface-500/10'
}: Props = $props();
function handle_toggle(prop: string) {
obj[prop] = !obj[prop];
if (onToggle) onToggle(prop, obj[prop]);
}
function handle_toggle(prop: string) {
obj[prop] = !obj[prop];
if (onToggle) onToggle(prop, obj[prop]);
}
</script>
<div class={container_class}>
{#if show_labels}
<span class="text-xs text-surface-500 flex items-center gap-1 uppercase font-bold tracking-wider mr-2">
<span
class="text-surface-500 mr-2 flex items-center gap-1 text-xs font-bold tracking-wider uppercase">
<Settings size="1.1em" /> Flags:
</span>
{/if}
@@ -63,9 +69,10 @@
type="button"
onclick={() => handle_toggle('alert')}
class="btn-icon btn-icon-sm preset-tonal-secondary hover:preset-filled-secondary-500 transition"
title="Toggle Alert Status"
>
<Siren size="1.2em" class={obj?.alert ? 'text-error-500' : 'opacity-40'} />
title="Toggle Alert Status">
<Siren
size="1.2em"
class={obj?.alert ? 'text-error-500' : 'opacity-40'} />
</button>
{/if}
@@ -75,9 +82,10 @@
type="button"
onclick={() => handle_toggle('private')}
class="btn-icon btn-icon-sm preset-tonal-secondary hover:preset-filled-secondary-500 transition"
title="Toggle Private/Encrypted"
>
<Fingerprint size="1.2em" class={obj?.private ? 'text-success-500' : 'opacity-40'} />
title="Toggle Private/Encrypted">
<Fingerprint
size="1.2em"
class={obj?.private ? 'text-success-500' : 'opacity-40'} />
</button>
{/if}
@@ -87,9 +95,10 @@
type="button"
onclick={() => handle_toggle('public')}
class="btn-icon btn-icon-sm preset-tonal-secondary hover:preset-filled-secondary-500 transition"
title="Toggle Public Visibility"
>
<Globe size="1.2em" class={obj?.public ? 'text-success-500' : 'opacity-40'} />
title="Toggle Public Visibility">
<Globe
size="1.2em"
class={obj?.public ? 'text-success-500' : 'opacity-40'} />
</button>
{/if}
@@ -99,9 +108,10 @@
type="button"
onclick={() => handle_toggle('personal')}
class="btn-icon btn-icon-sm preset-tonal-secondary hover:preset-filled-secondary-500 transition"
title="Toggle Personal Scope"
>
<BookHeart size="1.2em" class={obj?.personal ? 'text-success-500' : 'opacity-40'} />
title="Toggle Personal Scope">
<BookHeart
size="1.2em"
class={obj?.personal ? 'text-success-500' : 'opacity-40'} />
</button>
{/if}
@@ -111,9 +121,10 @@
type="button"
onclick={() => handle_toggle('professional')}
class="btn-icon btn-icon-sm preset-tonal-secondary hover:preset-filled-secondary-500 transition"
title="Toggle Professional Scope"
>
<BriefcaseBusiness size="1.2em" class={obj?.professional ? 'text-success-500' : 'opacity-40'} />
title="Toggle Professional Scope">
<BriefcaseBusiness
size="1.2em"
class={obj?.professional ? 'text-success-500' : 'opacity-40'} />
</button>
{/if}
@@ -123,9 +134,10 @@
type="button"
onclick={() => handle_toggle('template')}
class="btn-icon btn-icon-sm preset-tonal-secondary hover:preset-filled-secondary-500 transition"
title="Toggle Template Mode"
>
<NotepadTextDashed size="1.2em" class={obj?.template ? 'text-success-500' : 'opacity-40'} />
title="Toggle Template Mode">
<NotepadTextDashed
size="1.2em"
class={obj?.template ? 'text-success-500' : 'opacity-40'} />
</button>
{/if}
</div>

View File

@@ -1,95 +1,96 @@
<script lang="ts">
/**
* AE_Record_Controls.svelte
* GENERIC Aether Record Management Controls
* Manages: priority, hide, enable, alert, delete/disable
*
* Emits events — NO API calls. Parent is responsible for:
* 1. Calling the API (update_ae_obj, delete_ae_obj_id__*)
* 2. Refreshing the object from cache/API
* 3. Navigating away on delete
*
* Usage:
* <AE_Record_Controls
* obj={$lq__event_session_obj}
* obj_label="session"
* allow_delete={$ae_loc.manager_access}
* allow_disable={$ae_loc.administrator_access}
* on_toggle={(field, val) => { ... }}
* on_delete={(method) => { ... }}
* />
*/
import {
Star,
Eye,
EyeOff,
ToggleLeft,
ToggleRight,
Bell,
BellOff,
Trash2,
CircleMinus,
Settings
} from '@lucide/svelte';
/**
* AE_Record_Controls.svelte
* GENERIC Aether Record Management Controls
* Manages: priority, hide, enable, alert, delete/disable
*
* Emits events — NO API calls. Parent is responsible for:
* 1. Calling the API (update_ae_obj, delete_ae_obj_id__*)
* 2. Refreshing the object from cache/API
* 3. Navigating away on delete
*
* Usage:
* <AE_Record_Controls
* obj={$lq__event_session_obj}
* obj_label="session"
* allow_delete={$ae_loc.manager_access}
* allow_disable={$ae_loc.administrator_access}
* on_toggle={(field, val) => { ... }}
* on_delete={(method) => { ... }}
* />
*/
import {
Star,
Eye,
EyeOff,
ToggleLeft,
ToggleRight,
Bell,
BellOff,
Trash2,
CircleMinus,
Settings
} from '@lucide/svelte';
interface Props {
// The object whose flags are being displayed (read-only — parent owns state)
obj: any;
interface Props {
// The object whose flags are being displayed (read-only — parent owns state)
obj: any;
// Human-readable label for confirm dialogs ("session", "presenter", "location", etc.)
obj_label?: string;
// Human-readable label for confirm dialogs ("session", "presenter", "location", etc.)
obj_label?: string;
// Visibility — hide any control that doesn't apply for this object type
show_alert?: boolean;
show_priority?: boolean;
show_enable?: boolean;
show_hide?: boolean;
show_labels?: boolean;
// Visibility — hide any control that doesn't apply for this object type
show_alert?: boolean;
show_priority?: boolean;
show_enable?: boolean;
show_hide?: boolean;
show_labels?: boolean;
// Permission gates — parent passes booleans derived from $ae_loc
allow_delete?: boolean; // Hard permanent delete (manager+)
allow_disable?: boolean; // Soft disable/remove (administrator+)
// Permission gates — parent passes booleans derived from $ae_loc
allow_delete?: boolean; // Hard permanent delete (manager+)
allow_disable?: boolean; // Soft disable/remove (administrator+)
// Callbacks — parent handles API + refresh + navigation
on_toggle?: (field: string, new_val: boolean) => void;
on_delete?: (method: 'delete' | 'disable') => void;
// Callbacks — parent handles API + refresh + navigation
on_toggle?: (field: string, new_val: boolean) => void;
on_delete?: (method: 'delete' | 'disable') => void;
// Styling
container_class?: string;
}
// Styling
container_class?: string;
}
let {
obj,
obj_label = 'record',
show_alert = true,
show_priority = true,
show_enable = true,
show_hide = true,
show_labels = true,
allow_delete = false,
allow_disable = false,
on_toggle,
on_delete,
container_class = 'flex flex-row flex-wrap gap-1 items-center justify-evenly py-2 border-y border-surface-500/10'
}: Props = $props();
let {
obj,
obj_label = 'record',
show_alert = true,
show_priority = true,
show_enable = true,
show_hide = true,
show_labels = true,
allow_delete = false,
allow_disable = false,
on_toggle,
on_delete,
container_class = 'flex flex-row flex-wrap gap-1 items-center justify-evenly py-2 border-y border-surface-500/10'
}: Props = $props();
function toggle(field: string) {
if (on_toggle) on_toggle(field, !obj?.[field]);
}
function toggle(field: string) {
if (on_toggle) on_toggle(field, !obj?.[field]);
}
function handle_delete(method: 'delete' | 'disable') {
const msg =
method === 'delete'
? `Permanently delete this ${obj_label}? This cannot be undone.`
: `Remove (disable) this ${obj_label}?`;
if (!confirm(msg)) return;
if (on_delete) on_delete(method);
}
function handle_delete(method: 'delete' | 'disable') {
const msg =
method === 'delete'
? `Permanently delete this ${obj_label}? This cannot be undone.`
: `Remove (disable) this ${obj_label}?`;
if (!confirm(msg)) return;
if (on_delete) on_delete(method);
}
</script>
<div class={container_class}>
{#if show_labels}
<span class="text-xs text-surface-500 flex items-center gap-1 uppercase font-bold tracking-wider mr-2">
<span
class="text-surface-500 mr-2 flex items-center gap-1 text-xs font-bold tracking-wider uppercase">
<Settings size="1.1em" /> Controls:
</span>
{/if}
@@ -103,12 +104,10 @@
class:preset-filled-warning-500={obj?.priority}
class:preset-tonal-secondary={!obj?.priority}
class:hover:preset-filled-warning-500={!obj?.priority}
title={obj?.priority ? 'Remove priority flag' : 'Mark as priority'}
>
title={obj?.priority ? 'Remove priority flag' : 'Mark as priority'}>
<Star
size="1.2em"
class={obj?.priority ? 'fill-current' : 'opacity-50'}
/>
class={obj?.priority ? 'fill-current' : 'opacity-50'} />
</button>
{/if}
@@ -121,8 +120,7 @@
class:preset-filled-warning-500={obj?.hide}
class:preset-tonal-secondary={!obj?.hide}
class:hover:preset-filled-warning-500={!obj?.hide}
title={obj?.hide ? 'Unhide this record' : 'Hide this record'}
>
title={obj?.hide ? 'Unhide this record' : 'Hide this record'}>
{#if obj?.hide}
<EyeOff size="1.2em" class="text-warning-500" />
{:else}
@@ -140,8 +138,7 @@
class:preset-filled-success-500={obj?.enable}
class:preset-filled-error-500={!obj?.enable}
class:hover:preset-filled-success-500={!obj?.enable}
title={obj?.enable ? 'Disable this record' : 'Enable this record'}
>
title={obj?.enable ? 'Disable this record' : 'Enable this record'}>
{#if obj?.enable}
<ToggleRight size="1.2em" class="text-success-300" />
{:else}
@@ -159,8 +156,7 @@
class:preset-filled-error-500={obj?.alert}
class:preset-tonal-secondary={!obj?.alert}
class:hover:preset-filled-error-500={!obj?.alert}
title={obj?.alert ? 'Remove alert status' : 'Mark as alert'}
>
title={obj?.alert ? 'Remove alert status' : 'Mark as alert'}>
{#if obj?.alert}
<Bell size="1.2em" class="text-error-300" />
{:else}
@@ -175,8 +171,7 @@
type="button"
onclick={() => handle_delete('delete')}
class="btn-icon btn-icon-sm preset-filled-error-500 hover:preset-filled-error-600 transition"
title="Permanently delete this {obj_label}"
>
title="Permanently delete this {obj_label}">
<Trash2 size="1.2em" />
</button>
{:else if allow_disable}
@@ -184,8 +179,7 @@
type="button"
onclick={() => handle_delete('disable')}
class="btn-icon btn-icon-sm preset-filled-warning-500 hover:preset-filled-warning-600 transition"
title="Disable / soft-remove this {obj_label}"
>
title="Disable / soft-remove this {obj_label}">
<CircleMinus size="1.2em" />
</button>
{/if}