feature: update manager for klipper, moonraker, mainsail & os packages
Signed-off-by: Stefan Dej <meteyou@gmail.com>
This commit is contained in:
parent
974b7aab28
commit
339dda6455
29
src/App.vue
29
src/App.vue
@ -9,6 +9,12 @@
|
||||
#page-container {
|
||||
max-width: 1400px;
|
||||
}
|
||||
|
||||
#sidebarVersions {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<template>
|
||||
@ -52,6 +58,9 @@
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<p id="sidebarVersions" class="mb-0 text-body-2 pl-3 pb-2">
|
||||
v{{ getVersion }}<span class="" v-if="klipperVersion"> - {{ klipperVersion.substr(0, klipperVersion.lastIndexOf('-')) }}</span>
|
||||
</p>
|
||||
</v-navigation-drawer>
|
||||
|
||||
<v-app-bar app elevate-on-scroll>
|
||||
@ -76,15 +85,19 @@
|
||||
<v-card color="primary" dark >
|
||||
<v-card-text class="pt-2">
|
||||
Connecting...
|
||||
<v-progress-linear indeterminate color="white" class="mb-0"></v-progress-linear>
|
||||
<v-progress-linear indeterminate color="white" class="mb-0 mt-2"></v-progress-linear>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
||||
<v-footer app class="d-block">
|
||||
<span>v{{ getVersion }}</span>
|
||||
<span class="float-right d-none d-sm-inline" v-if="version">{{ version }}</span>
|
||||
</v-footer>
|
||||
<v-dialog :value="!updateStatus" persistent width="500">
|
||||
<v-card color="primary" dark >
|
||||
<v-card-text class="pt-2">
|
||||
{{ updateMessage}}
|
||||
<v-progress-linear indeterminate color="white" class="mb-0 mt-2"></v-progress-linear>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
@ -118,7 +131,6 @@ export default {
|
||||
...mapState({
|
||||
isConnected: state => state.socket.isConnected,
|
||||
hostname: state => state.printer.hostname,
|
||||
version: state => state.printer.software_version,
|
||||
klippy_state: state => state.server.klippy_state,
|
||||
printer_state: state => state.printer.print_stats.state,
|
||||
loadings: state => state.socket.loadings,
|
||||
@ -130,6 +142,11 @@ export default {
|
||||
boolNaviWebcam: state => state.gui.webcam.bool,
|
||||
config: state => state.printer.configfile.config,
|
||||
save_config_pending: state => state.printer.configfile.save_config_pending,
|
||||
|
||||
klipperVersion: state => state.printer.software_version,
|
||||
|
||||
updateStatus: state => state.server.updateManager.updateResponse.complete,
|
||||
updateMessage: state => state.server.updateManager.updateResponse.message,
|
||||
}),
|
||||
...mapGetters([
|
||||
'getTitle',
|
||||
|
@ -1,24 +1,99 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-card class="mt-6">
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-webcam</v-icon>Update</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-item-group class="v-btn-toggle" name="controllers">
|
||||
<v-btn small class="px-2 minwidth-0" color="primary" @click="btnSync" title="Pause print"><v-icon small>mdi-lifebuoy</v-icon></v-btn>
|
||||
</v-item-group>
|
||||
</v-toolbar>
|
||||
<v-card-text class="px-0 pt-0 pb-2 content">
|
||||
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</div>
|
||||
<v-card>
|
||||
<v-toolbar flat dense >
|
||||
<v-toolbar-title>
|
||||
<span class="subheading"><v-icon left>mdi-update</v-icon>Update</span>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-tooltip top>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-btn small class="px-2 minwidth-0" color="primary" @click="btnSync" v-bind="attrs" v-on="on"><v-icon small>mdi-refresh</v-icon></v-btn>
|
||||
</template>
|
||||
<span>Check for updates</span>
|
||||
</v-tooltip>
|
||||
</v-toolbar>
|
||||
<v-card-text class="px-0 pt-0 pb-0 content">
|
||||
<v-row v-if="'version' in klipper">
|
||||
<v-col class="pl-6 py-2 text-no-wrap">
|
||||
<strong>Klipper</strong><br />
|
||||
{{ klipper.version }}
|
||||
</v-col>
|
||||
<v-col class="pr-6 py-2 text-right">
|
||||
<v-chip
|
||||
small
|
||||
label
|
||||
outlined
|
||||
:color="getColor(klipper)"
|
||||
@click="updateKlipper"
|
||||
:disabled="is_disabled(klipper)"
|
||||
class="minwidth-0 mt-2 px-2 text-uppercase"
|
||||
><v-icon small class="mr-1">mdi-{{ getIcon(klipper) }}</v-icon>{{ getText(klipper) }}</v-chip>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<div v-if="'version' in moonraker">
|
||||
<v-divider class="mt-0 mb-0" ></v-divider>
|
||||
<v-row>
|
||||
<v-col class="pl-6 py-2 text-no-wrap">
|
||||
<strong>Moonraker</strong><br />
|
||||
{{ moonraker.version }}
|
||||
</v-col>
|
||||
<v-col class="pr-6 py-2 text-right">
|
||||
<v-chip
|
||||
small
|
||||
label
|
||||
outlined
|
||||
:color="getColor(moonraker)"
|
||||
@click="updateMoonraker"
|
||||
:disabled="is_disabled(moonraker)"
|
||||
class="minwidth-0 mt-2 px-2 text-uppercase"
|
||||
><v-icon small class="mr-1">mdi-{{ getIcon(moonraker) }}</v-icon>{{ getText(moonraker) }}</v-chip>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
<div v-if="mainsail !== false && 'version' in mainsail">
|
||||
<v-divider class="mt-0 mb-0" ></v-divider>
|
||||
<v-row>
|
||||
<v-col class="pl-6 py-2 text-no-wrap">
|
||||
<strong>Mainsail</strong><br />
|
||||
{{ 'v'+package_version }}
|
||||
<span v-if="!is_disabled(mainsail)"> > {{ mainsail.remote_version.replace('Version ', 'v') }}</span>
|
||||
</v-col>
|
||||
<v-col class="pr-6 py-2 text-right">
|
||||
<v-chip
|
||||
small
|
||||
label
|
||||
outlined
|
||||
:color="getColor(mainsail)"
|
||||
@click="updateMainsail"
|
||||
:disabled="is_disabled(mainsail)"
|
||||
class="minwidth-0 mt-2 px-2 text-uppercase"
|
||||
><v-icon small class="mr-1">mdi-{{ getIcon(mainsail) }}</v-icon>{{ getText(mainsail) }}</v-chip>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
<v-divider class="mt-0 mb-0 border-top-2" ></v-divider>
|
||||
<v-row>
|
||||
<v-col class="pl-6 py-2 text-no-wrap">
|
||||
<strong>System</strong><br />
|
||||
OS-Packages
|
||||
</v-col>
|
||||
<v-col class="pr-6 py-2 text-right">
|
||||
<v-chip
|
||||
small
|
||||
label
|
||||
outlined
|
||||
color="gray"
|
||||
@click="updateSystem"
|
||||
class="minwidth-0 mt-2 px-2 text-uppercase"
|
||||
><v-icon small class="mr-1">mdi-progress-upload</v-icon>upgrade</v-chip>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import { mapState } from 'vuex';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -30,14 +105,104 @@
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
...mapState({
|
||||
package_version: state => state.packageVersion,
|
||||
klipper: state => state.server.updateManager.klipper,
|
||||
moonraker: state => state.server.updateManager.moonraker,
|
||||
}),
|
||||
mainsail:{
|
||||
get() {
|
||||
if ('name' in this.$store.state.server.updateManager.client)
|
||||
return this.$store.state.server.updateManager.client
|
||||
|
||||
])
|
||||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
btnSync() {
|
||||
this.$socket.sendObj('machine.update.status', { refresh: true }, 'server/updateManager/getStatus')
|
||||
},
|
||||
getColor(object) {
|
||||
if (typeof object === 'object' && object !== false) {
|
||||
if ('is_valid' in object && !object.is_valid) return 'red'
|
||||
if ('is_dirty' in object && object.is_dirty) return 'red'
|
||||
|
||||
}
|
||||
if ('current_hash' in object && 'remote_hash' in object && object.current_hash !== object.remote_hash) return 'primary'
|
||||
|
||||
if ('name' in object && object.name === "mainsail") {
|
||||
let remote_version = object.remote_version.split(' ')
|
||||
remote_version = (remote_version.length > 1) ? remote_version[1] : remote_version[0]
|
||||
|
||||
if (this.package_version !== remote_version) return 'primary'
|
||||
}
|
||||
|
||||
return 'green'
|
||||
}
|
||||
|
||||
return 'red'
|
||||
},
|
||||
getText(object) {
|
||||
if (typeof object === 'object' && object !== false) {
|
||||
if ('is_valid' in object && !object.is_valid) return 'invalid'
|
||||
if ('is_dirty' in object && object.is_dirty) return 'dirty'
|
||||
|
||||
if ('current_hash' in object && 'remote_hash' in object && object.current_hash !== object.remote_hash) return 'update'
|
||||
|
||||
if ('name' in object && object.name === "mainsail") {
|
||||
let remote_version = object.remote_version.split(' ')
|
||||
remote_version = (remote_version.length > 1) ? remote_version[1] : remote_version[0]
|
||||
|
||||
if (this.package_version !== remote_version) return 'update'
|
||||
}
|
||||
|
||||
return 'up-to-date'
|
||||
}
|
||||
|
||||
return 'ERROR'
|
||||
},
|
||||
getIcon(object) {
|
||||
if (typeof object === 'object' && object !== false) {
|
||||
if ('is_valid' in object && !object.is_valid) return 'alert-circle'
|
||||
if ('is_dirty' in object && object.is_dirty) return 'alert-circle'
|
||||
|
||||
if ('current_hash' in object && 'remote_hash' in object && object.current_hash !== object.remote_hash) return 'progress-upload'
|
||||
|
||||
if ('name' in object && object.name === "mainsail") {
|
||||
let remote_version = object.remote_version.split(' ')
|
||||
remote_version = (remote_version.length > 1) ? remote_version[1] : remote_version[0]
|
||||
|
||||
if (this.package_version !== remote_version) return 'progress-upload'
|
||||
}
|
||||
|
||||
return 'check'
|
||||
}
|
||||
|
||||
return 'ERROR'
|
||||
},
|
||||
is_disabled(object) {
|
||||
if (typeof object === 'object' && object !== false) {
|
||||
if ('current_hash' in object && 'remote_hash' in object && object.current_hash !== object.remote_hash) return false
|
||||
|
||||
if ('name' in object && object.name === "mainsail") {
|
||||
if ('v'+this.package_version !== object.remote_version.replace('Version ', 'v')) return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
updateKlipper() {
|
||||
this.$socket.sendObj('machine.update.klipper', { })
|
||||
},
|
||||
updateMoonraker() {
|
||||
this.$socket.sendObj('machine.update.moonraker', { })
|
||||
},
|
||||
updateMainsail() {
|
||||
this.$socket.sendObj('machine.update.client', { })
|
||||
},
|
||||
updateSystem() {
|
||||
this.$socket.sendObj('machine.update.system', { })
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
@ -3,7 +3,6 @@
|
||||
<v-row>
|
||||
<v-col class="col-12 col-md-6 col-lg-4">
|
||||
<settings-general-panel></settings-general-panel>
|
||||
<settings-update-panel></settings-update-panel>
|
||||
<settings-webcam-panel class="mt-6"></settings-webcam-panel>
|
||||
</v-col>
|
||||
<v-col class="col-12 col-md-6 col-lg-4">
|
||||
|
@ -21,7 +21,8 @@
|
||||
<settings-runout-panel></settings-runout-panel>
|
||||
</v-col>
|
||||
<v-col :class="(klippy_state !== 'ready' ? 'col-md-12' : 'col-md-6')">
|
||||
<settings-logfiles-panel></settings-logfiles-panel>
|
||||
<settings-update-panel v-if="updateManager"></settings-update-panel>
|
||||
<settings-logfiles-panel :class="updateManager ? 'mt-6' : ''"></settings-logfiles-panel>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
@ -41,6 +42,11 @@
|
||||
...mapState({
|
||||
klippy_state: state => state.server.klippy_state,
|
||||
}),
|
||||
updateManager:{
|
||||
get() {
|
||||
return this.$store.state.server.plugins.includes('update_manager')
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
export default {
|
||||
reportError(state, payload) {
|
||||
window.console.log(payload)
|
||||
window.console.error(payload)
|
||||
},
|
||||
|
||||
void() {
|
||||
|
@ -3,10 +3,11 @@ import { getDefaultState } from './index'
|
||||
|
||||
export default {
|
||||
reset(state) {
|
||||
window.console.log("printer/reset");
|
||||
Object.assign(state, getDefaultState())
|
||||
|
||||
this.dispatch('socket/clearLoadings', null, { root: true })
|
||||
if (this.state.server.plugins.includes("update_manager"))
|
||||
Vue.prototype.$socket.sendObj('machine.update.status', { refresh: false }, 'server/updateManager/getStatus')
|
||||
},
|
||||
|
||||
setData(state, payload) {
|
||||
|
@ -5,27 +5,34 @@ export default {
|
||||
commit('reset')
|
||||
},
|
||||
|
||||
init({ dispatch }) {
|
||||
init({ dispatch, state }) {
|
||||
Vue.prototype.$socket.sendObj('server.info', {}, 'server/getInfo')
|
||||
Vue.prototype.$socket.sendObj('server.gcode_store', {}, 'server/getGcodeStore')
|
||||
Vue.prototype.$socket.sendObj('server.files.get_directory', { path: 'config' }, 'files/getDirectory')
|
||||
Vue.prototype.$socket.sendObj('server.files.get_directory', { path: 'config_examples' }, 'files/getDirectory')
|
||||
|
||||
if (state.plugins.length > 0 && state.plugins.includes("update_manager"))
|
||||
Vue.prototype.$socket.sendObj('machine.update.status', { refresh: false }, 'server/updateManager/getStatus')
|
||||
|
||||
dispatch('printer/init', null, { root: true })
|
||||
},
|
||||
|
||||
getInfo({ commit, state }, payload) {
|
||||
if (
|
||||
payload.plugins.includes("power") !== false &&
|
||||
state.plugins.length === 0
|
||||
) Vue.prototype.$socket.sendObj('machine.device_power.devices', {}, 'server/power/getDevices');
|
||||
|
||||
if (state.plugins.length === 0) {
|
||||
if (payload.plugins.includes("power") !== false)
|
||||
Vue.prototype.$socket.sendObj('machine.device_power.devices', {}, 'server/power/getDevices')
|
||||
|
||||
if (payload.plugins.includes("update_manager") !== false)
|
||||
Vue.prototype.$socket.sendObj('machine.update.status', {}, 'server/updateManager/getStatus')
|
||||
}
|
||||
|
||||
commit('setData', payload)
|
||||
|
||||
if (!payload.klippy_connected) {
|
||||
setTimeout(function(){
|
||||
Vue.prototype.$socket.sendObj('server.info', {}, 'server/getInfo');
|
||||
}, 1000);
|
||||
Vue.prototype.$socket.sendObj('server.info', {}, 'server/getInfo')
|
||||
}, 1000)
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -4,6 +4,7 @@ import getters from './getters'
|
||||
|
||||
// import modules
|
||||
import power from './power'
|
||||
import updateManager from './updateManager'
|
||||
|
||||
// create getDefaultState
|
||||
export function getDefaultState() {
|
||||
@ -26,6 +27,7 @@ export default {
|
||||
actions,
|
||||
mutations,
|
||||
modules: {
|
||||
power
|
||||
power,
|
||||
updateManager,
|
||||
}
|
||||
}
|
9
src/store/server/updateManager/actions.js
Normal file
9
src/store/server/updateManager/actions.js
Normal file
@ -0,0 +1,9 @@
|
||||
export default {
|
||||
reset({ commit }) {
|
||||
commit('reset')
|
||||
},
|
||||
|
||||
getStatus({ commit }, payload) {
|
||||
commit('setStatus', payload)
|
||||
},
|
||||
}
|
3
src/store/server/updateManager/getters.js
Normal file
3
src/store/server/updateManager/getters.js
Normal file
@ -0,0 +1,3 @@
|
||||
export default {
|
||||
|
||||
}
|
27
src/store/server/updateManager/index.js
Normal file
27
src/store/server/updateManager/index.js
Normal file
@ -0,0 +1,27 @@
|
||||
import actions from './actions'
|
||||
import mutations from './mutations'
|
||||
import getters from './getters'
|
||||
|
||||
export function getDefaultState() {
|
||||
return {
|
||||
moonraker: {},
|
||||
klipper: {},
|
||||
client: {},
|
||||
updateResponse: {
|
||||
application: "",
|
||||
complete: true,
|
||||
message: "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initial state
|
||||
const state = getDefaultState()
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
actions,
|
||||
mutations
|
||||
}
|
26
src/store/server/updateManager/mutations.js
Normal file
26
src/store/server/updateManager/mutations.js
Normal file
@ -0,0 +1,26 @@
|
||||
import { getDefaultState } from './index'
|
||||
import Vue from "vue";
|
||||
|
||||
export default {
|
||||
reset(state) {
|
||||
Object.assign(state, getDefaultState())
|
||||
},
|
||||
|
||||
setStatus(state, payload) {
|
||||
if ('version_info' in payload) {
|
||||
Object.entries(payload.version_info).forEach(([key, value]) => {
|
||||
Vue.set(state, key, value)
|
||||
})
|
||||
}
|
||||
|
||||
if ('busy' in payload && payload.busy === false) {
|
||||
Vue.set(state.updateResponse, 'complete', true)
|
||||
}
|
||||
},
|
||||
|
||||
setUpdateResponse(state, payload) {
|
||||
Vue.set(state, 'updateResponse', payload)
|
||||
|
||||
if (payload.application === "client" && payload.complete) window.location.reload(true)
|
||||
}
|
||||
}
|
@ -70,6 +70,10 @@ export default {
|
||||
commit('server/power/setStatus', payload.params[0], { root: true })
|
||||
break
|
||||
|
||||
case 'notify_update_response':
|
||||
commit('server/updateManager/setUpdateResponse', payload.params[0], { root: true })
|
||||
break
|
||||
|
||||
default:
|
||||
if (payload.result !== "ok") {
|
||||
if (
|
||||
@ -88,5 +92,10 @@ export default {
|
||||
|
||||
clearLoadings({ commit }) {
|
||||
commit('clearLoadings')
|
||||
}
|
||||
},
|
||||
|
||||
reportDebug({ commit }, payload) {
|
||||
window.console.log(payload)
|
||||
commit('void', {}, { root: true })
|
||||
},
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user