mirror of
https://github.com/seriousm4x/UpSnap.git
synced 2026-07-23 22:13:53 -04:00
207 lines
5.5 KiB
Svelte
207 lines
5.5 KiB
Svelte
<script lang="ts">
|
|
import { goto } from '$app/navigation';
|
|
import LL, { locale } from '$lib/i18n/i18n-svelte';
|
|
import { backendUrl, permission, pocketbase } from '$lib/stores/pocketbase';
|
|
import type { Device } from '$lib/types/device';
|
|
import {
|
|
faBed,
|
|
faCircleArrowDown,
|
|
faCircleArrowUp,
|
|
faLock,
|
|
faPen,
|
|
faRotateLeft
|
|
} from '@fortawesome/free-solid-svg-icons';
|
|
import type { Locale } from 'date-fns';
|
|
import { formatDistance, parseISO } from 'date-fns';
|
|
import { de } from 'date-fns/locale/de';
|
|
import { enUS } from 'date-fns/locale/en-US';
|
|
import { es } from 'date-fns/locale/es';
|
|
import { fr } from 'date-fns/locale/fr';
|
|
import { it } from 'date-fns/locale/it';
|
|
import { pt } from 'date-fns/locale/pt';
|
|
import { zhCN } from 'date-fns/locale/zh-CN';
|
|
import { zhTW } from 'date-fns/locale/zh-TW';
|
|
import Fa from 'svelte-fa';
|
|
import toast from 'svelte-french-toast';
|
|
import { scale } from 'svelte/transition';
|
|
import DeviceCardNic from './DeviceCardNic.svelte';
|
|
|
|
export let device: Device;
|
|
|
|
let moreButtons = [
|
|
{
|
|
text: $LL.device.card_btn_more_edit(),
|
|
icon: faPen,
|
|
onClick: () => goto(`/device/${device.id}`),
|
|
requires: $pocketbase.authStore.isAdmin || $permission.update?.includes(device.id)
|
|
},
|
|
{
|
|
text: $LL.device.card_btn_more_sleep(),
|
|
icon: faBed,
|
|
onClick: () => sleep(),
|
|
requires:
|
|
($pocketbase.authStore.isAdmin || $permission.power?.includes(device.id)) &&
|
|
device.status === 'online' &&
|
|
device.sol_enabled
|
|
},
|
|
{
|
|
text: $LL.device.card_btn_more_reboot(),
|
|
icon: faRotateLeft,
|
|
onClick: () => reboot(),
|
|
requires:
|
|
($pocketbase.authStore.isAdmin || $permission.power?.includes(device.id)) &&
|
|
device.status === 'online' &&
|
|
device.shutdown_cmd !== ''
|
|
}
|
|
];
|
|
|
|
// update device status change
|
|
let now = Date.now();
|
|
let interval: number;
|
|
$: {
|
|
clearInterval(interval);
|
|
interval = setInterval(() => {
|
|
now = Date.now();
|
|
}, 1000);
|
|
}
|
|
|
|
// dynamically import locales
|
|
// it's ugly but the only working solution i found in ~ 3 hours
|
|
var dateFnsLocale: Locale;
|
|
$: if ($locale !== undefined) {
|
|
(async () => {
|
|
switch ($locale) {
|
|
case 'de':
|
|
case 'de-DE':
|
|
dateFnsLocale = de;
|
|
break;
|
|
case 'en':
|
|
case 'en-US':
|
|
dateFnsLocale = enUS;
|
|
break;
|
|
case 'fr':
|
|
case 'fr-FR':
|
|
dateFnsLocale = fr;
|
|
break;
|
|
case 'it':
|
|
case 'it-IT':
|
|
dateFnsLocale = it;
|
|
break;
|
|
case 'es':
|
|
case 'es-ES':
|
|
dateFnsLocale = es;
|
|
break;
|
|
case 'pt':
|
|
case 'pt-PT':
|
|
dateFnsLocale = pt;
|
|
break;
|
|
case 'zh':
|
|
case 'zh-CN':
|
|
dateFnsLocale = zhCN;
|
|
break;
|
|
case 'zh-TW':
|
|
dateFnsLocale = zhTW;
|
|
break;
|
|
default:
|
|
dateFnsLocale = enUS;
|
|
break;
|
|
}
|
|
})();
|
|
}
|
|
|
|
function sleep() {
|
|
fetch(`${backendUrl}api/upsnap/sleep/${device.id}`, {
|
|
headers: {
|
|
Authorization: $pocketbase.authStore.token
|
|
}
|
|
}).catch((err) => {
|
|
toast.error(err.message);
|
|
});
|
|
}
|
|
|
|
function reboot() {
|
|
fetch(`${backendUrl}api/upsnap/reboot/${device.id}`, {
|
|
headers: {
|
|
Authorization: $pocketbase.authStore.token
|
|
}
|
|
}).catch((err) => {
|
|
toast.error(err.message);
|
|
});
|
|
}
|
|
</script>
|
|
|
|
<div class="card rounded-3xl bg-base-300 shadow-md" transition:scale={{ delay: 0, duration: 200 }}>
|
|
<div class="card-body p-6">
|
|
{#if device.link.toString() !== ''}
|
|
<a href={device.link.toString()} target="_blank">
|
|
<h1 class="link card-title">{device.name}</h1>
|
|
</a>
|
|
{:else}
|
|
<h1 class="card-title">{device.name}</h1>
|
|
{/if}
|
|
<ul class="menu rounded-box bg-base-200">
|
|
<!-- TODO: change to nic array once backend supports it -->
|
|
<DeviceCardNic {device} />
|
|
</ul>
|
|
{#if device.wake_cron_enabled || device.shutdown_cron_enabled || device.password}
|
|
<div class="flex flex-row flex-wrap gap-2">
|
|
{#if device.wake_cron_enabled}
|
|
<div class="tooltip" data-tip={$LL.device.card_tooltip_wake_cron()}>
|
|
<span class="badge badge-success gap-1 p-3"
|
|
><Fa icon={faCircleArrowUp} />{device.wake_cron}</span
|
|
>
|
|
</div>
|
|
{/if}
|
|
{#if device.shutdown_cron_enabled}
|
|
<div class="tooltip" data-tip={$LL.device.card_tooltip_shutdown_cron()}>
|
|
<span class="badge badge-error gap-1 p-3"
|
|
><Fa icon={faCircleArrowDown} />{device.shutdown_cron}</span
|
|
>
|
|
</div>
|
|
{/if}
|
|
{#if device.password}
|
|
<div class="tooltip" data-tip={$LL.device.card_tooltip_wake_password()}>
|
|
<span class="badge gap-1 p-3"><Fa icon={faLock} />{$LL.device.card_password()}</span>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
<div class="card-actions mt-auto items-center">
|
|
<span
|
|
class="tooltip"
|
|
data-tip="{$LL.device.card_tooltip_last_status_change()}: {device.updated}"
|
|
>
|
|
{#if dateFnsLocale !== undefined}
|
|
{formatDistance(parseISO(device.updated), now, {
|
|
includeSeconds: true,
|
|
addSuffix: true,
|
|
locale: dateFnsLocale
|
|
})}
|
|
{/if}
|
|
</span>
|
|
{#if moreButtons.filter((btn) => btn.requires).length > 0}
|
|
<div class="dropdown dropdown-end dropdown-top ms-auto bg-base-300">
|
|
<label tabindex="-1" class="btn btn-sm m-1" for="more-{device.id}"
|
|
>{$LL.device.card_btn_more()}</label
|
|
>
|
|
<ul
|
|
id="more-{device.id}"
|
|
tabindex="-1"
|
|
class="menu dropdown-content z-[1] w-fit rounded-box bg-base-100 p-2 shadow"
|
|
>
|
|
{#each moreButtons as btn}
|
|
{#if btn.requires}
|
|
<li>
|
|
<button on:click={btn.onClick}>
|
|
<Fa icon={btn.icon} />{btn.text}
|
|
</button>
|
|
</li>
|
|
{/if}
|
|
{/each}
|
|
</ul>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
</div>
|