diff options
author | Jakob Stendahl <jakob.stendahl@outlook.com> | 2021-09-19 19:43:11 +0200 |
---|---|---|
committer | Jakob Stendahl <jakob.stendahl@outlook.com> | 2021-09-19 19:43:11 +0200 |
commit | 7bdce37fd3f18e2712e18c4e2c64cac69af0aca1 (patch) | |
tree | b7ad3f1cca92e2dfd2664ae9e65652bd03ff58b2 /src_frontend/Components/Settings | |
parent | e6880cd8ccf82d993f222cb14b4860581654acb8 (diff) | |
download | Luxcena-Neo-7bdce37fd3f18e2712e18c4e2c64cac69af0aca1.tar.gz Luxcena-Neo-7bdce37fd3f18e2712e18c4e2c64cac69af0aca1.zip |
:boom: Introduce new UI based on svelte, and rewrite a lot of the node app and the NeoRuntime
Diffstat (limited to 'src_frontend/Components/Settings')
-rw-r--r-- | src_frontend/Components/Settings/CreateEditUser.svelte | 93 | ||||
-rw-r--r-- | src_frontend/Components/Settings/InstanceName.svelte | 36 | ||||
-rw-r--r-- | src_frontend/Components/Settings/SSLCert.svelte | 57 | ||||
-rw-r--r-- | src_frontend/Components/Settings/Settings.svelte | 25 | ||||
-rw-r--r-- | src_frontend/Components/Settings/System.svelte | 34 | ||||
-rw-r--r-- | src_frontend/Components/Settings/Users.svelte | 93 | ||||
-rw-r--r-- | src_frontend/Components/Settings/Version.svelte | 60 |
7 files changed, 398 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..29d04ae --- /dev/null +++ b/src_frontend/Components/Settings/Version.svelte @@ -0,0 +1,60 @@ +<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(); + }); + }); + } + + 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> + {/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 |