half sidebat, half quickControl
This commit is contained in:
@@ -37,5 +37,6 @@ main {
|
|||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: auto;
|
width: auto;
|
||||||
|
min-width: 200px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
<script setup>
|
||||||
|
import IrrigationApi from '../helper/irrigationApi';
|
||||||
|
import { reactive, onBeforeUnmount, ref } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps(['areaId']);
|
||||||
|
const api = new IrrigationApi();
|
||||||
|
let minutesSlider = ref(17);
|
||||||
|
let updateInterval;
|
||||||
|
|
||||||
|
let area = reactive({
|
||||||
|
name: "",
|
||||||
|
description: "",
|
||||||
|
valveId: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
let valve = reactive({
|
||||||
|
status: false,
|
||||||
|
remainingTime: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
api.getArea(props.areaId, (areaApi) => {
|
||||||
|
area.name = areaApi.name;
|
||||||
|
area.description = areaApi.description;
|
||||||
|
area.valveId = areaApi.valveId;
|
||||||
|
setUpdateValve();
|
||||||
|
});
|
||||||
|
|
||||||
|
function setUpdateValve() {
|
||||||
|
updateInterval = setInterval(updateValve, 1000);
|
||||||
|
|
||||||
|
function updateValve() {
|
||||||
|
api.getValve(area.valveId, (valveApi) => {
|
||||||
|
valve.status = valveApi.status;
|
||||||
|
valve.remainingTime = valveApi.remainingTime;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
clearInterval(updateInterval);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="border">
|
||||||
|
<div v-if="valve.status" class="valveOn valve">
|
||||||
|
<!-- <div id="headline"> -->
|
||||||
|
<h2>{{ area.name }}</h2>
|
||||||
|
<!-- </div> -->
|
||||||
|
<p>Status: Offen</p>
|
||||||
|
<p>Verbleibenede Zeit: {{ valve.remainingTime / 60 }} Min</p>
|
||||||
|
<button>Schließen</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="!valve.status" class="valveOff valve">
|
||||||
|
<!-- <div id="headline"> -->
|
||||||
|
<h2>{{ area.name }}</h2>
|
||||||
|
<!-- </div> -->
|
||||||
|
<p>Status: Geschlossen</p>
|
||||||
|
<div class="inputDiv">
|
||||||
|
<input type="range" min="0" max="120" v-model="minutesSlider">
|
||||||
|
<label>
|
||||||
|
<input type="number" v-model="minutesSlider">
|
||||||
|
Minuten
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<button>Öffnen</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.inputDiv {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: larger;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
margin: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border {
|
||||||
|
border-width: 2px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border-style: solid;
|
||||||
|
margin: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
width: 250px;
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
font-size: large;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
width: 30%;
|
||||||
|
font-size: larger;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="range"] {
|
||||||
|
align-self: center;
|
||||||
|
width: 65%;
|
||||||
|
margin-left: 45px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .headline {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-items: center;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 80px;
|
||||||
|
} */
|
||||||
|
|
||||||
|
h2{
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
height: 80px;
|
||||||
|
line-height: 30px;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.valve {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
border-radius: 10px;
|
||||||
|
|
||||||
|
}</style>
|
||||||
@@ -6,11 +6,14 @@ import { RouterLink } from 'vue-router'
|
|||||||
<nav>
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<RouterLink to="/"> <img src="../../assets/img/menuIcon/home.svg"> Home </RouterLink>
|
<RouterLink to="/"> <img src="../../assets/img/menuIcon/home.svg"> Start </RouterLink>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<RouterLink to="/about"> <img src="../../assets/img/menuIcon/logs.svg"> About</RouterLink>
|
<RouterLink to="/about"> <img src="../../assets/img/menuIcon/logs.svg"> About</RouterLink>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<RouterLink to="/quickControl"> <img src="../../assets/img/menuIcon/logs.svg"> Control</RouterLink>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,3 +1,117 @@
|
|||||||
|
<script setup>
|
||||||
|
import IrrigationApi from '../../helper/irrigationApi';
|
||||||
|
import { reactive, onBeforeUnmount, ref } from 'vue';
|
||||||
|
|
||||||
|
const api = new IrrigationApi();
|
||||||
|
const openValves = reactive([]);
|
||||||
|
const areas = [];
|
||||||
|
|
||||||
|
let updateInterval;
|
||||||
|
let pump = {
|
||||||
|
status: "Off",
|
||||||
|
time: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
api.getAreas(areasApi => {
|
||||||
|
areasApi.forEach(areaApi => {
|
||||||
|
areas.push(areaApi);
|
||||||
|
});
|
||||||
|
updateInterval = setInterval(updateApiData, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateApiData() {
|
||||||
|
api.getValves(valves => {
|
||||||
|
valves.forEach(valve => {
|
||||||
|
if (valve.status) {
|
||||||
|
const foundValve = openValves.find(oldValve => oldValve.id === valve.id);
|
||||||
|
if(foundValve === undefined) {
|
||||||
|
openValves.push(valve);
|
||||||
|
} else {
|
||||||
|
foundValve.remainingTime = valve.remainingTime;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const foundValveIndex = openValves.findIndex(oldValve => oldValve.id === valve.id);
|
||||||
|
if (foundValveIndex >= 0) {
|
||||||
|
openValves.splice(foundValveIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAreaName(valveId) {
|
||||||
|
const area = areas.find(area => area.valveId === valveId)
|
||||||
|
return area.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
clearInterval(updateInterval);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<p>Sidebar</p>
|
<aside>
|
||||||
</template>
|
<h2>Infos</h2>
|
||||||
|
<hr />
|
||||||
|
<h3>Pumpe</h3>
|
||||||
|
<p>
|
||||||
|
Status: <br />
|
||||||
|
<b>{{ pump.status }}</b> <br />
|
||||||
|
seit <br />
|
||||||
|
<b>{{ pump.time }}</b> <br />
|
||||||
|
Minuten
|
||||||
|
</p>
|
||||||
|
<hr />
|
||||||
|
<h3>Offene <br /> Bereiche</h3>
|
||||||
|
<p v-if="openValves.length === 0">
|
||||||
|
Alles zu!
|
||||||
|
</p>
|
||||||
|
<p v-else>
|
||||||
|
<ul>
|
||||||
|
<li v-for="valve in openValves">
|
||||||
|
Bereich: {{ getAreaName(valve.id) }}
|
||||||
|
Verbleibende Zeit: {{ parseInt(valve.remainingTime) }} min
|
||||||
|
<span>Schließen!</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</p>
|
||||||
|
<hr />
|
||||||
|
</aside>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
aside {
|
||||||
|
min-width: 200px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
text-align: center;
|
||||||
|
font-size: larger;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
b {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
const address = "http://127.0.0.1:8040/api/";
|
const address = "http://garten.home.kleiax.de/api/";
|
||||||
|
|
||||||
class IrrigationApi {
|
class IrrigationApi {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -13,10 +13,6 @@ class IrrigationApi {
|
|||||||
httpGet('valve', callback);
|
httpGet('valve', callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
patchValve(id, valve, callback) {
|
|
||||||
httpPatch('valve/' + id, valve, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
getArea(id, callback) {
|
getArea(id, callback) {
|
||||||
httpGet('area/' + id, callback);
|
httpGet('area/' + id, callback);
|
||||||
@@ -26,10 +22,6 @@ class IrrigationApi {
|
|||||||
httpGet('area', callback);
|
httpGet('area', callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveAll(callback) {
|
|
||||||
httpGet('area/saveAll', callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
createArea(area, callback) {
|
createArea(area, callback) {
|
||||||
httpPost('area', area, callback);
|
httpPost('area', area, callback);
|
||||||
}
|
}
|
||||||
@@ -42,6 +34,7 @@ class IrrigationApi {
|
|||||||
httpPatch('area/' + id, area, callback);
|
httpPatch('area/' + id, area, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getAreaConf(id, callback) {
|
getAreaConf(id, callback) {
|
||||||
httpGet('areaConf/specific/' + id, callback);
|
httpGet('areaConf/specific/' + id, callback);
|
||||||
}
|
}
|
||||||
@@ -83,26 +76,6 @@ class IrrigationApi {
|
|||||||
httpPatch('irrigationEvent/' + id, irrigationEvent, callback);
|
httpPatch('irrigationEvent/' + id, irrigationEvent, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
commandManualControlPause(id, duration, callback) {
|
|
||||||
httpPost('manualControl/pause/' + id, { duration: duration}, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
commandManualControlPauseAll(callback) {
|
|
||||||
httpPost('manualControl/pauseAll/', {}, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
commandManualControlUniqueIrrigationEvent(id, duration, callback) {
|
|
||||||
httpPost('manualControl/uniqueIrrigationEvent/' + id, {duration: duration}, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
commandManualControlStop(id, callback) {
|
|
||||||
httpPost('manualControl/stop/' + id, {}, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
commandManualControlStopAll(duration, callback) {
|
|
||||||
httpPost('manualControl/stopAll/', {duration: duration}, callback);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function httpGet(apiCall, callback) {
|
function httpGet(apiCall, callback) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router';
|
import { createRouter, createWebHistory } from 'vue-router';
|
||||||
import HomeView from '../views/HomeView.vue';
|
import HomeView from '../views/HomeView.vue';
|
||||||
|
import QuickAreaControlView from '../views/QuickAreaControlView.vue'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
@@ -27,6 +28,12 @@ const router = createRouter({
|
|||||||
name: 'api',
|
name: 'api',
|
||||||
component: HomeView
|
component: HomeView
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/quickControl',
|
||||||
|
name: 'quickControl',
|
||||||
|
component: QuickAreaControlView
|
||||||
|
},
|
||||||
|
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+21
-4
@@ -1,7 +1,24 @@
|
|||||||
|
<script setup>
|
||||||
|
import IrrigationApi from '../helper/irrigationApi';
|
||||||
|
import { reactive } from 'vue'
|
||||||
|
|
||||||
|
const apiData = reactive([]);
|
||||||
|
|
||||||
|
const api = new IrrigationApi();
|
||||||
|
api.getAreas((areas) => {
|
||||||
|
areas.forEach(area => {
|
||||||
|
apiData.push(area);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<h1>Seite About</h1>
|
<div>
|
||||||
|
<h1>Seite About</h1>
|
||||||
|
<div v-for="(area, index) in apiData" :key="index">
|
||||||
|
{{ area.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<script setup>
|
||||||
|
import AreaControlCard from '../components/AreaControlCard.vue';
|
||||||
|
import IrrigationApi from '../helper/irrigationApi.js';
|
||||||
|
import { reactive } from 'vue';
|
||||||
|
|
||||||
|
const api = new IrrigationApi();
|
||||||
|
const areaData = reactive([]);
|
||||||
|
|
||||||
|
api.getAreas((areas) => {
|
||||||
|
areas.forEach(area => {
|
||||||
|
areaData.push(area);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="card">
|
||||||
|
<AreaControlCard v-for="area in areaData" :areaId="area.id"></AreaControlCard>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.card{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user