Migrated the ESLint configuration to the new flat config format () and addressed several initial linting errors. Key changes include: - Updated ESLint configuration to treat as warnings instead of errors. - Fixed errors in by declaring and . - Corrected error in by using instead of an out-of-scope . - Resolved error in by replacing the undefined directive with the component. - Addressed errors in by replacing with and with . - Fixed errors in by importing necessary modules (, , ) and adding missing props (, , , , ).
581 lines
17 KiB
Svelte
581 lines
17 KiB
Svelte
<script lang="ts">
|
|
interface Props {
|
|
log_lvl?: number;
|
|
additional_kv?: key_val;
|
|
e_success?: boolean;
|
|
e_class?: string;
|
|
e_title?: string;
|
|
e_text?: string;
|
|
e_class_h1?: string;
|
|
e_class_h2?: string;
|
|
e_class_form_hidden?: string;
|
|
e_class_form_showing?: string;
|
|
btn_text?: string;
|
|
btn_title?: string;
|
|
btn_class?: string;
|
|
show_btn_class?: string;
|
|
hide_icon?: boolean;
|
|
}
|
|
|
|
let {
|
|
log_lvl = 0,
|
|
additional_kv = $bindable({}),
|
|
e_success = $bindable(false),
|
|
e_class = '',
|
|
e_title = 'Technical Help',
|
|
e_text = 'Request technical help for this application.',
|
|
e_class_h1 = $bindable(''),
|
|
e_class_h2 = $bindable(''),
|
|
e_class_form_hidden = $bindable(''),
|
|
e_class_form_showing = $bindable(''),
|
|
btn_text = 'Technical Help',
|
|
btn_title = 'Technical support help',
|
|
btn_class = '',
|
|
show_btn_class = '',
|
|
hide_icon = false
|
|
}: Props = $props();
|
|
|
|
// *** Import Svelte specific
|
|
import { goto } from '$app/navigation';
|
|
|
|
// *** Import other supporting libraries
|
|
import {
|
|
// ArrowBigRight,
|
|
BadgeQuestionMark,
|
|
ChevronDown,
|
|
ChevronRight,
|
|
// CircleX,
|
|
// Copy,
|
|
// Eye, EyeOff,
|
|
// Key,
|
|
LifeBuoy,
|
|
// LogIn, LogOut, LockKeyhole,
|
|
// Mail, MailCheck,
|
|
// Menu,
|
|
RefreshCw,
|
|
RefreshCcw,
|
|
RefreshCcwDot,
|
|
// ShieldEllipsis, ShieldMinus, ShieldPlus, ShieldUser,
|
|
SquareX
|
|
// User, UserCheck
|
|
} from '@lucide/svelte';
|
|
|
|
// *** Import Aether specific variables and functions
|
|
import {
|
|
ae_snip,
|
|
ae_loc,
|
|
ae_sess,
|
|
ae_api,
|
|
ae_trig,
|
|
slct,
|
|
slct_trigger,
|
|
type key_val
|
|
} from '$lib/stores/ae_stores';
|
|
import { User } from 'lucide-svelte';
|
|
import { api } from '$lib/api/api';
|
|
|
|
if (log_lvl) {
|
|
console.log(`Help - technical support component loaded`);
|
|
}
|
|
|
|
let help_tech_text: string = $state('');
|
|
let hide_additional_info: boolean = $state(true);
|
|
|
|
function preventDefault<T extends Event>(fn: (event: T) => void) {
|
|
return function (event: T) {
|
|
event.preventDefault();
|
|
fn(event);
|
|
};
|
|
}
|
|
|
|
function send_help_tech_email() {
|
|
if (log_lvl) {
|
|
console.log(`*** send_help_tech_email() ***`);
|
|
}
|
|
|
|
let subject = `Technical Notification - ${$ae_loc.name}`;
|
|
|
|
let body_html = `
|
|
<div>
|
|
Technical Notification,\n\n
|
|
<ul>
|
|
<li>Datetime: ${new Date().toISOString()}</li>
|
|
<li>URL: ${window.location.href}</li>
|
|
<li>Browser: ${navigator.userAgent}</li>
|
|
<li>Viewport Size: ${window.innerWidth} x ${window.innerHeight}</li>
|
|
<li>Screen Resolution: ${window.screen.width} x ${window.screen.height}</li>
|
|
<li>In iframe: ${$ae_loc?.iframe}</li>
|
|
<li>Theme Mode: ${$ae_loc?.theme_mode}</li>
|
|
<li>Theme Name: ${$ae_loc?.theme_name}</li>
|
|
<li>Account ID: ${$slct.account_id}</li>
|
|
<li>Access Type: ${$ae_loc?.access_type}</li>
|
|
${$ae_loc?.person_id ? `<li>person_id: ${$ae_loc?.person_id}</li>` : ''}
|
|
${$ae_loc?.user_id ? `<li>user_id: ${$ae_loc?.user_id}</li>` : ''}
|
|
${$ae_loc?.username ? `<li>username: ${$ae_loc?.username}</li>` : ''}
|
|
${$ae_loc?.email ? `<li>email: ${$ae_loc?.email}</li>` : ''}
|
|
<li>API Base URL: ${$ae_api.base_url}</li>
|
|
</ul>
|
|
<p>
|
|
Help Request:\n\n
|
|
${help_tech_text}
|
|
</p>
|
|
|
|
</div>
|
|
`;
|
|
|
|
api.send_email({
|
|
api_cfg: $ae_api,
|
|
from_email: $ae_loc.site_cfg_json?.noreply_email ?? 'noreply+tech@oneskyit.com',
|
|
from_name: $ae_loc.site_cfg_json?.noreply_name ?? 'IT NoReply',
|
|
// to_email: $ae_loc.site_cfg_json?.admin_email ?? 'admin+tech@oneskyit.com', // 'scott+idaabb@oneskyit.com',
|
|
to_email: 'it+tech@oneskyit.com',
|
|
// to_email: $idaa_slct.post_obj.email,
|
|
// to_email: 'scott+idaabb@oneskyit.com',
|
|
// to_name: $ae_loc.site_cfg_json?.admin_name ?? 'IT Tech',
|
|
to_name: 'IT Tech',
|
|
// to_name: $idaa_slct.post_obj.full_name ?? 'IDAA BB Poster',
|
|
subject: subject,
|
|
body_html: body_html
|
|
});
|
|
|
|
help_tech_text = ''; // Clear the text area after sending
|
|
}
|
|
</script>
|
|
|
|
<!-- class:bg-radial-[at_55%_50%]={$ae_sess.show_help_tech}
|
|
class:from-blue-400={$ae_sess.show_help_tech}
|
|
class:to-transparent={$ae_sess.show_help_tech}
|
|
class:to-90%={$ae_sess.show_help_tech} -->
|
|
<div
|
|
class="
|
|
flex flex-row
|
|
items-center justify-center
|
|
rounded-lg shadow-2xl
|
|
border-1 border-transparent
|
|
transition-all
|
|
{e_class}
|
|
{!$ae_sess.show_help_tech ? e_class_form_hidden : e_class_form_showing}
|
|
relative
|
|
"
|
|
class:w-xl={$ae_sess.show_help_tech}
|
|
class:w-fit={!$ae_sess.show_help_tech}
|
|
class:mx-auto={$ae_sess.show_help_tech}
|
|
class:m-2={$ae_sess.show_help_tech}
|
|
class:p-2={$ae_sess.show_help_tech}
|
|
class:hover:border-blue-400={$ae_sess.show_help_tech}
|
|
class:hover:dark:border-blue-600={$ae_sess.show_help_tech}
|
|
class:hover:shadow-blue-200={$ae_sess.show_help_tech}
|
|
class:hover:dark:shadow-blue-800={$ae_sess.show_help_tech}
|
|
class:bg-blue-100={$ae_sess.show_help_tech}
|
|
class:dark:bg-blue-900={$ae_sess.show_help_tech}
|
|
>
|
|
{#if $ae_sess.show_help_tech}
|
|
<div
|
|
class="
|
|
w-xl
|
|
flex flex-col gap-1
|
|
items-center justify-center
|
|
p-2
|
|
border rounded-xl border-gray-500/20
|
|
bg-blue-200
|
|
dark:bg-blue-800
|
|
transition-all
|
|
"
|
|
>
|
|
<div
|
|
class="
|
|
d-flex align-items-center justify-content-between
|
|
flex flex-row gap-1 items-center justify-between
|
|
w-full
|
|
"
|
|
>
|
|
<h1
|
|
class="
|
|
h1
|
|
text-base font-semibold text-gray-800 dark:text-gray-200
|
|
w-fit
|
|
{e_class_h1}
|
|
"
|
|
>
|
|
{#if e_success}
|
|
<span class="text-lg text-green-800 dark:text-green-200 font-semibold">
|
|
<BadgeQuestionMark class="inline-block mr-2" />
|
|
Help Requested
|
|
</span>
|
|
{:else}
|
|
<span class="text-lg text-gray-800 dark:text-gray-200 font-semibold">
|
|
<BadgeQuestionMark class="inline-block mr-2" />
|
|
<!-- Request Technical Help -->
|
|
Notify Technical Support
|
|
</span>
|
|
<!-- <span class="text-gray-500">
|
|
Send your help request with or without a description.
|
|
</span> -->
|
|
{/if}
|
|
|
|
<!-- Cancel button -->
|
|
</h1>
|
|
<button
|
|
type="button"
|
|
onclick={() => ($ae_sess.show_help_tech = false)}
|
|
class="
|
|
btn btn-base
|
|
preset-tonal-tertiary
|
|
preset-outlined-tertiary-100-900
|
|
hover:preset-filled-tertiary-200-800
|
|
transition-all
|
|
{btn_class}
|
|
"
|
|
title="Close Help Request Form"
|
|
>
|
|
<!-- <span class="fas fa-times"></span> -->
|
|
<SquareX size="1em" />
|
|
<span class="sr-only">Close</span>
|
|
</button>
|
|
</div>
|
|
|
|
<form
|
|
class="
|
|
m-1
|
|
flex flex-col gap-1
|
|
items-center justify-center
|
|
w-md max-w-lg
|
|
"
|
|
onsubmit={preventDefault(() => {
|
|
// Do stuff...
|
|
send_help_tech_email();
|
|
|
|
// Hide the request form
|
|
$ae_sess.show_help_tech = false;
|
|
|
|
alert('Notification sent to the IT team.');
|
|
})}
|
|
>
|
|
<textarea
|
|
class="
|
|
form-control
|
|
w-full max-w-lg h-24 p-2
|
|
border border-gray-300 rounded
|
|
text-gray-950 dark:text-gray-50
|
|
bg-white dark:bg-gray-500
|
|
hover:dark:bg-gray-50
|
|
hover:dark:text-gray-950
|
|
"
|
|
placeholder="Send with or without a description...."
|
|
bind:value={help_tech_text}
|
|
></textarea>
|
|
|
|
<button
|
|
type="submit"
|
|
class="
|
|
btn btn-lg
|
|
m-1
|
|
preset-tonal-warning
|
|
preset-outlined-warning-100-900
|
|
hover:preset-filled-warning-200-800
|
|
|
|
|
|
transition-all
|
|
{btn_class}
|
|
"
|
|
title={btn_title}
|
|
>
|
|
{#if !hide_icon}
|
|
<!-- <BadgeQuestionMark class="inline-block mr-2" /> -->
|
|
<LifeBuoy class="inline-block m-1" />
|
|
{/if}
|
|
|
|
{#if !help_tech_text}
|
|
Notify Without Description
|
|
{:else}
|
|
Send Notification
|
|
{/if}
|
|
</button>
|
|
</form>
|
|
|
|
<div
|
|
class="
|
|
text-sm text-gray-700 dark:text-gray-300 text-center italic
|
|
"
|
|
>
|
|
This is intended for technical issues only. Please contact your organization's staff if you
|
|
have a question about your membership, recorded content, meetings, or posts.
|
|
</div>
|
|
|
|
<div
|
|
class="
|
|
border border-gray-300 rounded p-2
|
|
w-full
|
|
max-w-2xl
|
|
overflow-scroll
|
|
"
|
|
>
|
|
<div
|
|
class="
|
|
d-flex align-items-center justify-content-between
|
|
flex flex-row gap-1 items-center justify-between
|
|
w-full
|
|
"
|
|
>
|
|
<h2
|
|
class="
|
|
h2
|
|
text-base font-semibold text-gray-800 dark:text-gray-200
|
|
{e_class_h2}
|
|
"
|
|
>
|
|
<span class="text-base font-semibold text-gray-800 dark:text-gray-200">
|
|
Additional Information Included
|
|
</span>
|
|
</h2>
|
|
<!-- Button to expand and show additional information -->
|
|
<button
|
|
type="button"
|
|
class="
|
|
btn btn-sm preset-tonal-tertiary
|
|
{btn_class}
|
|
"
|
|
onclick={() => (hide_additional_info = !hide_additional_info)}
|
|
title="Toggle additional information"
|
|
>
|
|
<span>
|
|
{#if hide_additional_info}
|
|
<!-- <span class="fas fa-caret-right"></span> -->
|
|
<ChevronRight size="1em" class="inline-block" />
|
|
Show
|
|
{:else}
|
|
<!-- <span class="fas fa-caret-down"></span> -->
|
|
<ChevronDown size="1em" class="inline-block" />
|
|
Hide
|
|
{/if}
|
|
</span>
|
|
</button>
|
|
</div>
|
|
<ul
|
|
class="list-disc list-inside text-sm text-gray-800 dark:text-gray-200"
|
|
class:hidden={hide_additional_info}
|
|
>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">Datetime =</span>
|
|
{new Date().toISOString()}
|
|
</li>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">URL =</span>
|
|
{window.location.href}
|
|
</li>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">Browser =</span>
|
|
{navigator.userAgent}
|
|
</li>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">Viewport Size =</span>
|
|
{window.innerWidth} x {window.innerHeight}
|
|
</li>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">Screen Resolution =</span>
|
|
{window.screen.width} x {window.screen.height}
|
|
</li>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">Dark mode =</span>
|
|
{window?.matchMedia?.('(prefers-color-scheme:dark)')?.matches ?? false}
|
|
</li>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">In iframe =</span>
|
|
{$ae_loc?.iframe}
|
|
</li>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">Theme Mode =</span>
|
|
{$ae_loc?.theme_mode}
|
|
</li>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">Theme Name =</span>
|
|
{$ae_loc?.theme_name}
|
|
</li>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">Account ID =</span>
|
|
{$slct.account_id}
|
|
</li>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">Access Type =</span>
|
|
{$ae_loc?.access_type}
|
|
</li>
|
|
{#if $ae_loc?.person_id}
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">person_id =</span>
|
|
{$ae_loc?.person_id}
|
|
</li>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">full_name =</span>
|
|
{$ae_loc?.full_name}
|
|
</li>
|
|
{/if}
|
|
{#if $ae_loc?.user_id}
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">user_id =</span>
|
|
{$ae_loc?.user_id}
|
|
</li>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">username =</span>
|
|
{$ae_loc?.username}
|
|
</li>
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">email =</span>
|
|
{$ae_loc?.email}
|
|
</li>
|
|
{/if}
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">API Base URL =</span>
|
|
{$ae_api.base_url}
|
|
</li>
|
|
|
|
{#if additional_kv && Object.keys(additional_kv).length > 0}
|
|
<h2 class="text-base font-semibold text-gray-800">Component Info:</h2>
|
|
<ul class="list-disc list-inside text-gray-800 text-sm">
|
|
{#each Object.entries(additional_kv) as [key, value]}
|
|
<li>
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">{key} =</span>
|
|
{value ?? '-- not set --'}
|
|
</li>
|
|
{/each}
|
|
</ul>
|
|
{/if}
|
|
</ul>
|
|
<div class="text-sm text-gray-700 dark:text-gray-300 text-center italic">
|
|
This information will be included in the help request to assist technical support in
|
|
diagnosing the issue.
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="
|
|
flex flex-row gap-2 items-center justify-around
|
|
w-full
|
|
mt-2
|
|
"
|
|
>
|
|
<button
|
|
type="button"
|
|
onclick={() => {
|
|
if ($ae_loc.edit_mode) {
|
|
// Confirm before clearing
|
|
if (
|
|
!confirm(
|
|
'Are you sure you want to clear IndexedDB databases, localStorage, and sessionStorage? This will also reload the page.'
|
|
)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
console.log(
|
|
'Clearing IndexedDB, localStorage, sessionStorage, and reloading the page...'
|
|
);
|
|
|
|
// Clear Indexed DB
|
|
indexedDB.deleteDatabase('ae_archives_db'); // Archives module
|
|
indexedDB.deleteDatabase('ae_core_db');
|
|
indexedDB.deleteDatabase('ae_events_db'); // Events module
|
|
indexedDB.deleteDatabase('ae_journals_db'); // Journals module
|
|
indexedDB.deleteDatabase('ae_posts_db'); // Posts module
|
|
indexedDB.deleteDatabase('ae_sponsorships_db'); // Sponsorships module
|
|
|
|
// Clear localStorage and sessionStorage
|
|
// Clearing the localStorage will force it to be re-created.
|
|
localStorage.clear();
|
|
sessionStorage.clear();
|
|
|
|
goto('/', { invalidateAll: true });
|
|
|
|
// window.location.reload(true);
|
|
} else {
|
|
// Confirm before clearing
|
|
if (
|
|
!confirm(
|
|
'Are you sure you want to clear IndexedDB databases and some caches? This will also reload the page.'
|
|
)
|
|
) {
|
|
return;
|
|
}
|
|
|
|
console.log(
|
|
'Clearing IndexedDB, localStorage, sessionStorage, and reloading the page...'
|
|
);
|
|
|
|
// Clear Indexed DB
|
|
indexedDB.deleteDatabase('ae_archives_db'); // Archives module
|
|
indexedDB.deleteDatabase('ae_core_db');
|
|
indexedDB.deleteDatabase('ae_events_db'); // Events module
|
|
indexedDB.deleteDatabase('ae_journals_db'); // Journals module
|
|
indexedDB.deleteDatabase('ae_posts_db'); // Posts module
|
|
indexedDB.deleteDatabase('ae_sponsorships_db'); // Sponsorships module
|
|
|
|
window.location.reload(true);
|
|
}
|
|
|
|
// This does not seem to work fast enough or something?
|
|
// goto('/', {invalidateAll: true});
|
|
|
|
// The page does usually seem to reload correctly?
|
|
// window.location.reload(true); // true only works with Firefox
|
|
// alert('Local and Session Storage cleared and Indexed DBs deleted. You will probably want to refresh the page.');
|
|
}}
|
|
class="
|
|
btn btn-sm
|
|
preset-tonal-surface
|
|
preset-outlined-warning-100-900
|
|
hover:preset-filled-warning-200-800
|
|
transition-all
|
|
{btn_class}
|
|
"
|
|
title="Clear App Data & Settings: Clear IndexedDB and reload. If in edit mode localStorage and sessionStorage will also be cleared."
|
|
>
|
|
<!-- <span class="fas fa-eraser mx-1"></span> -->
|
|
<!-- <span class="fas fa-sync mx-1"></span> -->
|
|
<RefreshCw size="1em" class="inline-block" />
|
|
<span class="md:inline">Clear & Reload</span>
|
|
</button>
|
|
|
|
<!-- Cancel button -->
|
|
<button
|
|
type="button"
|
|
onclick={() => ($ae_sess.show_help_tech = false)}
|
|
class="
|
|
btn btn-sm
|
|
preset-tonal-tertiary
|
|
preset-outlined-tertiary-100-900
|
|
hover:preset-filled-tertiary-100-900
|
|
transition-all
|
|
{btn_class}
|
|
"
|
|
title="Close Help Request Form"
|
|
>
|
|
<!-- <span class="fas fa-times"></span> -->
|
|
<SquareX size="1em" class="inline-block" />
|
|
<span class="">Cancel</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
{:else}
|
|
<button
|
|
type="button"
|
|
onclick={() => ($ae_sess.show_help_tech = true)}
|
|
class="
|
|
btn btn-sm
|
|
preset-filled-tertiary-400-600
|
|
preset-outlined-tertiary-100-900
|
|
hover:preset-filled-warning-500
|
|
transition-all
|
|
{btn_class}
|
|
{show_btn_class}
|
|
"
|
|
title={btn_title}
|
|
>
|
|
{#if !hide_icon}
|
|
<BadgeQuestionMark class="inline-block m-0.5" />
|
|
{/if}
|
|
<span class="hidden">
|
|
{btn_text}
|
|
</span>
|
|
</button>
|
|
{/if}
|
|
</div>
|