webapp: Implement BasePage component for default views
This commit is contained in:
parent
93512e2e0c
commit
03066af1c4
28
webapp/src/components/BasePage.vue
Normal file
28
webapp/src/components/BasePage.vue
Normal file
@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>{{ title }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="text-center" v-if="isLoading">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="!isLoading">
|
||||
<slot />
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
title: { type: String, required: true },
|
||||
isLoading: { type: Boolean, required: false, default: false }
|
||||
},
|
||||
});
|
||||
</script>
|
||||
@ -1,10 +1,5 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>About OpenDTU</h1>
|
||||
</div>
|
||||
|
||||
|
||||
<BasePage :title="'About OpenDTU'">
|
||||
<div class="accordion" id="accordionExample">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="headingOne">
|
||||
@ -96,12 +91,13 @@
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</BasePage>
|
||||
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import {
|
||||
BIconInfoCircle,
|
||||
BIconActivity,
|
||||
@ -111,6 +107,7 @@ import {
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
BIconInfoCircle,
|
||||
BIconActivity,
|
||||
BIconBug,
|
||||
|
||||
@ -1,121 +1,110 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>Config Management</h1>
|
||||
</div>
|
||||
<BasePage :title="'Config Management'" :isLoading="loading">
|
||||
<BootstrapAlert v-model="showAlert" dismissible :variant="alertType">
|
||||
{{ alertMessage }}
|
||||
</BootstrapAlert>
|
||||
|
||||
<div class="text-center" v-if="loading">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">Backup: Configuration File Backup</div>
|
||||
<div class="card-body text-center">
|
||||
Backup the configuration file
|
||||
<button class="btn btn-primary" @click="downloadConfig">Backup
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="!loading">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">Backup: Configuration File Backup</div>
|
||||
<div class="card-body text-center">
|
||||
Backup the configuration file
|
||||
<button class="btn btn-primary" @click="downloadConfig">Backup
|
||||
<div class="card mt-5">
|
||||
<div class="card-header text-white bg-primary">Restore: Restore the Configuration File</div>
|
||||
<div class="card-body text-center">
|
||||
|
||||
<div v-if="!uploading && UploadError != ''">
|
||||
<p class="h1 mb-2">
|
||||
<BIconExclamationCircleFill />
|
||||
</p>
|
||||
<span style="vertical-align: middle" class="ml-2">
|
||||
{{ UploadError }}
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<button class="btn btn-light" @click="clear">
|
||||
<BIconArrowLeft /> Back
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-5">
|
||||
<div class="card-header text-white bg-primary">Restore: Restore the Configuration File</div>
|
||||
<div class="card-body text-center">
|
||||
|
||||
<div v-if="!uploading && UploadError != ''">
|
||||
<p class="h1 mb-2">
|
||||
<BIconExclamationCircleFill />
|
||||
</p>
|
||||
<span style="vertical-align: middle" class="ml-2">
|
||||
{{ UploadError }}
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<button class="btn btn-light" @click="clear">
|
||||
<BIconArrowLeft /> Back
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-else-if="!uploading && UploadSuccess">
|
||||
<span class="h1 mb-2">
|
||||
<BIconCheckCircle />
|
||||
</span>
|
||||
<span> Upload Success </span>
|
||||
<br />
|
||||
<br />
|
||||
<button class="btn btn-primary" @click="clear">
|
||||
<BIconArrowLeft /> Back
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-else-if="!uploading">
|
||||
<div class="form-group pt-2 mt-3">
|
||||
<input class="form-control" type="file" ref="file" accept=".json" @change="uploadConfig" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="uploading">
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" :style="{ width: progress + '%' }"
|
||||
v-bind:aria-valuenow="progress" aria-valuemin="0" aria-valuemax="100">
|
||||
{{ progress }}%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger mt-3" role="alert">
|
||||
<b>Note:</b> This operation replaces the configuration file with the restored configuration and
|
||||
restarts OpenDTU to apply all settings.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-5">
|
||||
<div class="card-header text-white bg-primary">Initialize: Perform Factory Reset</div>
|
||||
<div class="card-body text-center">
|
||||
|
||||
<button class="btn btn-danger" @click="onFactoryResetModal">Restore Factory-Default Settings
|
||||
<div v-else-if="!uploading && UploadSuccess">
|
||||
<span class="h1 mb-2">
|
||||
<BIconCheckCircle />
|
||||
</span>
|
||||
<span> Upload Success </span>
|
||||
<br />
|
||||
<br />
|
||||
<button class="btn btn-primary" @click="clear">
|
||||
<BIconArrowLeft /> Back
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger mt-3" role="alert">
|
||||
<b>Note:</b> Click Restore Factory-Default Settings to restore and initialize the
|
||||
factory-default settings and reboot.
|
||||
<div v-else-if="!uploading">
|
||||
<div class="form-group pt-2 mt-3">
|
||||
<input class="form-control" type="file" ref="file" accept=".json" @change="uploadConfig" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="modal" id="factoryReset" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Factory Reset</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Are you sure you want to delete the current configuration and reset all settings to their
|
||||
factory defaults?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @click="onFactoryResetCancel"
|
||||
data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-danger" @click="onFactoryResetPerform">Factory
|
||||
Reset!</button>
|
||||
<div v-else-if="uploading">
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" :style="{ width: progress + '%' }"
|
||||
v-bind:aria-valuenow="progress" aria-valuemin="0" aria-valuemax="100">
|
||||
{{ progress }}%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger mt-3" role="alert">
|
||||
<b>Note:</b> This operation replaces the configuration file with the restored configuration and
|
||||
restarts OpenDTU to apply all settings.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-5">
|
||||
<div class="card-header text-white bg-primary">Initialize: Perform Factory Reset</div>
|
||||
<div class="card-body text-center">
|
||||
|
||||
<button class="btn btn-danger" @click="onFactoryResetModal">Restore Factory-Default Settings
|
||||
</button>
|
||||
|
||||
<div class="alert alert-danger mt-3" role="alert">
|
||||
<b>Note:</b> Click Restore Factory-Default Settings to restore and initialize the
|
||||
factory-default settings and reboot.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BasePage>
|
||||
|
||||
<div class="modal" id="factoryReset" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Factory Reset</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Are you sure you want to delete the current configuration and reset all settings to their
|
||||
factory defaults?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @click="onFactoryResetCancel"
|
||||
data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-danger" @click="onFactoryResetPerform">Factory
|
||||
Reset!</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import {
|
||||
BIconExclamationCircleFill,
|
||||
BIconArrowLeft,
|
||||
@ -126,6 +115,7 @@ import BootstrapAlert from "@/components/BootstrapAlert.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
BIconExclamationCircleFill,
|
||||
BIconArrowLeft,
|
||||
BIconCheckCircle,
|
||||
|
||||
@ -1,68 +1,59 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>DTU Settings</h1>
|
||||
</div>
|
||||
<BasePage :title="'DTU Settings'" :isLoading="dataLoading">
|
||||
<BootstrapAlert v-model="showAlert" dismissible :variant="alertType">
|
||||
{{ alertMessage }}
|
||||
</BootstrapAlert>
|
||||
|
||||
<div class="text-center" v-if="dataLoading">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="!dataLoading">
|
||||
<form @submit="saveDtuConfig">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">DTU Configuration</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputDtuSerial" class="col-sm-2 col-form-label">Serial:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" id="inputDtuSerial" min="1" max="99999999999"
|
||||
placeholder="DTU Serial" v-model="dtuConfigList.dtu_serial" />
|
||||
</div>
|
||||
<form @submit="saveDtuConfig">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">DTU Configuration</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputDtuSerial" class="col-sm-2 col-form-label">Serial:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" id="inputDtuSerial" min="1" max="99999999999"
|
||||
placeholder="DTU Serial" v-model="dtuConfigList.dtu_serial" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputPollInterval" class="col-sm-2 col-form-label">Poll Interval:</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" id="inputPollInterval" min="1" max="86400"
|
||||
placeholder="Poll Interval in Seconds" v-model="dtuConfigList.dtu_pollinterval"
|
||||
aria-describedby="pollIntervalDescription" />
|
||||
<span class="input-group-text" id="pollIntervalDescription">seconds</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputTimezone" class="col-sm-2 col-form-label">PA Level:</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-select" v-model="dtuConfigList.dtu_palevel">
|
||||
<option v-for="palevel in palevelList" :key="palevel.key" :value="palevel.key">
|
||||
{{ palevel.value }}
|
||||
</option>
|
||||
</select>
|
||||
<div class="row mb-3">
|
||||
<label for="inputPollInterval" class="col-sm-2 col-form-label">Poll Interval:</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" id="inputPollInterval" min="1" max="86400"
|
||||
placeholder="Poll Interval in Seconds" v-model="dtuConfigList.dtu_pollinterval"
|
||||
aria-describedby="pollIntervalDescription" />
|
||||
<span class="input-group-text" id="pollIntervalDescription">seconds</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputTimezone" class="col-sm-2 col-form-label">PA Level:</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-select" v-model="dtuConfigList.dtu_palevel">
|
||||
<option v-for="palevel in palevelList" :key="palevel.key" :value="palevel.key">
|
||||
{{ palevel.value }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mb-3">Save</button>
|
||||
</form>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mb-3">Save</button>
|
||||
</form>
|
||||
</BasePage>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import BootstrapAlert from "@/components/BootstrapAlert.vue";
|
||||
import type { DtuConfig } from "@/types/DtuConfig";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
BootstrapAlert,
|
||||
},
|
||||
data() {
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>Firmware Upgrade</h1>
|
||||
</div>
|
||||
|
||||
<BasePage :title="'Firmware Upgrade'">
|
||||
<div class="position-relative" v-if="loading">
|
||||
<div class="position-absolute top-50 start-50 translate-middle">
|
||||
<div class="spinner-border" role="status">
|
||||
@ -68,11 +64,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BasePage>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import SparkMD5 from "spark-md5";
|
||||
import {
|
||||
BIconExclamationCircleFill,
|
||||
@ -83,6 +80,7 @@ import {
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
BIconExclamationCircleFill,
|
||||
BIconArrowLeft,
|
||||
BIconArrowRepeat,
|
||||
|
||||
@ -1,9 +1,5 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>Inverter Settings</h1>
|
||||
</div>
|
||||
|
||||
<BasePage :title="'Inverter Settings'" :isLoading="dataLoading">
|
||||
<BootstrapAlert v-model="showAlert" dismissible :variant="alertType">
|
||||
{{ alertMessage }}
|
||||
</BootstrapAlert>
|
||||
@ -72,80 +68,79 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BasePage>
|
||||
|
||||
<div class="modal" id="inverterEdit" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Edit Inverter</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="modal" id="inverterEdit" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Edit Inverter</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<form>
|
||||
<div class="mb-3">
|
||||
<label for="inverter-serial" class="col-form-label">Serial:</label>
|
||||
<input v-model="editInverterData.serial" type="number" id="inverter-serial"
|
||||
class="form-control" />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="inverter-name" class="col-form-label">Name:</label>
|
||||
<input v-model="editInverterData.name" type="text" id="inverter-name"
|
||||
class="form-control" maxlength="31" />
|
||||
<form>
|
||||
<div class="mb-3">
|
||||
<label for="inverter-serial" class="col-form-label">Serial:</label>
|
||||
<input v-model="editInverterData.serial" type="number" id="inverter-serial"
|
||||
class="form-control" />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="inverter-name" class="col-form-label">Name:</label>
|
||||
<input v-model="editInverterData.name" type="text" id="inverter-name" class="form-control"
|
||||
maxlength="31" />
|
||||
</div>
|
||||
|
||||
<div class="mb-3" v-for="(max, index) in editInverterData.max_power" :key="`${index}`">
|
||||
<label :for="`inverter-max_${index}`" class="col-form-label">Max power string {{ index +
|
||||
1
|
||||
}}:</label>
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" :id="`inverter-max_${index}`" min="0"
|
||||
v-model="editInverterData.max_power[index]"
|
||||
:aria-describedby="`inverter-maxDescription_${index} inverter-maxHelpText_${index}`" />
|
||||
<span class="input-group-text" :id="`inverter-maxDescription_${index}`">W</span>
|
||||
</div>
|
||||
<div :id="`inverter-maxHelpText_${index}`" class="form-text">This value is used to
|
||||
calculate the Irradiation.</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="mb-3" v-for="(max, index) in editInverterData.max_power" :key="`${index}`">
|
||||
<label :for="`inverter-max_${index}`" class="col-form-label">Max power string {{ index +
|
||||
1
|
||||
}}:</label>
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" :id="`inverter-max_${index}`" min="0"
|
||||
v-model="editInverterData.max_power[index]"
|
||||
:aria-describedby="`inverter-maxDescription_${index} inverter-maxHelpText_${index}`" />
|
||||
<span class="input-group-text" :id="`inverter-maxDescription_${index}`">W</span>
|
||||
</div>
|
||||
<div :id="`inverter-maxHelpText_${index}`" class="form-text">This value is used to
|
||||
calculate the Irradiation.</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @click="onCancel"
|
||||
data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" @click="onEditSubmit(editId)">Save
|
||||
changes</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @click="onCancel"
|
||||
data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" @click="onEditSubmit(editId)">Save
|
||||
changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal" id="inverterDelete" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Delete Inverter</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Are you sure you want to delete the inverter "{{ deleteInverterData.name }}" with serial number
|
||||
{{ deleteInverterData.serial }}?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @click="onDeleteCancel"
|
||||
data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-danger"
|
||||
@click="onDelete(deleteId.toString())">Delete</button>
|
||||
</div>
|
||||
<div class="modal" id="inverterDelete" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Delete Inverter</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Are you sure you want to delete the inverter "{{ deleteInverterData.name }}" with serial number
|
||||
{{ deleteInverterData.serial }}?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @click="onDeleteCancel"
|
||||
data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-danger" @click="onDelete(deleteId.toString())">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import {
|
||||
BIconTrash,
|
||||
BIconPencil
|
||||
@ -163,6 +158,7 @@ declare interface Inverter {
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
BootstrapAlert,
|
||||
BIconTrash,
|
||||
BIconPencil,
|
||||
@ -177,6 +173,7 @@ export default defineComponent({
|
||||
editInverterData: {} as Inverter,
|
||||
deleteInverterData: {} as Inverter,
|
||||
inverters: [] as Inverter[],
|
||||
dataLoading: true,
|
||||
alertMessage: "",
|
||||
alertType: "info",
|
||||
showAlert: false,
|
||||
@ -198,9 +195,13 @@ export default defineComponent({
|
||||
},
|
||||
methods: {
|
||||
getInverters() {
|
||||
this.dataLoading = true;
|
||||
fetch("/api/inverter/list")
|
||||
.then((response) => response.json())
|
||||
.then((data) => (this.inverters = data.inverter));
|
||||
.then((data) => {
|
||||
this.inverters = data.inverter;
|
||||
this.dataLoading = false;
|
||||
});
|
||||
},
|
||||
onSubmit() {
|
||||
const formData = new FormData();
|
||||
|
||||
@ -1,237 +1,228 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>MqTT Settings</h1>
|
||||
</div>
|
||||
<BasePage :title="'MqTT Settings'" :isLoading="dataLoading">
|
||||
<BootstrapAlert v-model="showAlert" dismissible :variant="alertType">
|
||||
{{ alertMessage }}
|
||||
</BootstrapAlert>
|
||||
|
||||
<div class="text-center" v-if="dataLoading">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
<form @submit="saveMqttConfig">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">MqTT Configuration</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-4 form-check-label" for="inputMqtt">Enable MqTT</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputMqtt"
|
||||
v-model="mqttConfigList.mqtt_enabled" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3" v-show="mqttConfigList.mqtt_enabled">
|
||||
<label class="col-sm-4 form-check-label" for="inputMqttHass">Enable Home Assistant MQTT Auto
|
||||
Discovery</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputMqttHass"
|
||||
v-model="mqttConfigList.mqtt_hass_enabled" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="!dataLoading">
|
||||
<form @submit="saveMqttConfig">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">MqTT Configuration</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-4 form-check-label" for="inputMqtt">Enable MqTT</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputMqtt"
|
||||
v-model="mqttConfigList.mqtt_enabled" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3" v-show="mqttConfigList.mqtt_enabled">
|
||||
<label class="col-sm-4 form-check-label" for="inputMqttHass">Enable Home Assistant MQTT Auto
|
||||
Discovery</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputMqttHass"
|
||||
v-model="mqttConfigList.mqtt_hass_enabled" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-5" v-show="mqttConfigList.mqtt_enabled">
|
||||
<div class="card-header text-white bg-primary">
|
||||
MqTT Broker Parameter
|
||||
</div>
|
||||
|
||||
<div class="card mt-5" v-show="mqttConfigList.mqtt_enabled">
|
||||
<div class="card-header text-white bg-primary">
|
||||
MqTT Broker Parameter
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputHostname" class="col-sm-2 col-form-label">Hostname:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputHostname" maxlength="128"
|
||||
placeholder="Hostname or IP address" v-model="mqttConfigList.mqtt_hostname" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputHostname" class="col-sm-2 col-form-label">Hostname:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputHostname" maxlength="128"
|
||||
placeholder="Hostname or IP address" v-model="mqttConfigList.mqtt_hostname" />
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputPort" class="col-sm-2 col-form-label">Port:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" id="inputPort" min="1" max="65535"
|
||||
placeholder="Port number" v-model="mqttConfigList.mqtt_port" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputUsername" class="col-sm-2 col-form-label">Username:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputUsername" maxlength="32"
|
||||
placeholder="Username, leave empty for anonymous connection"
|
||||
v-model="mqttConfigList.mqtt_username" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputPassword" class="col-sm-2 col-form-label">Password:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" id="inputPassword" maxlength="32"
|
||||
placeholder="Password, leave empty for anonymous connection"
|
||||
v-model="mqttConfigList.mqtt_password" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputTopic" class="col-sm-2 col-form-label">Base Topic:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputTopic" maxlength="32"
|
||||
placeholder="Base topic, will be prepend to all published topics (e.g. inverter/)"
|
||||
v-model="mqttConfigList.mqtt_topic" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputPublishInterval" class="col-sm-2 col-form-label">Publish Interval:</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" id="inputPublishInterval" min="5" max="86400"
|
||||
placeholder="Publish Interval in Seconds"
|
||||
v-model="mqttConfigList.mqtt_publish_interval"
|
||||
aria-describedby="publishIntervalDescription" />
|
||||
<span class="input-group-text" id="publishIntervalDescription">seconds</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputPort" class="col-sm-2 col-form-label">Port:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" id="inputPort" min="1" max="65535"
|
||||
placeholder="Port number" v-model="mqttConfigList.mqtt_port" />
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 form-check-label" for="inputRetain">Enable Retain Flag</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputRetain"
|
||||
v-model="mqttConfigList.mqtt_retain" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputUsername" class="col-sm-2 col-form-label">Username:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputUsername" maxlength="32"
|
||||
placeholder="Username, leave empty for anonymous connection"
|
||||
v-model="mqttConfigList.mqtt_username" />
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 form-check-label" for="inputTls">Enable TLS</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputTls"
|
||||
v-model="mqttConfigList.mqtt_tls" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputPassword" class="col-sm-2 col-form-label">Password:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" id="inputPassword" maxlength="32"
|
||||
placeholder="Password, leave empty for anonymous connection"
|
||||
v-model="mqttConfigList.mqtt_password" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputTopic" class="col-sm-2 col-form-label">Base Topic:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputTopic" maxlength="32"
|
||||
placeholder="Base topic, will be prepend to all published topics (e.g. inverter/)"
|
||||
v-model="mqttConfigList.mqtt_topic" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputPublishInterval" class="col-sm-2 col-form-label">Publish Interval:</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" id="inputPublishInterval" min="5"
|
||||
max="86400" placeholder="Publish Interval in Seconds"
|
||||
v-model="mqttConfigList.mqtt_publish_interval"
|
||||
aria-describedby="publishIntervalDescription" />
|
||||
<span class="input-group-text" id="publishIntervalDescription">seconds</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 form-check-label" for="inputRetain">Enable Retain Flag</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputRetain"
|
||||
v-model="mqttConfigList.mqtt_retain" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 form-check-label" for="inputTls">Enable TLS</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputTls"
|
||||
v-model="mqttConfigList.mqtt_tls" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3" v-show="mqttConfigList.mqtt_tls">
|
||||
<label for="inputCert" class="col-sm-2 col-form-label">CA-Root-Certificate (default
|
||||
Letsencrypt):</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" id="inputCert" maxlength="2048" rows="10"
|
||||
placeholder="Root CA Certificate from Letsencrypt"
|
||||
v-model="mqttConfigList.mqtt_root_ca_cert">
|
||||
<div class="row mb-3" v-show="mqttConfigList.mqtt_tls">
|
||||
<label for="inputCert" class="col-sm-2 col-form-label">CA-Root-Certificate (default
|
||||
Letsencrypt):</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" id="inputCert" maxlength="2048" rows="10"
|
||||
placeholder="Root CA Certificate from Letsencrypt"
|
||||
v-model="mqttConfigList.mqtt_root_ca_cert">
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-5" v-show="mqttConfigList.mqtt_enabled">
|
||||
<div class="card-header text-white bg-primary">LWT Parameters</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputLwtTopic" class="col-sm-2 col-form-label">LWT Topic:</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text" id="basic-addon3">{{
|
||||
mqttConfigList.mqtt_topic
|
||||
}}</span>
|
||||
<input type="text" class="form-control" id="inputLwtTopic" maxlength="32"
|
||||
placeholder="LWT topic, will be append base topic"
|
||||
v-model="mqttConfigList.mqtt_lwt_topic" aria-describedby="basic-addon3" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputLwtOnline" class="col-sm-2 col-form-label">LWT Online message:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputLwtOnline" maxlength="20"
|
||||
placeholder="Message that will be published to LWT topic when online"
|
||||
v-model="mqttConfigList.mqtt_lwt_online" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputLwtOffline" class="col-sm-2 col-form-label">LWT Offline message:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputLwtOffline" maxlength="20"
|
||||
placeholder="Message that will be published to LWT topic when offline"
|
||||
v-model="mqttConfigList.mqtt_lwt_offline" />
|
||||
<div class="card mt-5" v-show="mqttConfigList.mqtt_enabled">
|
||||
<div class="card-header text-white bg-primary">LWT Parameters</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputLwtTopic" class="col-sm-2 col-form-label">LWT Topic:</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<span class="input-group-text" id="basic-addon3">{{
|
||||
mqttConfigList.mqtt_topic
|
||||
}}</span>
|
||||
<input type="text" class="form-control" id="inputLwtTopic" maxlength="32"
|
||||
placeholder="LWT topic, will be append base topic"
|
||||
v-model="mqttConfigList.mqtt_lwt_topic" aria-describedby="basic-addon3" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-5" v-show="mqttConfigList.mqtt_enabled && mqttConfigList.mqtt_hass_enabled">
|
||||
<div class="card-header text-white bg-primary">Home Assistant MQTT Auto Discovery Parameters</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputHassTopic" class="col-sm-2 col-form-label">Prefix Topic:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputHassTopic" maxlength="32"
|
||||
placeholder="The prefix for the discovery topic"
|
||||
v-model="mqttConfigList.mqtt_hass_topic" />
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<label for="inputLwtOnline" class="col-sm-2 col-form-label">LWT Online message:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputLwtOnline" maxlength="20"
|
||||
placeholder="Message that will be published to LWT topic when online"
|
||||
v-model="mqttConfigList.mqtt_lwt_online" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 form-check-label" for="inputHassRetain">Enable Retain Flag</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputHassRetain"
|
||||
v-model="mqttConfigList.mqtt_hass_retain" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<label for="inputLwtOffline" class="col-sm-2 col-form-label">LWT Offline message:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputLwtOffline" maxlength="20"
|
||||
placeholder="Message that will be published to LWT topic when offline"
|
||||
v-model="mqttConfigList.mqtt_lwt_offline" />
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 form-check-label" for="inputHassExpire">Enable Expiration</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputHassExpire"
|
||||
v-model="mqttConfigList.mqtt_hass_expire" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 form-check-label" for="inputIndividualPanels">Individual
|
||||
Panels:</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputIndividualPanels"
|
||||
v-model="mqttConfigList.mqtt_hass_individualpanels" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary mb-3">Save</button>
|
||||
</form>
|
||||
</template>
|
||||
</div>
|
||||
<div class="card mt-5" v-show="mqttConfigList.mqtt_enabled && mqttConfigList.mqtt_hass_enabled">
|
||||
<div class="card-header text-white bg-primary">Home Assistant MQTT Auto Discovery Parameters</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputHassTopic" class="col-sm-2 col-form-label">Prefix Topic:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputHassTopic" maxlength="32"
|
||||
placeholder="The prefix for the discovery topic"
|
||||
v-model="mqttConfigList.mqtt_hass_topic" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 form-check-label" for="inputHassRetain">Enable Retain Flag</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputHassRetain"
|
||||
v-model="mqttConfigList.mqtt_hass_retain" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 form-check-label" for="inputHassExpire">Enable Expiration</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputHassExpire"
|
||||
v-model="mqttConfigList.mqtt_hass_expire" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 form-check-label" for="inputIndividualPanels">Individual
|
||||
Panels:</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputIndividualPanels"
|
||||
v-model="mqttConfigList.mqtt_hass_individualpanels" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary mb-3">Save</button>
|
||||
</form>
|
||||
</BasePage>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import BootstrapAlert from "@/components/BootstrapAlert.vue";
|
||||
import type { MqttConfig } from "@/types/MqttConfig";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
BootstrapAlert,
|
||||
},
|
||||
data() {
|
||||
|
||||
@ -1,168 +1,161 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>MqTT Info</h1>
|
||||
</div>
|
||||
|
||||
<div class="text-center" v-if="dataLoading">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
<BasePage :title="'MqTT Info'" :isLoading="dataLoading">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">Configuration Summary</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_enabled,
|
||||
'bg-success': mqttDataList.mqtt_enabled,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_enabled">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Server</th>
|
||||
<td>{{ mqttDataList.mqtt_hostname }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Port</th>
|
||||
<td>{{ mqttDataList.mqtt_port }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Username</th>
|
||||
<td>{{ mqttDataList.mqtt_username }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Base Topic</th>
|
||||
<td>{{ mqttDataList.mqtt_topic }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Publish Interval</th>
|
||||
<td>{{ mqttDataList.mqtt_publish_interval }} seconds</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Retain</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_retain,
|
||||
'bg-success': mqttDataList.mqtt_retain,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_retain">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>TLS</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_tls,
|
||||
'bg-success': mqttDataList.mqtt_tls,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_tls">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="mqttDataList.mqtt_tls">
|
||||
<th>Root CA Certifcate Info</th>
|
||||
<td>{{ mqttDataList.mqtt_root_ca_cert_info }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="!dataLoading">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">Configuration Summary</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_enabled,
|
||||
'bg-success': mqttDataList.mqtt_enabled,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_enabled">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Server</th>
|
||||
<td>{{ mqttDataList.mqtt_hostname }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Port</th>
|
||||
<td>{{ mqttDataList.mqtt_port }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Username</th>
|
||||
<td>{{ mqttDataList.mqtt_username }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Base Topic</th>
|
||||
<td>{{ mqttDataList.mqtt_topic }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Publish Interval</th>
|
||||
<td>{{ mqttDataList.mqtt_publish_interval }} seconds</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Retain</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_retain,
|
||||
'bg-success': mqttDataList.mqtt_retain,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_retain">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>TLS</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_tls,
|
||||
'bg-success': mqttDataList.mqtt_tls,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_tls">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="mqttDataList.mqtt_tls">
|
||||
<th>Root CA Certifcate Info</th>
|
||||
<td>{{ mqttDataList.mqtt_root_ca_cert_info }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="card mt-5">
|
||||
<div class="card-header text-white bg-primary">Home Assistant MQTT Auto Discovery Configuration Summary
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_hass_enabled,
|
||||
'bg-success': mqttDataList.mqtt_hass_enabled,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_hass_enabled">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Base Topic</th>
|
||||
<td>{{ mqttDataList.mqtt_hass_topic }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Retain</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_hass_retain,
|
||||
'bg-success': mqttDataList.mqtt_hass_retain,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_hass_retain">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Expire</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_hass_expire,
|
||||
'bg-success': mqttDataList.mqtt_hass_expire,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_hass_expire">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Individual Panels</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_hass_individualpanels,
|
||||
'bg-success': mqttDataList.mqtt_hass_individualpanels,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_hass_individualpanels">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-5">
|
||||
<div class="card-header text-white bg-primary">Home Assistant MQTT Auto Discovery Configuration Summary</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_hass_enabled,
|
||||
'bg-success': mqttDataList.mqtt_hass_enabled,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_hass_enabled">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Base Topic</th>
|
||||
<td>{{ mqttDataList.mqtt_hass_topic }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Retain</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_hass_retain,
|
||||
'bg-success': mqttDataList.mqtt_hass_retain,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_hass_retain">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Expire</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_hass_expire,
|
||||
'bg-success': mqttDataList.mqtt_hass_expire,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_hass_expire">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Individual Panels</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_hass_individualpanels,
|
||||
'bg-success': mqttDataList.mqtt_hass_individualpanels,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_hass_individualpanels">enabled</span>
|
||||
<span v-else>disabled</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="card mt-5">
|
||||
<div class="card-header text-white bg-primary">Runtime Summary</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Connection Status</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_connected,
|
||||
'bg-success': mqttDataList.mqtt_connected,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_connected">connected</span>
|
||||
<span v-else>disconnected</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-5">
|
||||
<div class="card-header text-white bg-primary">Runtime Summary</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Connection Status</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !mqttDataList.mqtt_connected,
|
||||
'bg-success': mqttDataList.mqtt_connected,
|
||||
}">
|
||||
<span v-if="mqttDataList.mqtt_connected">connected</span>
|
||||
<span v-else>disconnected</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</BasePage>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { MqttStatus } from '@/types/MqttStatus';
|
||||
import { defineComponent } from 'vue';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import type { MqttStatus } from '@/types/MqttStatus';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dataLoading: true,
|
||||
|
||||
@ -1,123 +1,114 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>Network Settings</h1>
|
||||
</div>
|
||||
<BasePage :title="'Network Settings'" :isLoading="dataLoading">
|
||||
<BootstrapAlert v-model="showAlert" dismissible :variant="alertType">
|
||||
{{ alertMessage }}
|
||||
</BootstrapAlert>
|
||||
|
||||
<div class="text-center" v-if="dataLoading">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
<form @submit="saveNetworkConfig">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">WiFi Configuration</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputSSID" class="col-sm-2 col-form-label">WiFi SSID:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputSSID" maxlength="32" placeholder="SSID"
|
||||
v-model="networkConfigList.ssid" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputPassword" class="col-sm-2 col-form-label">WiFi Password:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" id="inputPassword" maxlength="64"
|
||||
placeholder="PSK" v-model="networkConfigList.password" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputHostname" class="col-sm-2 col-form-label">Hostname:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputHostname" maxlength="32"
|
||||
placeholder="Hostname" v-model="networkConfigList.hostname" />
|
||||
|
||||
<div class="alert alert-secondary" role="alert">
|
||||
<b>Hint:</b> The text <span class="font-monospace">%06X</span> will be replaced
|
||||
with the last 6 digits of the ESP ChipID in hex format.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 form-check-label" for="inputDHCP">Enable DHCP</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputDHCP"
|
||||
v-model="networkConfigList.dhcp" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="!dataLoading">
|
||||
<form @submit="saveNetworkConfig">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">WiFi Configuration</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputSSID" class="col-sm-2 col-form-label">WiFi SSID:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputSSID" maxlength="32" placeholder="SSID"
|
||||
v-model="networkConfigList.ssid" />
|
||||
</div>
|
||||
<div class="card" v-show="!networkConfigList.dhcp">
|
||||
<div class="card-header text-white bg-primary">
|
||||
Static IP Configuration
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputIP" class="col-sm-2 col-form-label">IP Address:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputIP" maxlength="32" placeholder="IP address"
|
||||
v-model="networkConfigList.ipaddress" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputPassword" class="col-sm-2 col-form-label">WiFi Password:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" id="inputPassword" maxlength="64"
|
||||
placeholder="PSK" v-model="networkConfigList.password" />
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<label for="inputNetmask" class="col-sm-2 col-form-label">Netmask:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputNetmask" maxlength="32"
|
||||
placeholder="Netmask" v-model="networkConfigList.netmask" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputHostname" class="col-sm-2 col-form-label">Hostname:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputHostname" maxlength="32"
|
||||
placeholder="Hostname" v-model="networkConfigList.hostname" />
|
||||
|
||||
<div class="alert alert-secondary" role="alert">
|
||||
<b>Hint:</b> The text <span class="font-monospace">%06X</span> will be replaced
|
||||
with the last 6 digits of the ESP ChipID in hex format.
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<label for="inputGateway" class="col-sm-2 col-form-label">Default Gateway:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputGateway" maxlength="32"
|
||||
placeholder="Default Gateway" v-model="networkConfigList.gateway" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-2 form-check-label" for="inputDHCP">Enable DHCP</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputDHCP"
|
||||
v-model="networkConfigList.dhcp" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<label for="inputDNS1" class="col-sm-2 col-form-label">DNS Server 1:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputDNS1" maxlength="32"
|
||||
placeholder="DNS Server 1" v-model="networkConfigList.dns1" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputDNS2" class="col-sm-2 col-form-label">DNS Server 2:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputDNS2" maxlength="32"
|
||||
placeholder="DNS Server 2" v-model="networkConfigList.dns2" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" v-show="!networkConfigList.dhcp">
|
||||
<div class="card-header text-white bg-primary">
|
||||
Static IP Configuration
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputIP" class="col-sm-2 col-form-label">IP Address:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputIP" maxlength="32"
|
||||
placeholder="IP address" v-model="networkConfigList.ipaddress" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputNetmask" class="col-sm-2 col-form-label">Netmask:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputNetmask" maxlength="32"
|
||||
placeholder="Netmask" v-model="networkConfigList.netmask" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputGateway" class="col-sm-2 col-form-label">Default Gateway:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputGateway" maxlength="32"
|
||||
placeholder="Default Gateway" v-model="networkConfigList.gateway" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputDNS1" class="col-sm-2 col-form-label">DNS Server 1:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputDNS1" maxlength="32"
|
||||
placeholder="DNS Server 1" v-model="networkConfigList.dns1" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputDNS2" class="col-sm-2 col-form-label">DNS Server 2:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputDNS2" maxlength="32"
|
||||
placeholder="DNS Server 2" v-model="networkConfigList.dns2" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mb-3">Save</button>
|
||||
</form>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mb-3">Save</button>
|
||||
</form>
|
||||
</BasePage>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import BootstrapAlert from "@/components/BootstrapAlert.vue";
|
||||
import type { NetworkConfig } from "@/types/NetworkkConfig";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
BootstrapAlert,
|
||||
},
|
||||
data() {
|
||||
|
||||
@ -1,29 +1,19 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>Network Info</h1>
|
||||
</div>
|
||||
<div class="text-center" v-if="dataLoading">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="!dataLoading">
|
||||
<WifiStationInfo :networkStatus="networkDataList" />
|
||||
<div class="mt-5"></div>
|
||||
<WifiApInfo :networkStatus="networkDataList" />
|
||||
<div class="mt-5"></div>
|
||||
<InterfaceNetworkInfo :networkStatus="networkDataList" />
|
||||
<div class="mt-5"></div>
|
||||
<InterfaceApInfo :networkStatus="networkDataList" />
|
||||
<div class="mt-5"></div>
|
||||
</template>
|
||||
</div>
|
||||
<BasePage :title="'Network Info'" :isLoading="dataLoading">
|
||||
<WifiStationInfo :networkStatus="networkDataList" />
|
||||
<div class="mt-5"></div>
|
||||
<WifiApInfo :networkStatus="networkDataList" />
|
||||
<div class="mt-5"></div>
|
||||
<InterfaceNetworkInfo :networkStatus="networkDataList" />
|
||||
<div class="mt-5"></div>
|
||||
<InterfaceApInfo :networkStatus="networkDataList" />
|
||||
<div class="mt-5"></div>
|
||||
</BasePage>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import WifiStationInfo from "@/components/WifiStationInfo.vue";
|
||||
import WifiApInfo from "@/components/WifiApInfo.vue";
|
||||
import InterfaceNetworkInfo from "@/components/InterfaceNetworkInfo.vue";
|
||||
@ -32,6 +22,7 @@ import type { NetworkStatus } from '@/types/NetworkStatus';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
WifiStationInfo,
|
||||
WifiApInfo,
|
||||
InterfaceNetworkInfo,
|
||||
|
||||
@ -1,97 +1,85 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>NTP Settings</h1>
|
||||
</div>
|
||||
<BasePage :title="'NTP Settings'" :isLoading="dataLoading || timezoneLoading">
|
||||
<BootstrapAlert v-model="showAlert" dismissible :variant="alertType">
|
||||
{{ alertMessage }}
|
||||
</BootstrapAlert>
|
||||
|
||||
<div class="text-center" v-if="dataLoading || timezoneLoading">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="!dataLoading && !timezoneLoading">
|
||||
<form @submit="saveNtpConfig">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">NTP Configuration</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputNtpServer" class="col-sm-2 col-form-label">Time Server:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputNtpServer" maxlength="32"
|
||||
placeholder="Time Server" v-model="ntpConfigList.ntp_server" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputTimezone" class="col-sm-2 col-form-label">Timezone:</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-select" v-model="timezoneSelect">
|
||||
<option v-for="(config, name) in timezoneList" :key="name + '---' + config"
|
||||
:value="name + '---' + config">
|
||||
{{ name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputTimezoneConfig" class="col-sm-2 col-form-label">Timezone Config:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputTimezoneConfig" maxlength="32"
|
||||
placeholder="Timezone" v-model="ntpConfigList.ntp_timezone" disabled />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mb-3">Save</button>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<template v-if="!dataLoading && !timezoneLoading">
|
||||
<form @submit="saveNtpConfig">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">Manual Time Synchronization</div>
|
||||
<div class="card-header text-white bg-primary">NTP Configuration</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="currentMcuTime" class="col-sm-2 col-form-label">Current OpenDTU Time:</label>
|
||||
<label for="inputNtpServer" class="col-sm-2 col-form-label">Time Server:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="currentMcuTime" v-model="mcuTime" disabled />
|
||||
<input type="text" class="form-control" id="inputNtpServer" maxlength="32"
|
||||
placeholder="Time Server" v-model="ntpConfigList.ntp_server" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<label for="currentLocalTime" class="col-sm-2 col-form-label">Current Local Time:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="currentLocalTime" v-model="localTime"
|
||||
disabled />
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center mb-3">
|
||||
<button type="button" class="btn btn-danger" @click="setCurrentTime()"
|
||||
title="Synchronize Time">Synchronize Time
|
||||
</button>
|
||||
</div>
|
||||
<div class="alert alert-secondary" role="alert">
|
||||
<b>Hint:</b> You can use the manual time synchronization to set the current time of OpenDTU if
|
||||
no NTP server is available. But be aware, that in case of power cycle the time gets lost. Also
|
||||
the time accurancy can be very bad as it is not resynchronised regularly.
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputTimezone" class="col-sm-2 col-form-label">Timezone:</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-select" v-model="timezoneSelect">
|
||||
<option v-for="(config, name) in timezoneList" :key="name + '---' + config"
|
||||
:value="name + '---' + config">
|
||||
{{ name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputTimezoneConfig" class="col-sm-2 col-form-label">Timezone Config:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputTimezoneConfig" maxlength="32"
|
||||
placeholder="Timezone" v-model="ntpConfigList.ntp_timezone" disabled />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mb-3">Save</button>
|
||||
</form>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">Manual Time Synchronization</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="currentMcuTime" class="col-sm-2 col-form-label">Current OpenDTU Time:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="currentMcuTime" v-model="mcuTime" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<label for="currentLocalTime" class="col-sm-2 col-form-label">Current Local Time:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="currentLocalTime" v-model="localTime" disabled />
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center mb-3">
|
||||
<button type="button" class="btn btn-danger" @click="setCurrentTime()"
|
||||
title="Synchronize Time">Synchronize Time
|
||||
</button>
|
||||
</div>
|
||||
<div class="alert alert-secondary" role="alert">
|
||||
<b>Hint:</b> You can use the manual time synchronization to set the current time of OpenDTU if
|
||||
no NTP server is available. But be aware, that in case of power cycle the time gets lost. Also
|
||||
the time accurancy can be very bad as it is not resynchronised regularly.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</BasePage>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import BootstrapAlert from "@/components/BootstrapAlert.vue";
|
||||
import type { NtpConfig } from "@/types/NtpConfig";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
BootstrapAlert,
|
||||
},
|
||||
data() {
|
||||
|
||||
@ -1,75 +1,66 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>NTP Info</h1>
|
||||
</div>
|
||||
|
||||
<div class="text-center" v-if="dataLoading">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
<BasePage :title="'NTP Info'" :isLoading="dataLoading">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">Configuration Summary</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Server</th>
|
||||
<td>{{ ntpDataList.ntp_server }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Timezone</th>
|
||||
<td>{{ ntpDataList.ntp_timezone }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Timezone Description</th>
|
||||
<td>{{ ntpDataList.ntp_timezone_descr }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="!dataLoading">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">Configuration Summary</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Server</th>
|
||||
<td>{{ ntpDataList.ntp_server }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Timezone</th>
|
||||
<td>{{ ntpDataList.ntp_timezone }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Timezone Description</th>
|
||||
<td>{{ ntpDataList.ntp_timezone_descr }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="card mt-5">
|
||||
<div class="card-header text-white bg-primary">Current Time</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !ntpDataList.ntp_status,
|
||||
'bg-success': ntpDataList.ntp_status,
|
||||
}">
|
||||
<span v-if="ntpDataList.ntp_status">synced</span>
|
||||
<span v-else>not synced</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Local Time</th>
|
||||
<td>{{ ntpDataList.ntp_localtime }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-5">
|
||||
<div class="card-header text-white bg-primary">Current Time</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<td class="badge" :class="{
|
||||
'bg-danger': !ntpDataList.ntp_status,
|
||||
'bg-success': ntpDataList.ntp_status,
|
||||
}">
|
||||
<span v-if="ntpDataList.ntp_status">synced</span>
|
||||
<span v-else>not synced</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Local Time</th>
|
||||
<td>{{ ntpDataList.ntp_localtime }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</BasePage>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import type { NtpStatus } from "@/types/NtpStatus";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dataLoading: true,
|
||||
|
||||
@ -1,60 +1,51 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>Security Settings</h1>
|
||||
</div>
|
||||
<BasePage :title="'Security Settings'" :isLoading="dataLoading">
|
||||
<BootstrapAlert v-model="showAlert" dismissible :variant="alertType">
|
||||
{{ alertMessage }}
|
||||
</BootstrapAlert>
|
||||
|
||||
<div class="text-center" v-if="dataLoading">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="!dataLoading">
|
||||
<form @submit="savePasswordConfig">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">Admin password</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputPassword" class="col-sm-2 col-form-label">Password:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" id="inputPassword" maxlength="64"
|
||||
placeholder="Password" v-model="securityConfigList.password" />
|
||||
</div>
|
||||
<form @submit="savePasswordConfig">
|
||||
<div class="card">
|
||||
<div class="card-header text-white bg-primary">Admin password</div>
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<label for="inputPassword" class="col-sm-2 col-form-label">Password:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" id="inputPassword" maxlength="64"
|
||||
placeholder="Password" v-model="securityConfigList.password" />
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputPasswordRepeat" class="col-sm-2 col-form-label">Repeat Password:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" id="inputPasswordRepeat" maxlength="64"
|
||||
placeholder="Password" v-model="passwordRepeat" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-secondary" role="alert">
|
||||
<b>Hint:</b>
|
||||
The administrator password is used to connect to the device when in AP mode.
|
||||
It must be 8..64 characters.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<label for="inputPasswordRepeat" class="col-sm-2 col-form-label">Repeat Password:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" id="inputPasswordRepeat" maxlength="64"
|
||||
placeholder="Password" v-model="passwordRepeat" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-secondary" role="alert">
|
||||
<b>Hint:</b>
|
||||
The administrator password is used to connect to the device when in AP mode.
|
||||
It must be 8..64 characters.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mb-3">Save</button>
|
||||
</form>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary mb-3">Save</button>
|
||||
</form>
|
||||
</BasePage>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import BootstrapAlert from "@/components/BootstrapAlert.vue";
|
||||
import type { SecurityConfig } from '@/types/SecurityConfig';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
BootstrapAlert,
|
||||
},
|
||||
data() {
|
||||
|
||||
@ -1,30 +1,19 @@
|
||||
<template>
|
||||
<div class="container-xxl" role="main">
|
||||
<div class="page-header">
|
||||
<h1>System Info</h1>
|
||||
</div>
|
||||
|
||||
<div class="text-center" v-if="dataLoading">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template v-if="!dataLoading">
|
||||
<FirmwareInfo :systemStatus="systemDataList" />
|
||||
<div class="mt-5"></div>
|
||||
<HardwareInfo :systemStatus="systemDataList" />
|
||||
<div class="mt-5"></div>
|
||||
<MemoryInfo :systemStatus="systemDataList" />
|
||||
<div class="mt-5"></div>
|
||||
<RadioInfo :systemStatus="systemDataList" />
|
||||
<div class="mt-5"></div>
|
||||
</template>
|
||||
</div>
|
||||
<BasePage :title="'System Info'" :isLoading="dataLoading">
|
||||
<FirmwareInfo :systemStatus="systemDataList" />
|
||||
<div class="mt-5"></div>
|
||||
<HardwareInfo :systemStatus="systemDataList" />
|
||||
<div class="mt-5"></div>
|
||||
<MemoryInfo :systemStatus="systemDataList" />
|
||||
<div class="mt-5"></div>
|
||||
<RadioInfo :systemStatus="systemDataList" />
|
||||
<div class="mt-5"></div>
|
||||
</BasePage>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import HardwareInfo from "@/components/HardwareInfo.vue";
|
||||
import FirmwareInfo from "@/components/FirmwareInfo.vue";
|
||||
import MemoryInfo from "@/components/MemoryInfo.vue";
|
||||
@ -33,6 +22,7 @@ import type { SystemStatus } from '@/types/SystemStatus';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
HardwareInfo,
|
||||
FirmwareInfo,
|
||||
MemoryInfo,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user