mirror of
https://github.com/seriousm4x/UpSnap.git
synced 2026-07-29 17:02:56 -04:00
feat: daisyUI 5, tailwind 4, design adjustments
This commit is contained in:
@@ -19,25 +19,23 @@
|
||||
"@eslint/js": "^9.19.0",
|
||||
"@sveltejs/adapter-static": "^3.0.8",
|
||||
"@sveltejs/kit": "^2.16.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.2",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"daisyui": "^4.12.23",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
||||
"daisyui": "5.0.0-beta.2",
|
||||
"eslint": "^9.19.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-plugin-svelte": "^2.46.1",
|
||||
"globals": "^15.14.0",
|
||||
"husky": "^9.1.7",
|
||||
"postcss": "^8.5.1",
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-svelte": "^3.3.3",
|
||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||
"svelte": "^4.2.19",
|
||||
"svelte": "^5.19.5",
|
||||
"svelte-check": "^4.1.4",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"tailwindcss": "^4.0.1",
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.7.3",
|
||||
"typescript-eslint": "^8.22.0",
|
||||
"vite": "^5.4.14"
|
||||
"vite": "^6.0.11"
|
||||
},
|
||||
"type": "module",
|
||||
"lint-staged": {
|
||||
@@ -46,10 +44,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
||||
"@tailwindcss/postcss": "^4.0.1",
|
||||
"cron-parser": "^4.9.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"pocketbase": "^0.25.1",
|
||||
"postcss": "^8.5.1",
|
||||
"svelte-fa": "^4.0.3",
|
||||
"svelte-french-toast": "^1.2.0",
|
||||
"theme-change": "^2.5.0",
|
||||
|
||||
3939
frontend/pnpm-lock.yaml
generated
3939
frontend/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +0,0 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {}
|
||||
}
|
||||
};
|
||||
5
frontend/postcss.config.mjs
Normal file
5
frontend/postcss.config.mjs
Normal file
@@ -0,0 +1,5 @@
|
||||
export default {
|
||||
plugins: {
|
||||
'@tailwindcss/postcss': {}
|
||||
}
|
||||
};
|
||||
@@ -1,3 +1,5 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@import 'tailwindcss';
|
||||
|
||||
@plugin "daisyui" {
|
||||
themes: all;
|
||||
}
|
||||
|
||||
@@ -31,13 +31,9 @@
|
||||
|
||||
export let device: Device;
|
||||
|
||||
let modalReboot: HTMLDialogElement;
|
||||
|
||||
$: moreButtons = [
|
||||
{
|
||||
text: $LL.device.card_btn_more_edit(),
|
||||
icon: faPen,
|
||||
onClick: () => goto(`/device/${device.id}`),
|
||||
requires: $pocketbase.authStore.isSuperuser || $permission.update?.includes(device.id)
|
||||
},
|
||||
{
|
||||
text: $LL.device.card_btn_more_sleep(),
|
||||
icon: faBed,
|
||||
@@ -50,11 +46,17 @@
|
||||
{
|
||||
text: $LL.device.card_btn_more_reboot(),
|
||||
icon: faRotateLeft,
|
||||
onClick: () => reboot(),
|
||||
onClick: () => askRebootConfirmation(),
|
||||
requires:
|
||||
($pocketbase.authStore.isSuperuser || $permission.power?.includes(device.id)) &&
|
||||
device.status === 'online' &&
|
||||
device.shutdown_cmd !== ''
|
||||
},
|
||||
{
|
||||
text: $LL.device.card_btn_more_edit(),
|
||||
icon: faPen,
|
||||
onClick: () => goto(`/device/${device.id}`),
|
||||
requires: $pocketbase.authStore.isSuperuser || $permission.update?.includes(device.id)
|
||||
}
|
||||
];
|
||||
|
||||
@@ -146,9 +148,17 @@
|
||||
locale: dateFnsLocale
|
||||
});
|
||||
}
|
||||
|
||||
function askRebootConfirmation() {
|
||||
if (device.shutdown_confirm) {
|
||||
modalReboot.showModal();
|
||||
} else {
|
||||
reboot();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="card rounded-3xl bg-base-300 shadow-md" transition:scale={{ delay: 0, duration: 200 }}>
|
||||
<div class="card bg-base-200 shadow-sm" transition:scale={{ delay: 0, duration: 200 }}>
|
||||
<div class="card-body p-6">
|
||||
{#if device.link.toString() !== ''}
|
||||
<a href={device.link.toString()} target="_blank">
|
||||
@@ -160,9 +170,9 @@
|
||||
{#if device.description}
|
||||
<p>{device.description}</p>
|
||||
{/if}
|
||||
<ul class="menu rounded-box bg-base-200">
|
||||
<div class="card rounded-box w-full">
|
||||
<DeviceCardNic {device} />
|
||||
</ul>
|
||||
</div>
|
||||
{#if device.wake_cron_enabled || device.shutdown_cron_enabled || device.password}
|
||||
<div class="mt-1 flex flex-row flex-wrap gap-2">
|
||||
{#if device.wake_cron_enabled}
|
||||
@@ -203,27 +213,33 @@
|
||||
{/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 class="ms-auto flex flex-row flex-wrap gap-1">
|
||||
{#each moreButtons as btn}
|
||||
{#if btn.requires}
|
||||
<div class="tooltip" data-tip={btn.text}>
|
||||
<button class="btn btn-sm btn-circle" on:click={btn.onClick}>
|
||||
<Fa icon={btn.icon} />
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<dialog class="modal" bind:this={modalReboot}>
|
||||
<div class="modal-box">
|
||||
<h3 class="text-lg font-bold">
|
||||
{$LL.device.modal_confirm_shutdown_title({ device: device.name })}
|
||||
</h3>
|
||||
<p class="py-4">{$LL.device.modal_confirm_shutdown_desc({ device: device.name })}</p>
|
||||
<div class="modal-action">
|
||||
<form method="dialog" class="flex flex-row flex-wrap gap-2">
|
||||
<button class="btn">{$LL.buttons.cancel()}</button>
|
||||
<button class="btn btn-success" on:click={reboot}>{$LL.buttons.confirm()}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import LL from '$lib/i18n/i18n-svelte';
|
||||
import { backendUrl, permission, pocketbase } from '$lib/stores/pocketbase';
|
||||
import type { Device } from '$lib/types/device';
|
||||
import { faCircle, faPowerOff } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faPowerOff } from '@fortawesome/free-solid-svg-icons';
|
||||
import Fa from 'svelte-fa';
|
||||
import toast from 'svelte-french-toast';
|
||||
|
||||
@@ -135,61 +135,66 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<li class="tooltip" class:disabled data-tip={hoverText}>
|
||||
<div
|
||||
class="flex items-start gap-4 p-2"
|
||||
on:click={disabled ? null : handleClick}
|
||||
on:keydown={disabled ? null : handleClick}
|
||||
role="none"
|
||||
>
|
||||
{#if device.status === 'offline'}
|
||||
<button class="btn btn-error flex-shrink"><Fa icon={faPowerOff} /></button>
|
||||
{:else if device.status === 'online'}
|
||||
<button
|
||||
class="btn btn-success flex-shrink"
|
||||
class:cursor-not-allowed={device.shutdown_cmd === ''}><Fa icon={faPowerOff} /></button
|
||||
>
|
||||
{:else if device.status === 'pending'}
|
||||
<button class="btn btn-warning flex-shrink">
|
||||
<span class="countdown font-mono">
|
||||
<span style="--value:{minutes};" />:
|
||||
<span style="--value:{seconds};" />
|
||||
</span>
|
||||
</button>
|
||||
{:else}
|
||||
<button class="btn btn-warning flex-shrink">
|
||||
<span class="loading loading-ring loading-sm" />
|
||||
</button>
|
||||
{/if}
|
||||
<div class="grow">
|
||||
<div class="text-lg font-bold leading-4">{device.ip}</div>
|
||||
<div>{device.mac}</div>
|
||||
<div class="flex flex-wrap gap-x-4">
|
||||
{#if device?.expand?.ports}
|
||||
{#each device?.expand?.ports.sort((a, b) => a.number - b.number) as port}
|
||||
<span class="flex items-center gap-1 break-all">
|
||||
{#if port.status}
|
||||
<Fa icon={faCircle} class="text-success" />
|
||||
{:else}
|
||||
<Fa icon={faCircle} class="text-error" />
|
||||
{/if}
|
||||
{#if port.link}
|
||||
<a
|
||||
href={port.link}
|
||||
target="_blank"
|
||||
class="underline"
|
||||
on:click={(e) => e.stopPropagation()}>{port.name} ({port.number})</a
|
||||
>
|
||||
{:else}
|
||||
{port.name} ({port.number})
|
||||
{/if}
|
||||
</span>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
<div
|
||||
class={`tooltip ${disabled ? 'cursor-not-allowed' : 'hover:bg-base-300 cursor-pointer'} bg-base-100 rounded-box flex items-start gap-4 p-2`}
|
||||
data-tip={hoverText}
|
||||
on:click={disabled ? null : handleClick}
|
||||
on:keydown={disabled ? null : handleClick}
|
||||
role="none"
|
||||
>
|
||||
{#if device.status === 'offline'}
|
||||
<button class="btn btn-error btn-circle size-12"><Fa icon={faPowerOff} /></button>
|
||||
{:else if device.status === 'online'}
|
||||
<button
|
||||
class="btn btn-success btn-circle size-12"
|
||||
class:cursor-not-allowed={device.shutdown_cmd === ''}><Fa icon={faPowerOff} /></button
|
||||
>
|
||||
{:else if device.status === 'pending'}
|
||||
<button class="btn btn-warning">
|
||||
<span class="countdown font-mono">
|
||||
<span style="--value:{minutes};"></span>:
|
||||
<span style="--value:{seconds};"></span>
|
||||
</span>
|
||||
</button>
|
||||
{:else}
|
||||
<button class="btn btn-warning btn-circle size-12" aria-label="Unknown">
|
||||
<span class="loading loading-ring loading-sm"></span>
|
||||
</button>
|
||||
{/if}
|
||||
<div class="grow">
|
||||
<div class="text-lg leading-4 font-bold">{device.ip}</div>
|
||||
<div class="">{device.mac}</div>
|
||||
<div class="flex flex-wrap gap-x-4">
|
||||
{#if device?.expand?.ports}
|
||||
{#each device?.expand?.ports.sort((a, b) => a.number - b.number) as port}
|
||||
<span class="flex items-center gap-1 break-all">
|
||||
{#if port.status}
|
||||
<div class="inline-grid *:[grid-area:1/1]">
|
||||
<div class="status status-success h-3 w-3 animate-ping"></div>
|
||||
<div class="status status-success h-3 w-3"></div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="inline-grid *:[grid-area:1/1]">
|
||||
<div class="status status-error h-3 w-3 animate-ping"></div>
|
||||
<div class="status status-error h-3 w-3"></div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if port.link}
|
||||
<a
|
||||
href={port.link}
|
||||
target="_blank"
|
||||
class="underline"
|
||||
on:click={(e) => e.stopPropagation()}>{port.name} ({port.number})</a
|
||||
>
|
||||
{:else}
|
||||
{port.name} ({port.number})
|
||||
{/if}
|
||||
</span>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
|
||||
<dialog class="modal" bind:this={modalWake}>
|
||||
<div class="modal-box">
|
||||
@@ -199,7 +204,7 @@
|
||||
<p class="py-4">{$LL.device.modal_confirm_wake_desc({ device: device.name })}</p>
|
||||
<div class="modal-action">
|
||||
<form method="dialog" class="flex flex-row flex-wrap gap-2">
|
||||
<button class="btn btn-neutral">{$LL.buttons.cancel()}</button>
|
||||
<button class="btn">{$LL.buttons.cancel()}</button>
|
||||
<button class="btn btn-success" on:click={wake}>{$LL.buttons.confirm()}</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -214,15 +219,9 @@
|
||||
<p class="py-4">{$LL.device.modal_confirm_shutdown_desc({ device: device.name })}</p>
|
||||
<div class="modal-action">
|
||||
<form method="dialog" class="flex flex-row flex-wrap gap-2">
|
||||
<button class="btn btn-neutral">{$LL.buttons.cancel()}</button>
|
||||
<button class="btn">{$LL.buttons.cancel()}</button>
|
||||
<button class="btn btn-success" on:click={shutdown}>{$LL.buttons.confirm()}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
||||
<style>
|
||||
:global(.menu li.disabled) {
|
||||
color: inherit;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -178,11 +178,11 @@
|
||||
</script>
|
||||
|
||||
<form on:submit|preventDefault={save}>
|
||||
<div class="card w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.device.general()}</h2>
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4">
|
||||
<div class="form-control w-full max-w-xs">
|
||||
<div class="w-full max-w-xs">
|
||||
<label class="label" for="device-name">
|
||||
<div class="label-text">
|
||||
<span>{$LL.device.general_name()}</span>
|
||||
@@ -198,7 +198,7 @@
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control w-full max-w-xs">
|
||||
<div class="w-full max-w-xs">
|
||||
<label class="label" for="device-ip">
|
||||
<div class="label-text">
|
||||
<span>{$LL.device.general_ip()}</span>
|
||||
@@ -214,7 +214,7 @@
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control w-full max-w-xs">
|
||||
<div class="w-full max-w-xs">
|
||||
<label class="label" for="device-mac">
|
||||
<div class="label-text">
|
||||
<span>{$LL.device.general_mac()}</span>
|
||||
@@ -230,7 +230,7 @@
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control w-full max-w-xs">
|
||||
<div class="w-full max-w-xs">
|
||||
<label class="label" for="device-netmask">
|
||||
<div class="label-text">
|
||||
<span>{$LL.device.general_netmask()}</span>
|
||||
@@ -246,7 +246,7 @@
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control w-full max-w-xs">
|
||||
<div class="w-full max-w-xs">
|
||||
<label class="label" for="device-description">
|
||||
<div class="label-text">
|
||||
<span>{$LL.device.general_description()}</span>
|
||||
@@ -261,15 +261,15 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<span class="badge self-center text-error">* {$LL.device.general_required_field()}</span>
|
||||
<span class="badge text-error self-center">* {$LL.device.general_required_field()}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.device.ports()}</h2>
|
||||
<p class="my-2">{$LL.device.ports_desc()}</p>
|
||||
<div class="form-control w-full">
|
||||
<div class="w-full">
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
<!-- eslint-disable-next-line @typescript-eslint/no-unused-vars -->
|
||||
{#each device.expand.ports as _, index}
|
||||
@@ -277,21 +277,21 @@
|
||||
{/each}
|
||||
</div>
|
||||
<button
|
||||
class="btn btn-primary mt-4 max-w-xs"
|
||||
class="btn max-w-xs {device.expand.ports.length > 0 ? 'mt-4' : ''}"
|
||||
on:click={() => createEmptyPort()}
|
||||
type="button">{$LL.device.ports_add_new()}</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.device.link()}</h2>
|
||||
<p class="my-2">
|
||||
{$LL.device.link_desc()}
|
||||
</p>
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
<div class="form-control w-full">
|
||||
<div class="w-full max-w-xs">
|
||||
<label class="label" for="device-link">
|
||||
<div class="label-text">{$LL.device.link()}</div>
|
||||
</label>
|
||||
@@ -303,7 +303,7 @@
|
||||
bind:value={device.link}
|
||||
/>
|
||||
</div>
|
||||
<label class="form-control w-full max-w-xs">
|
||||
<div class="w-full max-w-xs">
|
||||
<label class="label" for="device-link-open">
|
||||
<div class="label-text">{$LL.device.link_open()}</div>
|
||||
</label>
|
||||
@@ -316,18 +316,18 @@
|
||||
<option value="same_tab">{$LL.device.link_open_same_tab()}</option>
|
||||
<option value="new_tab">{$LL.device.link_open_new_tab()}</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.device.ping()}</h2>
|
||||
<p class="my-2">
|
||||
<!-- eslint-disable svelte/no-at-html-tags -->
|
||||
{@html $LL.device.ping_desc()}
|
||||
</p>
|
||||
<div class="form-control w-full">
|
||||
<div class="w-full max-w-xs">
|
||||
<label class="label cursor-pointer" for="ping-cmd">
|
||||
<span class="label-text">{$LL.device.ping_cmd()}</span>
|
||||
</label>
|
||||
@@ -341,7 +341,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.device.wake()}</h2>
|
||||
<p class="my-2">
|
||||
@@ -349,7 +349,7 @@
|
||||
<!-- eslint-disable svelte/no-at-html-tags -->
|
||||
{@html $LL.settings.ping_interval_desc2()}
|
||||
</p>
|
||||
<div class="form-control w-full">
|
||||
<div class="w-full max-w-xs">
|
||||
<label class="label cursor-pointer" for="wake-cmd">
|
||||
<span class="label-text">{$LL.device.wake_cmd()}</span>
|
||||
</label>
|
||||
@@ -361,24 +361,33 @@
|
||||
bind:value={device.wake_cmd}
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control flex flex-row flex-wrap gap-4">
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<div class="flex flex-col">
|
||||
<label class="label cursor-pointer" for="wake-confirm">
|
||||
<span class="label-text">{$LL.device.require_confirmation()}</span>
|
||||
</label>
|
||||
<input
|
||||
id="wake-confirm"
|
||||
type="checkbox"
|
||||
class="toggle toggle-success"
|
||||
bind:checked={device.wake_confirm}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
<div class="flex flex-col">
|
||||
<label class="label cursor-pointer" for="wake-cron-enable">
|
||||
<span class="label-text">{$LL.device.wake_cron_enable()}</span>
|
||||
</label>
|
||||
<input
|
||||
id="wake-confirm"
|
||||
id="wake-cron-enable"
|
||||
type="checkbox"
|
||||
class="toggle toggle-success"
|
||||
bind:checked={device.wake_confirm}
|
||||
bind:checked={device.wake_cron_enabled}
|
||||
/>
|
||||
<label class="label cursor-pointer" for="wake-confirm">
|
||||
<span class="label-text">{$LL.device.require_confirmation()}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control flex flex-row flex-wrap gap-4">
|
||||
<div class="w-full max-w-xs">
|
||||
<label class="label" for="wake-cron">
|
||||
<span class="label-text"
|
||||
>{$LL.device.wake_cron()}
|
||||
>{$LL.device.shutdown_cron()}
|
||||
{#if device.wake_cron_enabled}
|
||||
<span class="text-error">*</span>
|
||||
{/if}
|
||||
@@ -394,22 +403,11 @@
|
||||
required={device.wake_cron_enabled}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<label class="label cursor-pointer" for="wake-cron-enable">
|
||||
<span class="label-text">{$LL.device.wake_cron_enable()}</span>
|
||||
</label>
|
||||
<input
|
||||
id="wake-cron-enable"
|
||||
type="checkbox"
|
||||
class="toggle toggle-success"
|
||||
bind:checked={device.wake_cron_enabled}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">Sleep-On-LAN</h2>
|
||||
<p class="mt-2">
|
||||
@@ -423,78 +421,73 @@
|
||||
<!-- eslint-disable svelte/no-at-html-tags -->
|
||||
{@html $LL.device.sol_desc3()}
|
||||
</p>
|
||||
<div class="mt-4 flex flex-row flex-wrap items-end gap-4">
|
||||
<div>
|
||||
<div class="form-control flex flex-row flex-wrap gap-4">
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<input
|
||||
id="sol-enable"
|
||||
type="checkbox"
|
||||
class="toggle toggle-success"
|
||||
bind:checked={device.sol_enabled}
|
||||
/>
|
||||
<label class="label cursor-pointer" for="sol-enable">
|
||||
<span class="label-text">{$LL.device.sol_enable()}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
<div class="flex flex-col">
|
||||
<label class="label cursor-pointer" for="sol-enable">
|
||||
<span class="label-text">{$LL.device.sol_enable()}</span>
|
||||
</label>
|
||||
<input
|
||||
id="sol-enable"
|
||||
type="checkbox"
|
||||
class="toggle toggle-success"
|
||||
bind:checked={device.sol_enabled}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<label class="label" for="sol-port">
|
||||
<span class="label-text"
|
||||
>{$LL.device.sol_port()}
|
||||
{#if device.sol_enabled}
|
||||
<span class="text-error">*</span>
|
||||
{/if}
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
id="sol-port"
|
||||
type="number"
|
||||
min="1"
|
||||
max="65535"
|
||||
class="input"
|
||||
bind:value={device.sol_port}
|
||||
disabled={!device.sol_enabled}
|
||||
required={device.sol_enabled}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{#if device.sol_enabled}
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
<div class="flex flex-col">
|
||||
<label class="label cursor-pointer" for="sol-auth">
|
||||
<span class="label-text">{$LL.device.sol_authorization()}</span>
|
||||
</label>
|
||||
<input
|
||||
id="sol-auth"
|
||||
type="checkbox"
|
||||
class="toggle toggle-success"
|
||||
bind:checked={device.sol_auth}
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control flex flex-col">
|
||||
<label class="label" for="sol-port">
|
||||
<div class="flex flex-col">
|
||||
<label class="label" for="sol-user">
|
||||
<span class="label-text"
|
||||
>{$LL.device.sol_port()}
|
||||
{#if device.sol_enabled}
|
||||
>{$LL.device.sol_user()}
|
||||
{#if device.sol_auth}
|
||||
<span class="text-error">*</span>
|
||||
{/if}
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
id="sol-port"
|
||||
type="number"
|
||||
min="1"
|
||||
max="65535"
|
||||
id="sol-user"
|
||||
type="text"
|
||||
placeholder={$LL.device.sol_user()}
|
||||
class="input"
|
||||
bind:value={device.sol_port}
|
||||
disabled={!device.sol_enabled}
|
||||
required={device.sol_enabled}
|
||||
bind:value={device.sol_user}
|
||||
disabled={!device.sol_auth}
|
||||
required={device.sol_auth}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{#if device.sol_enabled}
|
||||
<div>
|
||||
<div class="form-control flex flex-row flex-wrap gap-4">
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<input
|
||||
id="sol-auth"
|
||||
type="checkbox"
|
||||
class="toggle toggle-success"
|
||||
bind:checked={device.sol_auth}
|
||||
/>
|
||||
<label class="label cursor-pointer" for="sol-auth">
|
||||
<span class="label-text">{$LL.device.sol_authorization()}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control flex flex-col">
|
||||
<label class="label" for="sol-user">
|
||||
<span class="label-text"
|
||||
>{$LL.device.sol_user()}
|
||||
{#if device.sol_auth}
|
||||
<span class="text-error">*</span>
|
||||
{/if}
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
id="sol-user"
|
||||
type="text"
|
||||
placeholder={$LL.device.sol_user()}
|
||||
class="input"
|
||||
bind:value={device.sol_user}
|
||||
disabled={!device.sol_auth}
|
||||
required={device.sol_auth}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-control flex flex-col">
|
||||
<div class="flex flex-col">
|
||||
<label class="label" for="sol-password">
|
||||
<span class="label-text"
|
||||
>{$LL.device.sol_password()}
|
||||
@@ -513,12 +506,12 @@
|
||||
required={device.sol_auth}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.device.shutdown()}</h2>
|
||||
<p class="my-2">
|
||||
@@ -526,19 +519,19 @@
|
||||
{@html $LL.device.shutdown_desc()}
|
||||
</p>
|
||||
<p class="my-2 font-bold">{$LL.device.shutdown_examples()}</p>
|
||||
<div class="mockup-code min-w-0 max-w-fit text-sm">
|
||||
<div class="mockup-code max-w-fit min-w-0 text-sm">
|
||||
<pre data-prefix="#"><code>{$LL.device.shutdown_examples_windows()}</code></pre>
|
||||
<pre data-prefix="$" class="text-warning"><code
|
||||
>net rpc shutdown -I 192.168.1.13 -U "user%password"</code
|
||||
></pre>
|
||||
</div>
|
||||
<div class="mockup-code min-w-0 max-w-fit text-sm">
|
||||
<div class="mockup-code max-w-fit min-w-0 text-sm">
|
||||
<pre data-prefix="#"><code>{$LL.device.shutdown_examples_linux()}</code></pre>
|
||||
<pre data-prefix="$" class="text-warning"><code
|
||||
>sshpass -p password ssh -o "StrictHostKeyChecking=no" user@192.168.1.13 "sudo poweroff"</code
|
||||
></pre>
|
||||
</div>
|
||||
<div class="form-control w-full">
|
||||
<div class="w-full max-w-xs">
|
||||
<label class="label cursor-pointer" for="shutdown-cmd">
|
||||
<span class="label-text">{$LL.device.shutdown_cmd()}</span>
|
||||
</label>
|
||||
@@ -550,23 +543,34 @@
|
||||
bind:value={device.shutdown_cmd}
|
||||
/>
|
||||
</div>
|
||||
<div class="form-control flex flex-row flex-wrap gap-4">
|
||||
<div class="flex flex-row items-center gap-2">
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
<div class="flex flex-col">
|
||||
<label class="label cursor-pointer" for="shutdown-confirm">
|
||||
<span class="label-text">{$LL.device.require_confirmation()}</span>
|
||||
</label>
|
||||
<input
|
||||
id="shutdown-confirm"
|
||||
type="checkbox"
|
||||
class="toggle toggle-success"
|
||||
bind:checked={device.shutdown_confirm}
|
||||
/>
|
||||
<label class="label cursor-pointer" for="shutdown-confirm">
|
||||
<span class="label-text">{$LL.device.require_confirmation()}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<p class="my-2">
|
||||
{$LL.device.shutdown_cron_desc()}
|
||||
</p>
|
||||
<div class="form-control flex flex-row flex-wrap gap-4">
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
<div class="flex flex-col">
|
||||
<label class="label cursor-pointer" for="shutdown-cron-enable">
|
||||
<span class="label-text">{$LL.device.shutdown_cron_enable()}</span>
|
||||
</label>
|
||||
<input
|
||||
id="shutdown-cron-enable"
|
||||
type="checkbox"
|
||||
class="toggle toggle-success"
|
||||
bind:checked={device.shutdown_cron_enabled}
|
||||
/>
|
||||
</div>
|
||||
<div class="w-full max-w-xs">
|
||||
<label class="label" for="shutdown-cron">
|
||||
<span class="label-text"
|
||||
@@ -586,28 +590,17 @@
|
||||
required={device.shutdown_cron_enabled}
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<label class="label cursor-pointer" for="shutdown-cron-enable">
|
||||
<span class="label-text">{$LL.device.shutdown_cron_enable()}</span>
|
||||
</label>
|
||||
<input
|
||||
id="shutdown-cron-enable"
|
||||
type="checkbox"
|
||||
class="toggle toggle-success"
|
||||
bind:checked={device.shutdown_cron_enabled}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.device.password()}</h2>
|
||||
<p class="my-2">
|
||||
<!-- eslint-disable svelte/no-at-html-tags -->
|
||||
{@html $LL.device.password_desc()}
|
||||
</p>
|
||||
<div class="form-control w-full">
|
||||
<div class="w-full">
|
||||
<input
|
||||
type="password"
|
||||
placeholder="123456"
|
||||
@@ -618,7 +611,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.device.groups()}</h2>
|
||||
<p class="my-2">
|
||||
@@ -641,7 +634,7 @@
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checked:checkbox-primary"
|
||||
class="checkbox"
|
||||
checked={device.groups.indexOf(group.id) !== -1}
|
||||
/>
|
||||
{group.name}
|
||||
@@ -656,7 +649,7 @@
|
||||
type="text"
|
||||
bind:value={newGroup}
|
||||
/>
|
||||
<button class="btn btn-primary join-item" type="button" on:click={() => addGroup()}
|
||||
<button class="btn btn-neutral join-item" type="button" on:click={() => addGroup()}
|
||||
>{$LL.buttons.add()}</button
|
||||
>
|
||||
</div>
|
||||
@@ -667,19 +660,17 @@
|
||||
<button class="btn btn-error" type="button" on:click={() => deleteModal.showModal()}
|
||||
><Fa icon={faTrash} />{$LL.buttons.delete()}</button
|
||||
>
|
||||
<dialog class="modal" bind:this={deleteModal}>
|
||||
<form method="dialog" class="modal-box">
|
||||
<h3 class="text-lg font-bold">{$LL.users.confirm_delete_title()}</h3>
|
||||
<p class="py-4">{$LL.users.confirm_delete_desc({ username: device.name })}</p>
|
||||
<div class="modal-action">
|
||||
<button class="btn">{$LL.buttons.cancel()}</button>
|
||||
<button class="btn btn-error" on:click={() => deleteDevice()}
|
||||
>{$LL.buttons.delete()}</button
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
</dialog>
|
||||
{/if}
|
||||
<button class="btn btn-success" type="submit"><Fa icon={faSave} />{$LL.buttons.save()}</button>
|
||||
</div>
|
||||
</form>
|
||||
<dialog class="modal" bind:this={deleteModal}>
|
||||
<form method="dialog" class="modal-box">
|
||||
<h3 class="text-lg font-bold">{$LL.users.confirm_delete_title()}</h3>
|
||||
<p class="py-4">{$LL.users.confirm_delete_desc({ username: device.name })}</p>
|
||||
<div class="modal-action">
|
||||
<button class="btn">{$LL.buttons.cancel()}</button>
|
||||
<button class="btn btn-error" on:click={() => deleteDevice()}>{$LL.buttons.delete()}</button>
|
||||
</div>
|
||||
</form>
|
||||
</dialog>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import type { RecordModel } from 'pocketbase';
|
||||
import Fa from 'svelte-fa';
|
||||
import toast from 'svelte-french-toast';
|
||||
import { scale } from 'svelte/transition';
|
||||
|
||||
export let device: Device;
|
||||
export let index: number;
|
||||
@@ -28,57 +27,46 @@
|
||||
</script>
|
||||
|
||||
{#if device.expand.ports[index]}
|
||||
<div class="card bg-base-100 shadow-sm" transition:scale={{ delay: 0, duration: 200 }}>
|
||||
<div class="card-body p-3">
|
||||
<div class="flex flex-row gap-2">
|
||||
<div>
|
||||
<label class="label p-0" for="port-name-{index}">
|
||||
<span class="label-text">{$LL.device.ports_name()}</span>
|
||||
</label>
|
||||
<input
|
||||
id="port-name-{index}"
|
||||
type="text"
|
||||
placeholder="ssh"
|
||||
class="input input-sm input-bordered w-full"
|
||||
required
|
||||
bind:value={device.expand.ports[index].name}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label p-0" for="port-number-{index}">
|
||||
<span class="label-text">{$LL.device.ports_number()}</span>
|
||||
</label>
|
||||
<input
|
||||
id="port-number-{index}"
|
||||
type="number"
|
||||
placeholder="22"
|
||||
min="1"
|
||||
max="65535"
|
||||
class="input input-sm input-bordered w-full"
|
||||
required
|
||||
bind:value={device.expand.ports[index].number}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="fieldset bg-base-100 border-base-300 rounded-box w-xs border p-4">
|
||||
<legend class="fieldset-legend"># {device.expand.ports.length}</legend>
|
||||
<div class="flex flex-row gap-2">
|
||||
<div>
|
||||
<label class="label p-0" for="port-link-{index}">
|
||||
<span class="label-text">{$LL.device.link()}</span>
|
||||
</label>
|
||||
<label class="fieldset-label" for="port-name-{index}">{$LL.device.ports_name()}</label>
|
||||
<input
|
||||
id="port-link-{index}"
|
||||
type="url"
|
||||
placeholder="https:// ..."
|
||||
class="input input-sm input-bordered w-full"
|
||||
bind:value={device.expand.ports[index].link}
|
||||
id="port-name-{index}"
|
||||
type="text"
|
||||
class="input input-sm"
|
||||
placeholder="ssh"
|
||||
bind:value={device.expand.ports[index].name}
|
||||
/>
|
||||
</div>
|
||||
<div class="card-actions justify-end">
|
||||
<button
|
||||
class="btn btn-outline btn-error btn-xs"
|
||||
on:click={() => deletePort(device.expand.ports[index])}
|
||||
type="button"><Fa icon={faTrash} />{$LL.buttons.delete()}</button
|
||||
>
|
||||
<div>
|
||||
<label class="fieldset-label" for="port-number-{index}">{$LL.device.ports_number()}</label>
|
||||
<input
|
||||
type="number"
|
||||
class="input input-sm"
|
||||
min="1"
|
||||
max="65535"
|
||||
placeholder="22"
|
||||
required
|
||||
bind:value={device.expand.ports[index].number}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label class="fieldset-label" for="port-link-{index}">{$LL.device.link()}</label>
|
||||
<input
|
||||
id="port-link-{index}"
|
||||
type="url"
|
||||
class="input input-sm"
|
||||
placeholder="https:// ..."
|
||||
bind:value={device.expand.ports[index].link}
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
class="btn btn-error btn-xs btn-soft ms-auto"
|
||||
on:click={() => deletePort(device.expand.ports[index])}
|
||||
type="button"><Fa icon={faTrash} />{$LL.buttons.delete()}</button
|
||||
>
|
||||
</fieldset>
|
||||
{/if}
|
||||
|
||||
@@ -52,7 +52,9 @@
|
||||
'dim',
|
||||
'nord',
|
||||
'sunset',
|
||||
'colorful'
|
||||
'caramellatte',
|
||||
'abyss',
|
||||
'silk'
|
||||
];
|
||||
let activeTheme: string | null = '';
|
||||
$: avatar = $pocketbase.authStore.record?.avatar;
|
||||
@@ -100,7 +102,7 @@
|
||||
<ul
|
||||
id="mobile-menu"
|
||||
tabindex="-1"
|
||||
class="menu dropdown-content z-[1] mt-3 w-max gap-1 rounded-box bg-base-300 p-2 shadow"
|
||||
class="menu dropdown-content rounded-box bg-base-200 z-[1] mt-3 w-max gap-1 p-2 shadow-sm"
|
||||
>
|
||||
{#if $settingsPub?.website_title}
|
||||
<div class="menu-title">
|
||||
@@ -139,35 +141,24 @@
|
||||
<ul>
|
||||
<div class="h-fit max-h-72 overflow-scroll">
|
||||
{#each availableThemes as theme}
|
||||
<li>
|
||||
<li class="w-full">
|
||||
<button
|
||||
class="overflow-hidden rounded-lg text-left outline-base-content"
|
||||
class="gap-3 px-2"
|
||||
data-set-theme={theme}
|
||||
on:click={() => (activeTheme = theme)}
|
||||
on:keydown={() => (activeTheme = theme)}
|
||||
>
|
||||
<div
|
||||
data-theme={theme}
|
||||
class="w-full cursor-pointer rounded bg-base-100 font-sans text-base-content"
|
||||
class="bg-base-100 grid shrink-0 grid-cols-2 gap-0.5 rounded-md p-1 shadow-sm"
|
||||
>
|
||||
<div class="grid grid-cols-5 grid-rows-3">
|
||||
<div
|
||||
class="col-span-5 row-span-3 row-start-1 flex items-center gap-2 px-4 py-3"
|
||||
>
|
||||
<Fa
|
||||
icon={faCheck}
|
||||
class={activeTheme === theme ? 'visible' : 'invisible'}
|
||||
/>
|
||||
<div class="flex-grow text-sm">{theme}</div>
|
||||
<div class="flex h-full flex-shrink-0 flex-wrap gap-1">
|
||||
<div class="w-2 rounded bg-primary" />
|
||||
<div class="w-2 rounded bg-secondary" />
|
||||
<div class="w-2 rounded bg-accent" />
|
||||
<div class="w-2 rounded bg-neutral" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-base-content size-1 rounded-full"></div>
|
||||
<div class="bg-primary size-1 rounded-full"></div>
|
||||
<div class="bg-secondary size-1 rounded-full"></div>
|
||||
<div class="bg-accent size-1 rounded-full"></div>
|
||||
</div>
|
||||
<div class="truncate">{theme}</div>
|
||||
<Fa icon={faCheck} class={activeTheme === theme ? 'visible' : 'invisible'} />
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
@@ -177,7 +168,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<a class="btn btn-ghost px-2 text-xl normal-case" href="/">
|
||||
<a class="btn btn-ghost h-full border-0 px-2 text-xl" href="/">
|
||||
<img
|
||||
src={$settingsPub?.id && $settingsPub?.favicon
|
||||
? `${backendUrl}api/files/settings_public/${$settingsPub?.id}/${$settingsPub?.favicon}`
|
||||
@@ -192,64 +183,61 @@
|
||||
{#if $settingsPub?.website_title}
|
||||
<span class="px-2">{$settingsPub?.website_title}</span>
|
||||
{/if}
|
||||
<ul class="menu menu-horizontal gap-1 px-1">
|
||||
<li>
|
||||
<a href="/" class="p-2" class:active={$page.url.pathname === '/'}
|
||||
<ul class="menu menu-horizontal h-full gap-1 px-1">
|
||||
<li class="h-full">
|
||||
<a href="/" class="p-2" class:menu-active={$page.url.pathname === '/'}
|
||||
><Fa icon={faHome} />{$LL.home.page_title()}</a
|
||||
>
|
||||
</li>
|
||||
{#if $pocketbase.authStore.isSuperuser}
|
||||
<li>
|
||||
<a href="/users" class="p-2" class:active={$page.url.pathname.startsWith('/users')}
|
||||
<li class="h-full">
|
||||
<a href="/users" class="p-2" class:menu-active={$page.url.pathname.startsWith('/users')}
|
||||
><Fa icon={faUsersGear} />{$LL.users.page_title()}</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/settings/" class="p-2" class:active={$page.url.pathname.startsWith('/settings')}
|
||||
<li class="h-full">
|
||||
<a
|
||||
href="/settings/"
|
||||
class="p-2"
|
||||
class:menu-active={$page.url.pathname.startsWith('/settings')}
|
||||
><Fa icon={faCog} />{$LL.settings.page_title()}</a
|
||||
>
|
||||
</li>
|
||||
{/if}
|
||||
</ul>
|
||||
<div class="dropdown dropdown-end">
|
||||
<div tabindex="-1" class="btn btn-ghost normal-case">
|
||||
<Fa icon={faSwatchbook} />
|
||||
<span class="font-normal">{$LL.navbar.theme()}</span>
|
||||
<Fa icon={faChevronDown} />
|
||||
</div>
|
||||
<div
|
||||
class="dropdown-content z-[1] mt-3 h-fit max-h-96 w-56 overflow-y-auto rounded-box bg-base-200 text-base-content shadow"
|
||||
>
|
||||
<div class="grid grid-cols-1 gap-3 p-3" tabindex="-1">
|
||||
{#each availableThemes as theme}
|
||||
<button
|
||||
class="overflow-hidden rounded-lg text-left outline-base-content"
|
||||
data-set-theme={theme}
|
||||
on:click={() => (activeTheme = theme)}
|
||||
on:keydown={() => (activeTheme = theme)}
|
||||
>
|
||||
<div
|
||||
data-theme={theme}
|
||||
class="w-full cursor-pointer bg-base-100 font-sans text-base-content"
|
||||
>
|
||||
<div class="grid grid-cols-5 grid-rows-3">
|
||||
<div class="col-span-5 row-span-3 row-start-1 flex items-center gap-2 px-4 py-3">
|
||||
<Fa icon={faCheck} class={activeTheme === theme ? 'visible' : 'invisible'} />
|
||||
<div class="flex-grow text-sm">{theme}</div>
|
||||
<div class="flex h-full flex-shrink-0 flex-wrap gap-1">
|
||||
<div class="w-2 rounded bg-primary" />
|
||||
<div class="w-2 rounded bg-secondary" />
|
||||
<div class="w-2 rounded bg-accent" />
|
||||
<div class="w-2 rounded bg-neutral" />
|
||||
</div>
|
||||
<div class="dropdown dropdown-end">
|
||||
<button class="btn btn-ghost hover:bg-base-content/10 h-full border-0 p-2">
|
||||
<Fa icon={faSwatchbook} />
|
||||
<span class="font-normal">{$LL.navbar.theme()}</span>
|
||||
<Fa icon={faChevronDown} />
|
||||
</button>
|
||||
<div class="dropdown-content bg-base-200 rounded-box z-1 mt-3 w-52 shadow-sm">
|
||||
<ul class="menu menu-horizontal h-fit max-h-96 overflow-y-auto">
|
||||
{#each availableThemes as theme}
|
||||
<li class="w-full">
|
||||
<button
|
||||
class="gap-3 px-2"
|
||||
data-set-theme={theme}
|
||||
on:click={() => (activeTheme = theme)}
|
||||
on:keydown={() => (activeTheme = theme)}
|
||||
>
|
||||
<div
|
||||
data-theme={theme}
|
||||
class="bg-base-100 grid shrink-0 grid-cols-2 gap-0.5 rounded-md p-1 shadow-sm"
|
||||
>
|
||||
<div class="bg-base-content size-1 rounded-full"></div>
|
||||
<div class="bg-primary size-1 rounded-full"></div>
|
||||
<div class="bg-secondary size-1 rounded-full"></div>
|
||||
<div class="bg-accent size-1 rounded-full"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
{/each}
|
||||
<div class="truncate">{theme}</div>
|
||||
<Fa icon={faCheck} class={activeTheme === theme ? 'visible' : 'invisible'} />
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="ms-auto justify-end">
|
||||
{#if $pocketbase.authStore?.record !== null}
|
||||
@@ -267,7 +255,7 @@
|
||||
</label>
|
||||
<ul
|
||||
tabindex="-1"
|
||||
class="menu dropdown-content z-[1] mt-3 rounded-box bg-base-300 p-2 shadow"
|
||||
class="menu dropdown-content rounded-box bg-base-200 z-[1] mt-3 w-52 p-2 shadow"
|
||||
>
|
||||
<li class="menu-title">
|
||||
{$pocketbase.authStore.isSuperuser
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
</script>
|
||||
|
||||
{#if $settingsPriv}
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.device.tabs[1]()}</h2>
|
||||
<p class="my-2">
|
||||
@@ -136,7 +136,7 @@
|
||||
placeholder="192.168.1.0/24"
|
||||
bind:value={scanRange}
|
||||
/>
|
||||
<button class="btn btn-primary join-item" type="submit">{$LL.buttons.save()}</button>
|
||||
<button class="btn btn-neutral join-item" type="submit">{$LL.buttons.save()}</button>
|
||||
</div>
|
||||
</form>
|
||||
<div>
|
||||
@@ -153,7 +153,7 @@
|
||||
</button>
|
||||
{:else if scanRunning}
|
||||
<button class="btn no-animation">
|
||||
<span class="loading loading-spinner" />
|
||||
<span class="loading loading-spinner"></span>
|
||||
{$LL.device.network_scan_running()}
|
||||
</button>
|
||||
{:else}
|
||||
@@ -167,7 +167,7 @@
|
||||
</div>
|
||||
{#if scanResponse.devices?.length > 0}
|
||||
{#each scanResponse.devices.sort( (a, b) => a.ip.localeCompare( b.ip, undefined, { numeric: true } ) ) as device, index}
|
||||
<div class="collapse collapse-arrow bg-base-200">
|
||||
<div class="collapse-arrow bg-base-100 collapse">
|
||||
<input type="radio" name="scanned-devices" checked={index === 0} />
|
||||
<div class="collapse-title font-bold">
|
||||
{device.name} <span class="badge">{device.ip}</span>
|
||||
@@ -208,7 +208,9 @@
|
||||
<div class="form-control max-w-fit">
|
||||
<label class="label cursor-pointer">
|
||||
<input type="checkbox" class="checkbox" bind:checked={replaceNetmaskCheckbox} />
|
||||
<span class="label-text ms-2">{$LL.device.network_scan_replace_netmask()}</span>
|
||||
<span class="label-text ms-2 text-wrap break-words"
|
||||
>{$LL.device.network_scan_replace_netmask()}</span
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
{#if replaceNetmaskCheckbox}
|
||||
@@ -229,7 +231,9 @@
|
||||
<div class="form-control max-w-fit">
|
||||
<label class="label cursor-pointer">
|
||||
<input type="checkbox" class="checkbox" bind:checked={addAllCheckbox} />
|
||||
<span class="label-text ms-2">{$LL.device.network_scan_include_unknown()}</span>
|
||||
<span class="label-text ms-2 text-wrap break-words"
|
||||
>{$LL.device.network_scan_include_unknown()}</span
|
||||
>
|
||||
</label>
|
||||
{#if addAllCheckbox}
|
||||
<button
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<div class="container mx-auto max-w-lg text-center">
|
||||
<span class="loading loading-dots loading-lg" />
|
||||
<span class="loading loading-dots loading-lg"></span>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
|
||||
|
||||
|
||||
import { initI18nSvelte } from 'typesafe-i18n/svelte';
|
||||
import type { Formatters, Locales, TranslationFunctions, Translations } from './i18n-types';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
|
||||
|
||||
|
||||
import { initFormatters } from './formatters';
|
||||
import type { Locales, Translations } from './i18n-types';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
|
||||
|
||||
|
||||
import { initFormatters } from './formatters';
|
||||
import type { Locales, Translations } from './i18n-types';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// This file was auto-generated by 'typesafe-i18n'. Any manual changes will be overwritten.
|
||||
|
||||
|
||||
import {
|
||||
i18n as initI18n,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { page } from '$app/state';
|
||||
import Navbar from '$lib/components/Navbar.svelte';
|
||||
import Transition from '$lib/components/Transition.svelte';
|
||||
import LL, { setLocale } from '$lib/i18n/i18n-svelte';
|
||||
@@ -19,6 +19,8 @@
|
||||
duration: 5000
|
||||
};
|
||||
|
||||
let authIsValid = false;
|
||||
|
||||
onMount(async () => {
|
||||
// load locale
|
||||
const detectedLocale = detectLocale(
|
||||
@@ -31,6 +33,8 @@
|
||||
setLocale(detectedLocale);
|
||||
|
||||
$pocketbase.authStore.onChange(() => {
|
||||
authIsValid = $pocketbase.authStore.isValid;
|
||||
|
||||
// load user permissions
|
||||
if ($pocketbase.authStore.record?.collectionName === 'users') {
|
||||
$pocketbase
|
||||
@@ -57,7 +61,7 @@
|
||||
}
|
||||
|
||||
// redirect to welcome page if setup is not completed
|
||||
if ($settingsPub.setup_completed === false && $page.url.pathname !== '/welcome') {
|
||||
if ($settingsPub.setup_completed === false && page.url.pathname !== '/welcome') {
|
||||
$pocketbase.authStore.clear();
|
||||
goto('/welcome');
|
||||
return;
|
||||
@@ -98,13 +102,13 @@
|
||||
{/if}
|
||||
</svelte:head>
|
||||
|
||||
{#if $pocketbase.authStore.isValid}
|
||||
{#if authIsValid}
|
||||
<Navbar />
|
||||
{/if}
|
||||
|
||||
<Toaster position="bottom-center" {toastOptions} />
|
||||
|
||||
<Transition url={$page.url}>
|
||||
<Transition url={page.url}>
|
||||
<div class="container mx-auto mb-4 p-2">
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
@@ -109,11 +109,7 @@
|
||||
type="button"
|
||||
on:click={() => (orderByGroups = !orderByGroups)}
|
||||
>{$LL.home.order_groups()}
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checked:checkbox-primary"
|
||||
checked={orderByGroups}
|
||||
/>
|
||||
<input type="checkbox" class="checkbox" checked={orderByGroups} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -134,8 +130,11 @@
|
||||
value="ip"
|
||||
/>
|
||||
{/if}
|
||||
<div class="tooltip" data-tip={$LL.home.order_tooltip()}>
|
||||
<button class="btn join-item" on:click={() => (orderExpanded = !orderExpanded)}>
|
||||
<div class="tooltip join-item" data-tip={$LL.home.order_tooltip()}>
|
||||
<button
|
||||
class="btn {orderExpanded ? '' : 'rounded-field'}"
|
||||
on:click={() => (orderExpanded = !orderExpanded)}
|
||||
>
|
||||
{#if orderExpanded}
|
||||
<Fa icon={faChevronCircleRight} size="lg" />
|
||||
{:else}
|
||||
@@ -175,18 +174,34 @@
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="container text-center">
|
||||
<p>{$LL.home.no_devices()}</p>
|
||||
{#if $pocketbase.authStore.isSuperuser || $permission.create}
|
||||
<p>
|
||||
<a href="/device/new" class="btn btn-ghost"
|
||||
><Fa icon={faPlus} class="ms-2" />{$LL.home.add_first_device()}
|
||||
</a>
|
||||
</p>
|
||||
{:else}
|
||||
<p>
|
||||
{$LL.home.grant_permissions()}
|
||||
</p>
|
||||
{/if}
|
||||
<div class="flex justify-center">
|
||||
<div role="alert" class="alert alert-horizontal w-fit">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-6 w-6 shrink-0 stroke-current"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
||||
/>
|
||||
</svg>
|
||||
{#if $pocketbase.authStore.isSuperuser || $permission.create}
|
||||
<div>
|
||||
<h3 class="font-bold">{$LL.home.no_devices()}</h3>
|
||||
<div class="text-xs">{$LL.home.add_first_device()}</div>
|
||||
</div>
|
||||
<a href="/device/new" class="btn btn-sm"
|
||||
><Fa icon={faPlus} />{$LL.home.add_first_device()}</a
|
||||
>
|
||||
{:else}
|
||||
<span>
|
||||
Please ask the admin to grant you permissions to existing devices or to create new ones.
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
</script>
|
||||
|
||||
<h1 class="mb-8 text-3xl font-bold">{$LL.account.page_title()}</h1>
|
||||
<div class="card w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="flex flex-row items-center gap-4">
|
||||
<div class="avatar">
|
||||
@@ -166,16 +166,16 @@
|
||||
</div>
|
||||
</div>
|
||||
<form on:submit|preventDefault={saveUser}>
|
||||
<h2 class="card-title mb-2 mt-4">{$LL.account.avatar_title()}</h2>
|
||||
<h2 class="card-title mt-4 mb-2">{$LL.account.avatar_title()}</h2>
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
{#each [...Array(10).keys()] as i}
|
||||
<div class="avatar btn btn-circle btn-ghost">
|
||||
<div class="avatar">
|
||||
<div
|
||||
class="w-11 rounded-full"
|
||||
class:ring={newAvatar !== undefined
|
||||
class="hover:ring-neutral w-11 rounded-full hover:ring-2 hover:ring-offset-2"
|
||||
class:ring-2={newAvatar !== undefined
|
||||
? i === newAvatar
|
||||
: i === $pocketbase.authStore.record?.avatar}
|
||||
class:ring-primary={newAvatar !== undefined
|
||||
class:ring-success={newAvatar !== undefined
|
||||
? i === newAvatar
|
||||
: i === $pocketbase.authStore.record?.avatar}
|
||||
class:ring-offset-base-100={newAvatar !== undefined
|
||||
@@ -194,7 +194,7 @@
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<h2 class="card-title mb-2 mt-4">{$LL.account.language_title()}</h2>
|
||||
<h2 class="card-title mt-4 mb-2">{$LL.account.language_title()}</h2>
|
||||
<select class="select select-bordered w-full max-w-xs" bind:value={selectedLanguage}>
|
||||
<option value="auto" selected={localStorageLang === null}
|
||||
>🌐 {$LL.account.language_option_auto()}</option
|
||||
@@ -214,7 +214,7 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.account.change_password_title()}</h2>
|
||||
<p>{$LL.account.change_password_body()}</p>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
<h1 class="mb-8 text-3xl font-bold">{$LL.device.page_title()}</h1>
|
||||
<div class="mb-6 flex justify-center">
|
||||
<ul class="menu menu-horizontal gap-1 rounded-box bg-base-300">
|
||||
<ul class="menu menu-horizontal rounded-box bg-base-200">
|
||||
{#each tabs as tab}
|
||||
{#if tab.show}
|
||||
<li>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
</script>
|
||||
|
||||
<div class="mt-10 flex items-center justify-center">
|
||||
<div class="card w-full max-w-lg bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 w-full max-w-lg shadow-sm">
|
||||
<div class="card-body">
|
||||
{#if $settingsPub?.website_title}
|
||||
<h1 class="text-center text-xl font-bold">{$settingsPub?.website_title}</h1>
|
||||
@@ -89,7 +89,7 @@
|
||||
</label>
|
||||
<label class="relative block">
|
||||
<div
|
||||
class="absolute right-4 top-1/2 -translate-y-1/2 cursor-pointer"
|
||||
class="absolute top-1/2 right-4 -translate-y-1/2 cursor-pointer"
|
||||
role="none"
|
||||
on:click={() => toggleVisibility(inputPassword)}
|
||||
on:keydown={() => toggleVisibility(inputPassword)}
|
||||
@@ -108,13 +108,11 @@
|
||||
</label>
|
||||
<div class="card-actions mt-4">
|
||||
<div class="dropdown">
|
||||
<label tabindex="-1" class="btn btn-neutral" for="other-providers"
|
||||
>{$LL.login.btn_more()}</label
|
||||
>
|
||||
<label tabindex="-1" class="btn" for="other-providers">{$LL.login.btn_more()}</label>
|
||||
<ul
|
||||
id="other-providers"
|
||||
tabindex="-1"
|
||||
class="menu dropdown-content z-[1] w-56 rounded-box bg-base-200 p-2 shadow"
|
||||
class="menu dropdown-content rounded-box bg-base-200 z-1 w-56 p-2 shadow-sm"
|
||||
>
|
||||
<li class="menu-title flex flex-row items-center gap-2">
|
||||
{$LL.login.menu_title_auth_providers()}
|
||||
@@ -135,7 +133,7 @@
|
||||
{/await}
|
||||
</ul>
|
||||
</div>
|
||||
<button class="btn btn-primary ms-auto" type="submit"
|
||||
<button class="btn btn-success ms-auto" type="submit"
|
||||
>{$LL.login.btn_login()} <Fa icon={faLockOpen} /></button
|
||||
>
|
||||
</div>
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
{:else}
|
||||
<h1 class="mb-8 text-3xl font-bold">{$LL.settings.page_title()}</h1>
|
||||
<form on:submit|preventDefault={save}>
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.settings.ping_interval_title()}</h2>
|
||||
<p class="mt-2">
|
||||
@@ -120,17 +120,13 @@
|
||||
</p>
|
||||
<div class="form-control w-fit">
|
||||
<label class="label cursor-pointer gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox-primary checkbox"
|
||||
bind:checked={settingsPrivClone.lazy_ping}
|
||||
/>
|
||||
<input type="checkbox" class="checkbox" bind:checked={settingsPrivClone.lazy_ping} />
|
||||
<span class="label-text">{$LL.settings.lazy_ping_enable()}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.settings.website_title_title()}</h2>
|
||||
<p class="my-2">{$LL.settings.website_title_desc()}</p>
|
||||
@@ -144,7 +140,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.settings.icon_title()}</h2>
|
||||
<p class="my-2">
|
||||
@@ -171,7 +167,7 @@
|
||||
bind:this={faviconInputElement}
|
||||
/>
|
||||
<button
|
||||
class="btn btn-outline btn-error"
|
||||
class="btn btn-error"
|
||||
on:click={() => resetFavicon()}
|
||||
on:keydown={() => resetFavicon()}>{$LL.buttons.reset()}</button
|
||||
>
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
<h1 class="mb-8 text-3xl font-bold">{$LL.users.page_title()}</h1>
|
||||
{#each users as user, index}
|
||||
<form on:submit|preventDefault={() => save(user)}>
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body gap-4">
|
||||
<h2 class="card-title">
|
||||
<label tabindex="-1" class="avatar" for="avatar{index}">
|
||||
@@ -196,17 +196,13 @@
|
||||
</h2>
|
||||
{#each permissions.filter((perm) => perm.user === user.id) as permission}
|
||||
<div class="form-control w-fit">
|
||||
<label class="label cursor-pointer gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={permission.create}
|
||||
class="checkbox checked:checkbox-primary"
|
||||
/>
|
||||
<label class="label cursor-pointer gap-2 text-wrap">
|
||||
<input type="checkbox" bind:checked={permission.create} class="checkbox" />
|
||||
{$LL.users.allow_create_devices({ username: user.username })}
|
||||
</label>
|
||||
</div>
|
||||
{/each}
|
||||
<div class="collapse collapse-arrow bg-base-200">
|
||||
<div class="collapse-arrow bg-base-200 collapse">
|
||||
<input type="checkbox" />
|
||||
<div class="collapse-title text-xl font-medium">{$LL.users.device_permissions()}</div>
|
||||
<div class="collapse-content">
|
||||
@@ -222,7 +218,7 @@
|
||||
<div class="font-bold">{$LL.users.delete()}</div>
|
||||
<div class="font-bold">{$LL.users.power()}</div>
|
||||
{#each devices as device}
|
||||
<hr class="border-b-1 col-span-full w-full border-neutral opacity-30" />
|
||||
<hr class="border-neutral col-span-full w-full border-b-1 opacity-30" />
|
||||
{#each permissions.filter((perm) => perm.user === user.id) as permission}
|
||||
<div
|
||||
class="col-span-full flex flex-row flex-wrap gap-2 place-self-start break-all md:col-span-1"
|
||||
@@ -232,32 +228,32 @@
|
||||
</div>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checked:checkbox-primary md:col-start-2"
|
||||
class="checkbox md:col-start-2"
|
||||
bind:group={permission.read}
|
||||
value={device.id}
|
||||
/>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checked:checkbox-primary"
|
||||
class="checkbox"
|
||||
bind:group={permission.update}
|
||||
value={device.id}
|
||||
/>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checked:checkbox-primary"
|
||||
class="checkbox"
|
||||
bind:group={permission.delete}
|
||||
value={device.id}
|
||||
/>
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox checked:checkbox-primary"
|
||||
class="checkbox"
|
||||
bind:group={permission.power}
|
||||
value={device.id}
|
||||
/>
|
||||
{/each}
|
||||
{/each}
|
||||
<button
|
||||
class="btn btn-neutral btn-sm md:col-start-2"
|
||||
class="btn btn-sm md:col-start-2"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
toggleAllPermissions(user, 'read');
|
||||
@@ -268,7 +264,7 @@
|
||||
/></button
|
||||
>
|
||||
<button
|
||||
class=" btn btn-neutral btn-sm"
|
||||
class=" btn btn-sm"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
toggleAllPermissions(user, 'update');
|
||||
@@ -279,7 +275,7 @@
|
||||
/></button
|
||||
>
|
||||
<button
|
||||
class=" btn btn-neutral btn-sm"
|
||||
class=" btn btn-sm"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
toggleAllPermissions(user, 'delete');
|
||||
@@ -290,7 +286,7 @@
|
||||
/></button
|
||||
>
|
||||
<button
|
||||
class=" btn btn-neutral btn-sm"
|
||||
class=" btn btn-sm"
|
||||
type="button"
|
||||
on:click={() => {
|
||||
toggleAllPermissions(user, 'power');
|
||||
@@ -332,7 +328,7 @@
|
||||
</form>
|
||||
</dialog>
|
||||
{/each}
|
||||
<div class="card mt-6 w-full bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.users.create_new_user()}</h2>
|
||||
<form on:submit|preventDefault={createUser}>
|
||||
@@ -390,7 +386,7 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span class="badge mt-4 self-center text-error">* {$LL.users.required_field()}</span>
|
||||
<span class="badge text-error mt-4 self-center">* {$LL.users.required_field()}</span>
|
||||
<div class="card-actions justify-end">
|
||||
<button type="submit" class="btn btn-success mt-2"
|
||||
><Fa icon={faPlus} />{$LL.buttons.add()}</button
|
||||
|
||||
@@ -69,14 +69,14 @@
|
||||
|
||||
<div class="mt-10 flex items-center justify-center">
|
||||
<div class="my-4 flex w-screen max-w-lg flex-col gap-16">
|
||||
<div class="card bg-base-300 shadow-xl">
|
||||
<div class="card bg-base-200 shadow-sm">
|
||||
{#if $settingsPub?.setup_completed}
|
||||
<figure class="mx-auto w-72 pt-6"><img src="/gopher.svg" alt="Gopher" /></figure>
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{$LL.welcome.not_expected_title()}</h2>
|
||||
<p>{$LL.welcome.not_expected_desc()}</p>
|
||||
<div class="card-actions justify-end">
|
||||
<button class="btn btn-primary" on:click={() => goto('/')}
|
||||
<button class="btn btn-success" on:click={() => goto('/')}
|
||||
>{$LL.welcome.not_expected_back()}</button
|
||||
>
|
||||
</div>
|
||||
@@ -87,7 +87,7 @@
|
||||
<h2 class="card-title">{$LL.welcome.step1_page_title()}</h2>
|
||||
<p>{$LL.welcome.step1_setup_desc()}</p>
|
||||
<div class="card-actions justify-end">
|
||||
<button class="btn btn-primary" on:click={() => (stepsCompleted = 1)}
|
||||
<button class="btn btn-success" on:click={() => (stepsCompleted = 1)}
|
||||
>{$LL.welcome.step1_setup_btn_next()} <Fa icon={faArrowRight} /></button
|
||||
>
|
||||
</div>
|
||||
@@ -115,7 +115,7 @@
|
||||
</label>
|
||||
<label class="relative block">
|
||||
<div
|
||||
class="absolute right-4 top-1/2 -translate-y-1/2 cursor-pointer"
|
||||
class="absolute top-1/2 right-4 -translate-y-1/2 cursor-pointer"
|
||||
role="none"
|
||||
on:click={() => toggleVisibility(inputPassword)}
|
||||
on:keydown={() => toggleVisibility(inputPassword)}
|
||||
@@ -138,7 +138,7 @@
|
||||
</label>
|
||||
<label class="relative block">
|
||||
<div
|
||||
class="absolute right-4 top-1/2 -translate-y-1/2 cursor-pointer"
|
||||
class="absolute top-1/2 right-4 -translate-y-1/2 cursor-pointer"
|
||||
role="none"
|
||||
on:click={() => toggleVisibility(inputConfirm)}
|
||||
on:keydown={() => toggleVisibility(inputConfirm)}
|
||||
@@ -157,7 +157,7 @@
|
||||
/>
|
||||
</label>
|
||||
<div class="card-actions mt-4 justify-end">
|
||||
<button class="btn btn-primary" type="submit"
|
||||
<button class="btn btn-success" type="submit"
|
||||
>{$LL.welcome.step2_btn_create()} <Fa icon={faArrowRight} /></button
|
||||
>
|
||||
</div>
|
||||
@@ -178,7 +178,7 @@
|
||||
</div>
|
||||
{#if !$settingsPub?.setup_completed}
|
||||
<ul class="steps steps-horizontal">
|
||||
<li class="step step-primary">{$LL.welcome.progress_step1()}</li>
|
||||
<li class="step step-success">{$LL.welcome.progress_step1()}</li>
|
||||
<li class="step" class:step-primary={stepsCompleted > 0}>{$LL.welcome.progress_step2()}</li>
|
||||
<li class="step" class:step-primary={stepsCompleted > 1}>{$LL.welcome.progress_step3()}</li>
|
||||
</ul>
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
import themes from 'daisyui/src/theming/themes';
|
||||
import daisyui from 'daisyui';
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ['./src/**/*.{html,js,svelte,ts}'],
|
||||
theme: {
|
||||
extend: {}
|
||||
},
|
||||
plugins: [daisyui],
|
||||
daisyui: {
|
||||
themes: [
|
||||
{
|
||||
light: {
|
||||
...themes['light'],
|
||||
primary: '#55BCD9',
|
||||
secondary: '#D4A35C',
|
||||
'primary-content': '#ffffff'
|
||||
},
|
||||
dark: {
|
||||
...themes['dark'],
|
||||
primary: '#55BCD9',
|
||||
secondary: '#D4A35C',
|
||||
'base-300': '#12161b',
|
||||
'--rounded-btn': '1.9rem',
|
||||
'--tab-border': '2px',
|
||||
'--tab-radius': '.5rem'
|
||||
},
|
||||
cupcake: {
|
||||
...themes['cupcake'],
|
||||
primary: '#55BCD9',
|
||||
secondary: '#D4A35C',
|
||||
'primary-content': '#ffffff'
|
||||
},
|
||||
colorful: {
|
||||
...themes['light'],
|
||||
primary: '#00bdf8',
|
||||
secondary: '#009aff',
|
||||
accent: '#00b3a2',
|
||||
neutral: '#161200',
|
||||
'base-100': '#ffffff',
|
||||
info: '#00c5dc',
|
||||
success: '#00d892',
|
||||
warning: '#f77800',
|
||||
error: '#f36165'
|
||||
}
|
||||
},
|
||||
'bumblebee',
|
||||
'emerald',
|
||||
'corporate',
|
||||
'synthwave',
|
||||
'retro',
|
||||
'cyberpunk',
|
||||
'valentine',
|
||||
'halloween',
|
||||
'garden',
|
||||
'forest',
|
||||
'aqua',
|
||||
'lofi',
|
||||
'pastel',
|
||||
'fantasy',
|
||||
'wireframe',
|
||||
'black',
|
||||
'luxury',
|
||||
'dracula',
|
||||
'cmyk',
|
||||
'autumn',
|
||||
'business',
|
||||
'acid',
|
||||
'lemonade',
|
||||
'night',
|
||||
'coffee',
|
||||
'winter',
|
||||
'dim',
|
||||
'nord',
|
||||
'sunset'
|
||||
]
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user