-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from OpenEVSE/jeremypoulter/issue29
UI for Certificate management
- Loading branch information
Showing
13 changed files
with
426 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
<script> | ||
import { uistates_store } from "./../../../lib/stores/uistates.js"; | ||
import { _ } from 'svelte-i18n' | ||
import Box from "./../../ui/Box.svelte"; | ||
import Borders from "./../../ui/Borders.svelte"; | ||
import Button from "../../ui/Button.svelte" | ||
import IconButton from "../../ui/IconButton.svelte" | ||
import CertificatesModal from "./CertificatesModal.svelte"; | ||
import { certificate_store } from "../../../lib/stores/certificates.js" | ||
import { config_store } from "./../../../lib/stores/config.js"; | ||
import { serialQueue } from "./../../../lib/queue.js"; | ||
let certificates_modal_opened = false | ||
let removeCertificateState = "" | ||
async function removeCertificate(id) { | ||
let certificate = $certificate_store.findIndex(item => item.id === id) | ||
removeCertificateState = "loading" | ||
if (certificate > -1) | ||
{ | ||
if(await serialQueue.add(() => certificate_store.remove(id))) | ||
{ | ||
let config = { }; | ||
[ | ||
"mqtt_certitficate_id", | ||
"www_certitficate_id" | ||
].forEach(key => { | ||
if ($config_store[key] == id) { | ||
config[key] = "" | ||
} | ||
}); | ||
if (Object.keys(config).length > 0) { | ||
await serialQueue.add(() => config_store.upload(config)); | ||
} | ||
$certificate_store.splice(certificate,1) | ||
$certificate_store = $certificate_store | ||
removeCertificateState = "" | ||
} | ||
} | ||
} | ||
function uploadCertificate() { | ||
certificates_modal_opened = true; | ||
} | ||
</script> | ||
|
||
<Box title={$_("config.titles.certificates")} icon="mdi:certificate" back={true}> | ||
<div class="my-2 is-flex is-justify-content-center is-align-items-center is-flex-direction-column" > | ||
<Borders> | ||
{#if $certificate_store.length} | ||
<table class="table is-size-6 has-text-weight-normal" > | ||
<thead> | ||
<tr> | ||
<th class="has-text-centered has-text-dark"><abbr title={$_("config.certificates.id")}>{$_("config.certificates.id")}</abbr></th> | ||
<th class="has-text-centered has-text-dark"><abbr title={$_("config.certificates.type")}>{$_("config.certificates.type")}</abbr></th> | ||
<th class="has-text-centered has-text-dark"><abbr title="{$_("config.certificates.name")}">{$_("config.certificates.name")}</abbr></th> | ||
<th></th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{#each $certificate_store as item} | ||
<tr> | ||
<td class="has-text-dark">{ item.id }</td> | ||
<td class="has-text-dark">{ $_("config.certificates."+item.type) }</td> | ||
<td class="has-text-dark">{ item.name }</td> | ||
<td class="has-text-dark"> | ||
<div class="delabs"> | ||
<div class="del"> | ||
<IconButton | ||
icon="fa6-solid:xmark" | ||
size="is-size-5" | ||
state={removeCertificateState} | ||
color="has-text-danger" | ||
butn_submit={()=>{removeCertificate(item.id)}} | ||
/> | ||
</div> | ||
</div> | ||
</td> | ||
</tr> | ||
{/each} | ||
</tbody> | ||
</table> | ||
{:else} | ||
<div class="content">{$_("config.certificates.empty")}</div> | ||
{/if} | ||
</Borders> | ||
<div class="mt-4"> | ||
<Button name={$_("config.certificates.upload")} butn_submit={uploadCertificate}/> | ||
</div> | ||
</div> | ||
|
||
</Box> | ||
|
||
{#if certificates_modal_opened} | ||
<CertificatesModal bind:is_opened={certificates_modal_opened} /> | ||
{/if} |
128 changes: 128 additions & 0 deletions
128
src/components/blocks/configuration/CertificatesModal.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
<script> | ||
import { _ } from 'svelte-i18n' | ||
import Box from "../../ui/Box.svelte"; | ||
import Borders from "../../ui/Borders.svelte"; | ||
import Button from "../../ui/Button.svelte" | ||
import Select from "../../ui/Select.svelte"; | ||
import InputForm from "../../ui/InputForm.svelte"; | ||
import { serialQueue } from "../../../lib/queue.js"; | ||
import Modal from "../..//ui/Modal.svelte"; | ||
import { certificate_store } from "../../../lib/stores/certificates.js" | ||
import { validateFormData } from "./../../../lib/utils.js"; | ||
import { uistates_store } from "./../../../lib/stores/uistates.js"; | ||
import { get } from 'svelte/store' | ||
export let is_opened = false; | ||
let formdata = { | ||
type: {val: undefined, input: undefined, status: "", req: true}, | ||
name: {val: undefined, input: undefined, status: "", req: true}, | ||
private_key: {val: undefined, input: undefined, status: "", req: true}, | ||
certificate: {val: undefined, input: undefined, status: "", req: true} | ||
} | ||
let saveCertificateState = "" | ||
let timeout | ||
function alert(msg) { | ||
get(uistates_store).alertbox.title = "error" | ||
get(uistates_store).alertbox.body = msg | ||
get(uistates_store).alertbox.visible = true | ||
} | ||
async function saveCertificate() | ||
{ | ||
saveCertificateState = "loading"; | ||
formdata.private_key.req = formdata.type.val === "client"; | ||
let valid = validateFormData({data: formdata, i18n_path: "config.certificates.missing-", req: true}); | ||
if (!valid.ok) { | ||
saveCertificateState = "error"; | ||
alert(valid.msg) | ||
return; | ||
} | ||
let certificate = { | ||
name: formdata.name.val, | ||
certificate: formdata.certificate.val | ||
}; | ||
if (formdata.type.val === "client") { | ||
certificate.key = formdata.private_key.val; | ||
} | ||
let res = await serialQueue.add(() => certificate_store.upload(certificate)); | ||
if(res.success) | ||
{ | ||
saveCertificateState = "ok"; | ||
certificate.type = formdata.type.val; | ||
certificate.id = res.id; | ||
$certificate_store.push(certificate) | ||
timeout = setTimeout(() => { | ||
is_opened = false | ||
}, 500) | ||
} else { | ||
saveCertificateState = "error"; | ||
alert(res.msg) | ||
} | ||
$certificate_store = $certificate_store | ||
} | ||
</script> | ||
|
||
<Modal fit bind:is_opened> | ||
|
||
<Box title={$_("config.titles.certificates")} icon="mdi:certificate"> | ||
<div class="is-flex is-align-items-center is-justify-content-center px-6-tablet"> | ||
<div class="has-text-centered"> | ||
<div class=""> | ||
<Select | ||
items={[ | ||
{ name: $_("config.certificates.root"), value: "root" }, | ||
{ name: $_("config.certificates.client"), value: "client" } | ||
]} | ||
title={$_("config.certificates.type")} | ||
bind:this={formdata.type.input} | ||
bind:value={formdata.type.val} | ||
bind:status={formdata.type.status} | ||
/> | ||
|
||
<InputForm | ||
is_inline size={30} | ||
title="{$_("config.certificates.name")}*" | ||
placeholder="{$_("config.certificates.name_placeholder")}" | ||
bind:this={formdata.name.input} | ||
bind:value={formdata.name.val} | ||
bind:status={formdata.name.status} | ||
/> | ||
</div> | ||
|
||
<div> | ||
<InputForm | ||
title="{$_("config.certificates.certificate")}*" | ||
multiline monospace | ||
bind:this={formdata.certificate.input} | ||
bind:value={formdata.certificate.val} placeholder="-----BEGIN CERTIFICATE-----..." | ||
bind:status={formdata.certificate.status} | ||
/> | ||
</div> | ||
|
||
{#if "client" === formdata.type.val} | ||
<div> | ||
<InputForm | ||
title="{$_("config.certificates.private_key")}*" | ||
multiline monospace | ||
bind:this={formdata.private_key.input} | ||
bind:value={formdata.private_key.val} placeholder="-----BEGIN RSA PRIVATE KEY-----..." | ||
bind:status={formdata.private_key.status} | ||
/> | ||
</div> | ||
{/if} | ||
</div> | ||
</div> | ||
<div class="mt-4 is-flex is-justify-content-center mb-4"> | ||
<Button name={$_("save")} color="is-info" butn_submit={saveCertificate} state={saveCertificateState} /> | ||
<Button name={$_("cancel")} color="is-danger" butn_submit={()=>is_opened = false} /> | ||
</div> | ||
|
||
</Box> | ||
|
||
</Modal> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.