aboutsummaryrefslogtreecommitdiff
path: root/src_frontend/Components/Settings
diff options
context:
space:
mode:
Diffstat (limited to 'src_frontend/Components/Settings')
-rw-r--r--src_frontend/Components/Settings/CreateEditUser.svelte93
-rw-r--r--src_frontend/Components/Settings/InstanceName.svelte36
-rw-r--r--src_frontend/Components/Settings/SSLCert.svelte57
-rw-r--r--src_frontend/Components/Settings/Settings.svelte25
-rw-r--r--src_frontend/Components/Settings/System.svelte34
-rw-r--r--src_frontend/Components/Settings/Users.svelte93
-rw-r--r--src_frontend/Components/Settings/Version.svelte66
7 files changed, 404 insertions, 0 deletions
diff --git a/src_frontend/Components/Settings/CreateEditUser.svelte b/src_frontend/Components/Settings/CreateEditUser.svelte
new file mode 100644
index 0000000..ca87336
--- /dev/null
+++ b/src_frontend/Components/Settings/CreateEditUser.svelte
@@ -0,0 +1,93 @@
+<script>
+ import { onMount } from "svelte";
+ import dialogPolyfill from 'dialog-polyfill'
+ import Button from "../../ComponentLib/Button/Button.svelte";
+ import { authorizedSocket } from "../../stores/socketStore.js";
+ import { notif } from "../../stores/notifs";
+
+ export let username = null;
+
+ let modal;
+ let password = "";
+ let newUser = username == null;
+
+ function open() {
+ modal.showModal()
+ }
+ function register(node) {
+ dialogPolyfill.registerDialog(node);
+ }
+
+ function updateUser() {
+ authorizedSocket.emit("user:newpassword", username, password, (res) => {
+ if (!res.success) { notif({title: res.reason}); }
+ modal.close();
+ });
+ }
+
+ function createUser() {
+ authorizedSocket.emit("user:create", username, password, (res) => {
+ if (!res.success) { notif({title: res.reason}); }
+ modal.close();
+ });
+ }
+</script>
+
+<style>
+ dialog {
+ padding: 0;
+ border: none;
+ border-radius: 15px;
+ }
+ h2 {
+ margin: 0;
+ }
+ .content {
+ padding: 15px;
+ box-sizing: border-box;
+ }
+ input {
+ display: block;
+ width: 100%;
+ box-sizing: border-box;
+ }
+ .buttons {
+ padding: 0 15px 15px 15px;
+ display: flex;
+ }
+ .buttons > * {
+ flex-grow: 1;
+ }
+ .buttons > *:not(:last-child) {
+ margin-right: 5px;
+ }
+ .buttons > *:not(:first-child) {
+ margin-left: 5px;
+ }
+</style>
+
+<slot name="trigger" {open}></slot>
+<dialog bind:this={modal} use:register>
+ <div class="content">
+ <h2>
+ {#if newUser}
+ Create user
+ {:else}
+ Edit user
+ {/if}
+ </h2>
+ <label for="username">Username</label>
+ <input type="text" id="username" placeholder="username" bind:value={username} disabled="{!newUser}" />
+ <label for="password">password</label>
+ <input type="password" id="password" bind:value={password} />
+ </div>
+ <div class="buttons">
+ <div><Button fullWidth=true on:click={() => modal.close() } color={"var(--theme-primary)"} backgroundColor={"white"}>Cancel</Button></div>
+ {#if newUser}
+ <div><Button fullWidth=true on:click={createUser}>Create</Button></div>
+ {:else}
+ <div><Button fullWidth=true on:click={updateUser}>Update</Button></div>
+ {/if}
+ </div>
+
+</dialog> \ No newline at end of file
diff --git a/src_frontend/Components/Settings/InstanceName.svelte b/src_frontend/Components/Settings/InstanceName.svelte
new file mode 100644
index 0000000..6d1892a
--- /dev/null
+++ b/src_frontend/Components/Settings/InstanceName.svelte
@@ -0,0 +1,36 @@
+<script>
+ import { onMount } from "svelte";
+ import { openSocket, authorizedSocket } from "../../stores/socketStore.js";
+
+ let name = "-";
+
+ openSocket.on("name", (_name) => name = _name);
+
+ function saveName() {
+ authorizedSocket.emit("name:set", name, (res) => {});
+ }
+
+ onMount(async() => {
+ openSocket.emit("name:get");
+ });
+</script>
+
+<style>
+ div {
+ margin-bottom: 15px;
+ }
+ h1 { margin-bottom: 0; }
+ input {
+ background-color: var(--grey-200);
+ border-radius: 15px;
+ width: 100%;
+ padding: 15px;
+ box-sizing: border-box;
+ border: none;
+ }
+</style>
+
+<div>
+ <h1>Name</h1>
+ <input type="text" bind:value={name} on:change={saveName} />
+</div>
diff --git a/src_frontend/Components/Settings/SSLCert.svelte b/src_frontend/Components/Settings/SSLCert.svelte
new file mode 100644
index 0000000..adb3649
--- /dev/null
+++ b/src_frontend/Components/Settings/SSLCert.svelte
@@ -0,0 +1,57 @@
+<script>
+ import { onMount } from "svelte";
+
+ import FloatingButton from "../../ComponentLib/Button/FloatingButton.svelte";
+ import ConfirmActionDialog from "../Dialogs/ConfirmActionDialog.svelte";
+ import { authorizedSocket } from "../../stores/socketStore.js";
+
+ let isValid = false;
+ let CN = "-";
+ let validTime = "-";
+
+ authorizedSocket.on("sslcert:info", (status) => {
+ isValid = status.isValid;
+ CN = status.CN;
+ validTime = Math.round((status.certExpire-(new Date()).getTime())/86400000);
+ });
+
+ let newCertPromise;
+ function generateNewCert() {
+ newCertPromise = new Promise((resolve, reject) => {
+ authorizedSocket.emit("sslcert:generate_new", () => {
+ resolve();
+ });
+ });
+ }
+
+ onMount(async() => {
+ authorizedSocket.emit("sslcert:info");
+ });
+</script>
+
+<style>
+ h1 { margin-bottom: 0; }
+ p { margin: 0; }
+ .small {
+ font-weight: 100;
+ font-style: italic;
+ font-size: 12px;
+ color: var(--grey-600);
+ }
+ .button {
+ margin-top: 10px;
+ }
+</style>
+
+<div>
+ <h1>SSL Certificate</h1>
+ <p>{isValid ? "VALID" : "INVALID"} <span class="small">(for {validTime} days)</span></p>
+ <p><span class="small">CN</span> {CN}</p>
+
+ <ConfirmActionDialog title="Are you sure?" text="Are you sure you want to generate new self signed SSL Certificate?" action={generateNewCert}>
+ <svelte:fragment slot="trigger" let:open>
+ <div class="button"><FloatingButton on:click={open} bind:loadingPromise={newCertPromise} fullWidth=true>Generate new cerificate</FloatingButton></div>
+ </svelte:fragment>
+ </ConfirmActionDialog>
+ <!-- <div class="button"><Button fullWidth=true round=true>Show details</Button></div> -->
+</div>
diff --git a/src_frontend/Components/Settings/Settings.svelte b/src_frontend/Components/Settings/Settings.svelte
new file mode 100644
index 0000000..b95f1ac
--- /dev/null
+++ b/src_frontend/Components/Settings/Settings.svelte
@@ -0,0 +1,25 @@
+<script>
+ import { fade } from 'svelte/transition';
+ import InstanceName from './InstanceName.svelte';
+ import Version from "./Version.svelte";
+ import SSLCert from "./SSLCert.svelte";
+ import System from "./System.svelte";
+ import Users from "./Users.svelte";
+
+ import { authorizedSocketNeeded } from "../../stores/socketStore.js";
+ authorizedSocketNeeded.set(true);
+</script>
+
+<style>
+ div {
+ padding-bottom: var(--theme-padding);
+ }
+</style>
+
+<div>
+ <InstanceName />
+ <Version />
+ <SSLCert />
+ <Users />
+ <System />
+</div> \ No newline at end of file
diff --git a/src_frontend/Components/Settings/System.svelte b/src_frontend/Components/Settings/System.svelte
new file mode 100644
index 0000000..1af4531
--- /dev/null
+++ b/src_frontend/Components/Settings/System.svelte
@@ -0,0 +1,34 @@
+<script>
+ import FloatingButton from "../../ComponentLib/Button/FloatingButton.svelte";
+ import ConfirmActionDialog from "../Dialogs/ConfirmActionDialog.svelte";
+ import { authorizedSocket } from "../../stores/socketStore.js";
+
+ function restartSystem() {
+ authorizedSocket.emit("restart:system");
+ }
+ function restartService() {
+ authorizedSocket.emit("restart:service");
+ }
+
+</script>
+
+<style>
+ h1, p {
+ margin-bottom: 10px;
+ }
+ .button { margin-bottom: 10px; }
+</style>
+
+<div>
+ <h1>System restart</h1>
+ <ConfirmActionDialog title="Are you sure?" text="Are you sure you want to restart the rPI?" action={restartSystem}>
+ <svelte:fragment slot="trigger" let:open>
+ <div class="button"><FloatingButton on:click={open} fullWidth=true>Restart system</FloatingButton></div>
+ </svelte:fragment>
+ </ConfirmActionDialog>
+ <ConfirmActionDialog title="Are you sure?" text="Are you sure you want to restart the Luxcena NEO service?" action={restartService}>
+ <svelte:fragment slot="trigger" let:open>
+ <div class="button"><FloatingButton on:click={open} fullWidth=true>Restart service</FloatingButton></div>
+ </svelte:fragment>
+ </ConfirmActionDialog>
+</div> \ No newline at end of file
diff --git a/src_frontend/Components/Settings/Users.svelte b/src_frontend/Components/Settings/Users.svelte
new file mode 100644
index 0000000..7e68c3a
--- /dev/null
+++ b/src_frontend/Components/Settings/Users.svelte
@@ -0,0 +1,93 @@
+<script>
+ import { onMount } from "svelte";
+ import { authorizedSocket, authorizedSocketNeeded, user } from "../../stores/socketStore.js";
+ authorizedSocketNeeded.set(true);
+ import CreateEditUser from "./CreateEditUser.svelte";
+ import ConfirmActionDialog from "../Dialogs/ConfirmActionDialog.svelte";
+ import FloatingButton from "../../ComponentLib/Button/FloatingButton.svelte";
+
+
+ let usersList = [];
+
+ function deleteUser(username) {
+ authorizedSocket.emit("user:delete", username, (res) => {
+ if (!res.success) { notif({title: res.reason}); }
+ });
+ };
+
+ authorizedSocket.on("users", (users) => {
+ usersList = users;
+ });
+
+ onMount(() => {
+ authorizedSocket.emit("users:get");
+ });
+</script>
+
+<style>
+ h1 {
+ margin: 0;
+ }
+ ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ }
+ li {
+ width: 100%;
+ display: flex;
+ padding: 10px 10px;
+ border-radius: 5px;
+ align-items:center;
+ box-sizing: border-box;
+ }
+ li:hover {
+ background-color: var(--grey-100);
+ }
+ li:not(:last-child) {
+ border-bottom: 0.5px solid var(--grey-400);
+ }
+ .align-right { margin-left: auto; }
+ button {
+ background-color: transparent;
+ border: none;
+ padding: 10px;
+ border-radius: 50%;
+ }
+ button:hover {
+ background-color: var(--grey-300);
+ }
+ button:active {
+ background-color: var(--grey-400);
+ }
+</style>
+
+<div>
+ <h1>Users</h1>
+ <ul>
+ {#each usersList as _user}
+ <li>
+ {_user}
+ <div class="align-right">
+ {#if $user?.username != _user}
+ <ConfirmActionDialog title="Are you sure?" text="Are you sure you want to delete {_user}" action={() => {deleteUser(_user)}}>
+ <svelte:fragment slot="trigger" let:open>
+ <button on:click={open}><i class="fas fa-trash"></i></button>
+ </svelte:fragment>
+ </ConfirmActionDialog>
+ {/if}
+ <CreateEditUser username={_user}>
+ <svelte:fragment slot="trigger" let:open>
+ <button on:click={open}><i class="fas fa-edit"></i></button>
+ </svelte:fragment>
+ </CreateEditUser>
+ </div>
+ </li>
+ {/each}
+ </ul>
+ <CreateEditUser>
+ <svelte:fragment slot="trigger" let:open>
+ <div class="button"><FloatingButton on:click={open} fullWidth=true>Create new user</FloatingButton></div>
+ </svelte:fragment>
+ </CreateEditUser>
+</div> \ No newline at end of file
diff --git a/src_frontend/Components/Settings/Version.svelte b/src_frontend/Components/Settings/Version.svelte
new file mode 100644
index 0000000..35c8f96
--- /dev/null
+++ b/src_frontend/Components/Settings/Version.svelte
@@ -0,0 +1,66 @@
+<script>
+ import { onMount } from 'svelte';
+ import FloatingButton from "../../ComponentLib/Button/FloatingButton.svelte";
+ import PrettyVar from "../../ComponentLib/PrettyVar.svelte";
+ import { authorizedSocket } from "../../stores/socketStore.js";
+
+ let version = "-";
+ let branch = "-";
+ let newVer = "-";
+
+ authorizedSocket.on("version:branch", _branch => branch = _branch);
+ authorizedSocket.on("version:current_number", _version => version = _version);
+ authorizedSocket.on("version:newest_number", _version => newVer = _version);
+
+ let checkVersionPromise;
+ function checkForUpdate() {
+ checkVersionPromise = new Promise((resolve, reject) => {
+ authorizedSocket.emit("version:check_for_update", () => {
+ resolve();
+ });
+ });
+ }
+
+ let updateVersionPromise;
+ function doUpdate() {
+ authorizedSocket.emit("system:update_version");
+ }
+
+ onMount(async() => {
+ authorizedSocket.emit("version:branch");
+ authorizedSocket.emit("version:current_number");
+ authorizedSocket.emit("version:newest_number");
+ });
+</script>
+
+<style>
+ h1, p { margin: 0; }
+ .label {
+ font-weight: 100;
+ font-style: italic;
+ color: var(--grey-600);
+ }
+ .button-row {
+ /* display: flex; */
+ margin-top: 20px;
+ width: 100%;
+ /* justify-content: center; */
+ /* align-items: center; */
+ }
+ .update-available {
+ color: var(--green-300);
+ }
+</style>
+
+<div>
+ <h1>Version</h1>
+ <p><span class="label">Current version</span> <PrettyVar varText={version}/></p>
+ <p><span class="label">Current branch</span> <PrettyVar bind:varText={branch}/></p>
+ {#if newVer != version}
+ <p><span class="update-available">Version <PrettyVar bind:varText={newVer} /> available.</span></p>
+ <FloatingButton on:click={doUpdate} bind:loadingPromise={updateVersionPromise} fullWidth=true>Update luxcena-neo</FloatingButton>
+ {/if}
+ <div class="button-row">
+ <FloatingButton on:click={checkForUpdate} bind:loadingPromise={checkVersionPromise} fullWidth=true>Check for updates</FloatingButton>
+ </div>
+</div> \ No newline at end of file