Adding users controls on the frontend quit/shutdown/reboot
This commit is contained in:
parent
2ea8ef49e8
commit
9ed61f201e
@ -35,6 +35,18 @@
|
||||
<input type="checkbox" @change="switch_config('frontend', 'virtual_keyboard')" v-model="config.frontend.virtual_keyboard">
|
||||
<i class="form-icon"></i> Use virtual keyboard (for touch screen)
|
||||
</label>
|
||||
<label class="form-switch">
|
||||
<input type="checkbox" @change="switch_config('frontend', 'reboot_option')" v-model="config.frontend.reboot_option">
|
||||
<i class="form-icon"></i> Allow the end-user to reboot the device from the interface.
|
||||
</label>
|
||||
<label class="form-switch">
|
||||
<input type="checkbox" @change="switch_config('frontend', 'shutdown_option')" v-model="config.frontend.shutdown_option">
|
||||
<i class="form-icon"></i> Allow the end-user to shutdown the device from the interface.
|
||||
</label>
|
||||
<label class="form-switch">
|
||||
<input type="checkbox" @change="switch_config('frontend', 'quit_option')" v-model="config.frontend.quit_option">
|
||||
<i class="form-icon"></i> Allow the end-user to quit the interface
|
||||
</label>
|
||||
<label class="form-switch">
|
||||
<input type="checkbox" @change="switch_config('frontend', 'hide_mouse')" v-model="config.frontend.hide_mouse">
|
||||
<i class="form-icon"></i> Hide mouse (for touch screen)
|
||||
|
@ -1,9 +1,12 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<div class="wrapper">
|
||||
<Controls />
|
||||
<transition name="fade" mode="out-in">
|
||||
<router-view />
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@ -26,5 +29,13 @@
|
||||
|
||||
<script>
|
||||
document.title = 'TinyCheck Frontend'
|
||||
import Controls from "@/components/Controls.vue"
|
||||
|
||||
export default {
|
||||
name: 'app',
|
||||
components: {
|
||||
Controls
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -240,6 +240,11 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
width:100%;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.center {
|
||||
width: fit-content;
|
||||
position: relative;
|
||||
@ -634,3 +639,44 @@ ul {
|
||||
opacity:1;
|
||||
}
|
||||
}
|
||||
|
||||
.controls {
|
||||
position:fixed;
|
||||
right:0;
|
||||
top:0;
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
.quit-icon {
|
||||
background-image: url("data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9JzMwMHB4JyB3aWR0aD0nMzAwcHgnICBmaWxsPSIjMjUyNTI1IiB4bWxuczp4PSJodHRwOi8vbnMuYWRvYmUuY29tL0V4dGVuc2liaWxpdHkvMS4wLyIgeG1sbnM6aT0iaHR0cDovL25zLmFkb2JlLmNvbS9BZG9iZUlsbHVzdHJhdG9yLzEwLjAvIiB4bWxuczpncmFwaD0iaHR0cDovL25zLmFkb2JlLmNvbS9HcmFwaHMvMS4wLyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEwMCAxMDA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHJlcXVpcmVkRXh0ZW5zaW9ucz0iaHR0cDovL25zLmFkb2JlLmNvbS9BZG9iZUlsbHVzdHJhdG9yLzEwLjAvIiB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIj48L2ZvcmVpZ25PYmplY3Q+PGcgaTpleHRyYW5lb3VzPSJzZWxmIj48cGF0aCBkPSJNNTAsMi41QzIzLjgsMi41LDIuNSwyMy44LDIuNSw1MFMyMy44LDk3LjUsNTAsOTcuNVM5Ny41LDc2LjIsOTcuNSw1MFM3Ni4yLDIuNSw1MCwyLjV6IE03My40LDY2LjMgICAgYzAuNywwLjcsMC43LDEuNywwLDIuNGwtNC44LDQuOGMtMC43LDAuNy0xLjcsMC43LTIuNCwwTDUwLDU3LjJMMzMuNyw3My40Yy0wLjcsMC43LTEuNywwLjctMi40LDBsLTQuOC00LjggICAgYy0wLjctMC43LTAuNy0xLjcsMC0yLjRMNDIuOCw1MEwyNi42LDMzLjdjLTAuNy0wLjctMC43LTEuNywwLTIuNGw0LjgtNC44YzAuNy0wLjcsMS43LTAuNywyLjQsMEw1MCw0Mi44bDE2LjMtMTYuMyAgICBjMC43LTAuNywxLjctMC43LDIuNCwwbDQuOCw0LjhjMC43LDAuNywwLjcsMS43LDAsMi40TDU3LjIsNTBMNzMuNCw2Ni4zeiI+PC9wYXRoPjwvZz48L3N3aXRjaD48L3N2Zz4=");
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: block;
|
||||
margin-right: 10px;
|
||||
margin-top: 10px;
|
||||
background-size: cover;
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.off-icon {
|
||||
background-image: url("data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9JzMwMHB4JyB3aWR0aD0nMzAwcHgnICBmaWxsPSIjMmIyYjJiIiB4bWxuczp4PSJodHRwOi8vbnMuYWRvYmUuY29tL0V4dGVuc2liaWxpdHkvMS4wLyIgeG1sbnM6aT0iaHR0cDovL25zLmFkb2JlLmNvbS9BZG9iZUlsbHVzdHJhdG9yLzEwLjAvIiB4bWxuczpncmFwaD0iaHR0cDovL25zLmFkb2JlLmNvbS9HcmFwaHMvMS4wLyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDEwMCAxMDAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEwMCAxMDA7IiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3dpdGNoPjxmb3JlaWduT2JqZWN0IHJlcXVpcmVkRXh0ZW5zaW9ucz0iaHR0cDovL25zLmFkb2JlLmNvbS9BZG9iZUlsbHVzdHJhdG9yLzEwLjAvIiB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIj48L2ZvcmVpZ25PYmplY3Q+PGcgaTpleHRyYW5lb3VzPSJzZWxmIj48cGF0aCBkPSJNNTAsMi41TDUwLDIuNUMyMy44LDIuNSwyLjUsMjMuOCwyLjUsNTBsMCwwYzAsMjYuMiwyMS4zLDQ3LjUsNDcuNSw0Ny41bDAsMGMyNi4yLDAsNDcuNS0yMS4zLDQ3LjUtNDcuNWwwLDAgICAgQzk3LjUsMjMuOCw3Ni4yLDIuNSw1MCwyLjV6IE00NS43LDI0LjJjMC0yLjQsMS45LTQuMyw0LjMtNC4zczQuMywxLjksNC4zLDQuM3YyMS42YzAsMi40LTEuOSw0LjMtNC4zLDQuM3MtNC4zLTEuOS00LjMtNC4zVjI0LjIgICAgeiBNNTAsNzguNGMtMTUuMiwwLTI3LjYtMTIuNC0yNy42LTI3LjZjMC04LjcsNC0xNi43LDExLTIyYzEuOS0xLjQsNC42LTEsNiwwLjhjMS40LDEuOSwxLDQuNi0wLjgsNmMtNC44LDMuNi03LjYsOS4yLTcuNiwxNS4yICAgIGMwLDEwLjUsOC41LDE5LjEsMTkuMSwxOS4xYzEwLjUsMCwxOS4xLTguNSwxOS4xLTE5LjFjMC02LTIuOC0xMS41LTcuNi0xNS4yYy0xLjktMS40LTIuMy00LjEtMC44LTZjMS40LTEuOSw0LjEtMi4zLDYtMC44ICAgIGM3LDUuMywxMSwxMy4zLDExLDIyQzc3LjYsNjYsNjUuMiw3OC40LDUwLDc4LjR6Ij48L3BhdGg+PC9nPjwvc3dpdGNoPjwvc3ZnPg==");
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: block;
|
||||
margin-right: 10px;
|
||||
margin-top: 10px;
|
||||
background-size: cover;
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.off-icon:hover {
|
||||
opacity: 0.3;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.quit-icon:hover {
|
||||
opacity: 0.3;
|
||||
cursor:pointer;
|
||||
}
|
52
app/frontend/src/components/Controls.vue
Normal file
52
app/frontend/src/components/Controls.vue
Normal file
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div class="controls">
|
||||
<i class="off-icon" v-on:click="action('shutdown')" v-if="off_available && off_display"></i>
|
||||
<i class="quit-icon" v-on:click="action('quit')" v-if="quit_available && quit_display"></i>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
export default {
|
||||
name: 'Controls',
|
||||
data: function (){
|
||||
return {
|
||||
off_available : false,
|
||||
off_display : false,
|
||||
quit_available: false,
|
||||
quit_display : false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
action: function(action) {
|
||||
axios.get(`/api/misc/${action}`, { timeout: 30000 })
|
||||
.then(response => {
|
||||
if(response.data.status)
|
||||
console.log(`Let's ${action}`)
|
||||
})
|
||||
.catch(error => { console.log(error) });
|
||||
},
|
||||
load_config: function() {
|
||||
axios.get(`/api/misc/config`, { timeout: 60000 })
|
||||
.then(response => {
|
||||
this.quit_available = response.data.quit_option
|
||||
this.off_available = response.data.shutdown_option
|
||||
})
|
||||
.catch(error => { console.log(error) });
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route (){
|
||||
if ( ["capture", "report"].includes(this.$router.currentRoute.name) || screen.height != window.innerHeight ){
|
||||
this.off_display = false;
|
||||
this.quit_display = false;
|
||||
} else {
|
||||
this.off_display = (this.off_available)? true : false;
|
||||
this.quit_display = (this.quit_available)? true : false;
|
||||
}
|
||||
}
|
||||
},
|
||||
created: function() {
|
||||
this.load_config()
|
||||
},
|
||||
}
|
||||
</script>
|
@ -27,12 +27,11 @@
|
||||
</div>
|
||||
<div v-else>
|
||||
<p>
|
||||
<strong>Unfortunately, we got some issues.</strong>
|
||||
<strong>Unfortunately, we got some issues <br />during the AP creation.</strong>
|
||||
<br /><br />
|
||||
Please verify that you've two Wifi interfaces on your device<br />
|
||||
and restart it by clicking on the button below.<br />
|
||||
Please verify that you've two WiFi interfaces on your device<br /> and try again by restarting it.<br /><br />
|
||||
</p>
|
||||
<button class="btn" v-on:click="reboot()">Reboot the device</button>
|
||||
<button v-if="reboot_option" class="btn" v-on:click="reboot()">Restart the device</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -53,14 +52,15 @@ export default {
|
||||
capture_token: false,
|
||||
capture_start: false,
|
||||
interval: false,
|
||||
error: false
|
||||
error: false,
|
||||
reboot_option: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
generate_ap: function() {
|
||||
clearInterval(this.interval)
|
||||
this.ssid_name = false
|
||||
axios.get(`/api/network/ap/start`, { timeout: 70000 })
|
||||
axios.get(`/api/network/ap/start`, { timeout: 30000 })
|
||||
.then(response => (this.show_ap(response.data)))
|
||||
},
|
||||
show_ap: function(data) {
|
||||
@ -109,9 +109,19 @@ export default {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
load_config: function() {
|
||||
axios.get(`/api/misc/config`, { timeout: 60000 })
|
||||
.then(response => {
|
||||
this.reboot_option = response.data.reboot_option
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
});
|
||||
},
|
||||
},
|
||||
created: function() {
|
||||
this.load_config()
|
||||
this.generate_ap();
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,35 @@ def api_reboot():
|
||||
"""
|
||||
Reboot the device
|
||||
"""
|
||||
sp.Popen("reboot", shell=True)
|
||||
if read_config(("frontend", "reboot_option")):
|
||||
sp.Popen("shutdown -r now", shell=True)
|
||||
return jsonify({"mesage": "Let's reboot."})
|
||||
else:
|
||||
return jsonify({"message": "Option disabled", "status": False})
|
||||
|
||||
|
||||
@misc_bp.route("/quit", methods=["GET"])
|
||||
def api_quit():
|
||||
"""
|
||||
Quit the interface (Chromium browser)
|
||||
"""
|
||||
if read_config(("frontend", "quit_option")):
|
||||
sp.Popen('pkill -INT -f "chromium-browser"', shell=True)
|
||||
return jsonify({"message": "Let's quit", "status": True})
|
||||
else:
|
||||
return jsonify({"message": "Option disabled", "status": False})
|
||||
|
||||
|
||||
@misc_bp.route("/shutdown", methods=["GET"])
|
||||
def api_shutdown():
|
||||
"""
|
||||
Reboot the device
|
||||
"""
|
||||
if read_config(("frontend", "shutdown_option")):
|
||||
sp.Popen("shutdown -h now", shell=True)
|
||||
return jsonify({"message": "Let's shutdown", "status": True})
|
||||
else:
|
||||
return jsonify({"message": "Option disabled", "status": False})
|
||||
|
||||
|
||||
@misc_bp.route("/config", methods=["GET"])
|
||||
@ -27,4 +54,7 @@ def get_config():
|
||||
"hide_mouse": read_config(("frontend", "hide_mouse")),
|
||||
"download_links": read_config(("frontend", "download_links")),
|
||||
"sparklines": read_config(("frontend", "sparklines")),
|
||||
"quit_option": read_config(("frontend", "quit_option")),
|
||||
"shutdown_option": read_config(("frontend", "shutdown_option")),
|
||||
"reboot_option": read_config(("frontend", "reboot_option"))
|
||||
})
|
||||
|
13
update.sh
13
update.sh
@ -45,5 +45,18 @@ elif [ $PWD = "/tmp/tinycheck" ]; then
|
||||
service tinycheck-frontend restart
|
||||
service tinycheck-watchers restart
|
||||
|
||||
# Updating configuration with new key-val pairs.
|
||||
if ! grep -q reboot_option /usr/share/tinycheck/config.yaml; then
|
||||
sed -i 's/frontend:/frontend:\n reboot_option: true/g' /usr/share/tinycheck/config.yaml
|
||||
fi
|
||||
|
||||
if ! grep -q shutdown_option /usr/share/tinycheck/config.yaml; then
|
||||
sed -i 's/frontend:/frontend:\n shutdown_option: true/g' /usr/share/tinycheck/config.yaml
|
||||
fi
|
||||
|
||||
if ! grep -q quit_option /usr/share/tinycheck/config.yaml; then
|
||||
sed -i 's/frontend:/frontend:\n quit_option: true/g' /usr/share/tinycheck/config.yaml
|
||||
fi
|
||||
|
||||
echo "[+] TinyCheck updated!"
|
||||
fi
|
Loading…
Reference in New Issue
Block a user