feat: init interface before display panels (#961)

This commit is contained in:
Stefan Dej 2022-07-15 00:24:39 +02:00 committed by GitHub
parent 7536bce10d
commit 1f9d8e86be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 350 additions and 248 deletions

View File

@ -21,7 +21,7 @@
<script type="module" src="/src/main.ts"></script>
</head>
<body>
<body style="background-color: #121212">
<noscript>
<strong>
We're sorry but Mainsail doesn't work properly without JavaScript enabled. Please enable it to continue.

16
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "mainsail",
"version": "2.2.1",
"version": "2.3.0-alpha",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "mainsail",
"version": "2.2.1",
"version": "2.3.0-alpha",
"dependencies": {
"@codemirror/basic-setup": "^0.19.1",
"@codemirror/highlight": "^0.19.7",
@ -3804,9 +3804,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001363",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001363.tgz",
"integrity": "sha512-HpQhpzTGGPVMnCjIomjt+jvyUu8vNFo3TaDiZ/RcoTrlOq/5+tC8zHdsbgFB6MxmaY+jCpsH09aD80Bb4Ow3Sg==",
"version": "1.0.30001364",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001364.tgz",
"integrity": "sha512-9O0xzV3wVyX0SlegIQ6knz+okhBB5pE0PC40MNdwcipjwpxoUEHL24uJ+gG42cgklPjfO5ZjZPme9FTSN3QT2Q==",
"dev": true,
"funding": [
{
@ -12341,9 +12341,9 @@
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001363",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001363.tgz",
"integrity": "sha512-HpQhpzTGGPVMnCjIomjt+jvyUu8vNFo3TaDiZ/RcoTrlOq/5+tC8zHdsbgFB6MxmaY+jCpsH09aD80Bb4Ow3Sg==",
"version": "1.0.30001364",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001364.tgz",
"integrity": "sha512-9O0xzV3wVyX0SlegIQ6knz+okhBB5pE0PC40MNdwcipjwpxoUEHL24uJ+gG42cgklPjfO5ZjZPme9FTSN3QT2Q==",
"dev": true
},
"caseless": {

View File

@ -1,6 +1,6 @@
{
"name": "mainsail",
"version": "2.2.1",
"version": "2.3.0-alpha",
"private": true,
"decription": "a klipper web interface",
"author": {

View File

@ -1,3 +1,8 @@
{
"hostname": null,
"port": null,
"remoteMode": false,
"instances": [
]
}

View File

@ -29,22 +29,25 @@
<template>
<v-app dark :style="cssVars">
<the-sidebar></the-sidebar>
<the-topbar></the-topbar>
<v-main id="content" :style="mainStyle">
<overlay-scrollbars class="main-content-scrollbar">
<v-container id="page-container" fluid class="container px-3 px-sm-6 py-sm-6 mx-auto">
<router-view></router-view>
</v-container>
</overlay-scrollbars>
</v-main>
<the-select-printer-dialog v-if="remoteMode"></the-select-printer-dialog>
<template v-if="socketIsConnected && guiIsReady">
<the-sidebar></the-sidebar>
<the-topbar></the-topbar>
<v-main id="content" :style="mainStyle">
<overlay-scrollbars class="main-content-scrollbar">
<v-container id="page-container" fluid class="container px-3 px-sm-6 py-sm-6 mx-auto">
<router-view></router-view>
</v-container>
</overlay-scrollbars>
</v-main>
<the-update-dialog></the-update-dialog>
<the-editor></the-editor>
<the-timelapse-rendering-snackbar></the-timelapse-rendering-snackbar>
<the-fullscreen-upload></the-fullscreen-upload>
<the-upload-snackbar></the-upload-snackbar>
</template>
<the-select-printer-dialog v-else-if="remoteMode"></the-select-printer-dialog>
<the-connecting-dialog v-else></the-connecting-dialog>
<the-update-dialog></the-update-dialog>
<the-editor></the-editor>
<the-timelapse-rendering-snackbar></the-timelapse-rendering-snackbar>
<the-fullscreen-upload></the-fullscreen-upload>
<the-upload-snackbar></the-upload-snackbar>
</v-app>
</template>

View File

@ -7,20 +7,11 @@
<v-toolbar-title>
<span class="subheading">
<v-icon left>{{ mdiConnection }}</v-icon>
<template v-if="connectingFailed">
{{ $t('ConnectionDialog.Failed', { host: formatHostname }) }}
</template>
<template v-else-if="isConnecting">
{{ $t('ConnectionDialog.Connecting', { host: formatHostname }) }}
</template>
<template v-else>{{ formatHostname }}</template>
{{ titleText }}
</span>
</v-toolbar-title>
</v-toolbar>
<v-card-text v-if="isConnecting" class="pt-5">
<v-progress-linear color="white" indeterminate></v-progress-linear>
</v-card-text>
<v-card-text v-if="!isConnecting && connectingFailed" class="pt-5">
<v-card-text v-if="connectingFailed" class="pt-5">
<connection-status :moonraker="false"></connection-status>
<p class="text-center mt-3">{{ $t('ConnectionDialog.CannotConnectTo', { host: formatHostname }) }}</p>
<template v-if="counter > 2">
@ -36,6 +27,9 @@
<v-btn class="primary--text" @click="reconnect">{{ $t('ConnectionDialog.TryAgain') }}</v-btn>
</div>
</v-card-text>
<v-card-text v-else class="pt-5">
<v-progress-linear color="white" indeterminate></v-progress-linear>
</v-card-text>
</v-card>
</v-dialog>
</template>
@ -73,10 +67,6 @@ export default class TheConnectingDialog extends Mixins(BaseMixin) {
return parseInt(this.port) !== 80 && this.port !== '' ? this.hostname + ':' + this.port : this.hostname
}
get isConnected() {
return this.$store.state.socket.isConnected
}
get isConnecting() {
return this.$store.state.socket.isConnecting
}
@ -86,7 +76,15 @@ export default class TheConnectingDialog extends Mixins(BaseMixin) {
}
get showDialog() {
return !this.isConnected
return true
}
get titleText() {
if (this.connectingFailed) return this.$t('ConnectionDialog.Failed', { host: this.formatHostname })
if (this.isConnecting) return this.$t('ConnectionDialog.Connecting', { host: this.formatHostname })
if (!this.guiIsReady) return this.$t('ConnectionDialog.Initializing')
return this.formatHostname
}
reconnect() {

View File

@ -32,12 +32,12 @@
</template>
</template>
</template>
<template v-if="isConnecting">
<template v-if="isConnecting || (isConnected && !guiIsReady)">
<v-card-text>
<v-progress-linear color="primary" indeterminate></v-progress-linear>
</v-card-text>
</template>
<template v-else-if="!isConnecting && connectingFailed">
<template v-else-if="connectingFailed">
<v-card-text>
<p>
{{
@ -54,7 +54,7 @@
</div>
</v-card-text>
</template>
<template v-else-if="!isConnecting && dialogAddPrinter.bool">
<template v-else-if="dialogAddPrinter.bool">
<v-form v-model="addPrinterValid" @submit.prevent="addPrinter">
<v-card-text>
<v-row>
@ -92,7 +92,7 @@
</v-card-actions>
</v-form>
</template>
<template v-else-if="!isConnecting && dialogEditPrinter.bool">
<template v-else-if="dialogEditPrinter.bool">
<v-form v-model="editPrinterValid" @submit.prevent="updatePrinter">
<v-card-text>
<v-row>
@ -290,7 +290,7 @@ export default class TheSelectPrinterDialog extends Mixins(BaseMixin) {
}
get showDialog() {
return !this.isConnected
return !this.isConnected || (this.isConnected && !this.guiIsReady)
}
get currentUrl() {
@ -316,6 +316,7 @@ export default class TheSelectPrinterDialog extends Mixins(BaseMixin) {
if (this.dialogAddPrinter.bool) return this.$t('SelectPrinterDialog.AddPrinter')
else if (this.dialogEditPrinter.bool) return this.$t('SelectPrinterDialog.EditPrinter')
else if (this.isConnecting) return this.$t('SelectPrinterDialog.Connecting', { host: this.formatHostname })
else if (this.isConnected && !this.guiIsReady) return this.$t('ConnectionDialog.Initializing')
else if (this.connectingFailed)
return this.$t('SelectPrinterDialog.ConnectionFailed', { host: this.formatHostname })
else return this.$t('SelectPrinterDialog.SelectPrinter')

View File

@ -19,6 +19,10 @@ export default class BaseMixin extends Vue {
return this.$store.state.socket.isConnected ?? false
}
get guiIsReady() {
return this.$store.state.socket.initializationList.length === 0
}
get klippyIsConnected(): boolean {
return this.$store.state.server.klippy_connected ?? false
}

View File

@ -110,6 +110,7 @@
"CannotConnectTo": "Cannot connect to Moonraker ({host}).",
"CheckMoonrakerLog": "If this message appears repeatedly, please have a look in the log file located at:",
"Connecting": "Connecting to {host}",
"Initializing": "Initializing",
"Failed": "Connection failed",
"TryAgain": "try again"
},

View File

@ -74,32 +74,30 @@ import 'vue-resize/dist/vue-resize.css'
import VueResize from 'vue-resize'
Vue.use(VueResize)
//load config.json and init vue
fetch('/config.json')
.then((res) => res.json())
.then(async (file) => {
await store.dispatch('importConfigJson', file)
const initLoad = async () => {
//load config.json
await fetch('/config.json')
.then((res) => res.json())
.then(async (file) => {
window.console.debug('Loaded config.json')
const url = store.getters['socket/getWebsocketUrl']
Vue.use(WebSocketPlugin, {
url: url,
store: store,
await store.dispatch('importConfigJson', file)
})
.catch((_) => {
window.console.error('config.json not found or cannot be decoded!')
})
if (!store?.state?.remoteMode) Vue.$socket.connect()
const url = store.getters['socket/getWebsocketUrl']
Vue.use(WebSocketPlugin, { url, store })
if (!store?.state?.remoteMode) Vue.$socket.connect()
}
new Vue({
vuetify,
router,
store,
i18n,
render: (h) => h(App),
}).$mount('#app')
})
.catch((error) => {
const p = document.createElement('p')
const content = document.createTextNode('config.json not found or cannot be decoded!')
p.appendChild(content)
document.getElementById('app')?.append(p)
window.console.error('Error:', error)
})
initLoad()
new Vue({
vuetify,
router,
store,
i18n,
render: (h) => h(App),
}).$mount('#app')

View File

@ -24,23 +24,12 @@ export class WebSocketClient {
this.url = url
}
// eslint-disable-next-line
passToStore(eventName: string, event: any): void {
if (!eventName.startsWith('socket/')) {
return
}
this.store?.dispatch(eventName, event)
}
async connect() {
this.store?.dispatch('socket/setData', {
isConnecting: true,
})
if (this.instance) {
this.instance.close()
}
await this.instance?.close()
this.instance = new WebSocket(this.url)
this.instance.onopen = () => {
@ -48,88 +37,100 @@ export class WebSocketClient {
this.store?.dispatch('socket/onOpen', event)
}
this.instance.onclose = async (e) => {
if (!e.wasClean && this.reconnects < this.maxReconnects) {
this.reconnects++
setTimeout(() => {
this.connect()
}, this.reconnectInterval)
} else await this.store?.dispatch('socket/onClose', e)
this.instance.onclose = (e) => {
if (e.wasClean || this.reconnects >= this.maxReconnects) {
this.store?.dispatch('socket/onClose', e)
return
}
this.reconnects++
setTimeout(() => {
this.connect()
}, this.reconnectInterval)
}
this.instance.onerror = () => {
if (this.instance) this.instance.close()
this.instance?.close()
}
this.instance.onmessage = (msg) => {
if (this.store === null) return
const data = JSON.parse(msg.data)
if (this.store) {
const wait = this.getWaitById(data.id)
if (wait && wait.action !== '') {
if (data.error?.message) {
if (data.error?.message !== 'Klippy Disconnected')
window.console.error('Response Error: ' + wait.action + ' > ' + data.error.message)
} else if (wait.action) {
let result = data.result
if (result === 'ok') result = { result: result }
if (typeof result === 'string') result = { result: result }
const wait = this.getWaitById(data.id)
const preload = {}
if (wait.actionPayload) Object.assign(preload, wait.actionPayload)
Object.assign(preload, { requestParams: wait.params })
Object.assign(preload, result)
this.store?.dispatch(wait.action, preload)
}
} else this.store?.dispatch('socket/onMessage', data)
// report error messages
if (data.error?.message) {
if (data.error?.message !== 'Klippy Disconnected')
window.console.error(`Response Error: ${data.error.message} (${wait?.action ?? 'no action'})`)
if (wait) this.removeWaitById(wait.id)
if (wait?.id) this.removeWaitById(wait.id)
return
}
// pass it to socket/onMessage, if no wait exists
if (!wait) {
this.store?.dispatch('socket/onMessage', data)
return
}
// pass result to action
if (wait?.action) {
let result = data.result
if (result === 'ok') result = { result: result }
if (typeof result === 'string') result = { result: result }
const preload = {}
if (wait.actionPayload) Object.assign(preload, wait.actionPayload)
Object.assign(preload, { requestParams: wait.params })
Object.assign(preload, result)
this.store?.dispatch(wait.action, preload)
}
this.removeWaitById(wait.id)
}
}
async close() {
if (this.instance) await this.instance.close()
close(): void {
this.instance?.close()
}
getWaitById(id: number): Wait | null {
return this.waits.find((wait: Wait) => wait.id === id) ?? null
}
removeWaitById(id: number): void {
removeWaitById(id: number | null): void {
const index = this.waits.findIndex((wait: Wait) => wait.id === id)
if (index) {
const wait = this.waits[index]
if (wait.loading && this.store) {
this.store.dispatch('socket/removeLoading', { name: wait.loading })
}
if (wait.loading) this.store?.dispatch('socket/removeLoading', { name: wait.loading })
this.waits.splice(index, 1)
}
}
emit(method: string, params: Params, options: emitOptions = {}): void {
if (this.instance?.readyState === WebSocket.OPEN) {
const id = Math.floor(Math.random() * 10000) + 1
this.waits.push({
id: id,
params: params,
action: options.action ?? null,
actionPayload: options.actionPayload ?? {},
loading: options.loading ?? null,
})
if (this.instance?.readyState !== WebSocket.OPEN) return
if (options.loading && this.store) {
this.store.dispatch('socket/addLoading', { name: options.loading })
}
const id = Math.floor(Math.random() * 10000) + 1
this.waits.push({
id: id,
params: params,
action: options.action ?? null,
actionPayload: options.actionPayload ?? {},
loading: options.loading ?? null,
})
const msg = JSON.stringify({
if (options.loading) this.store?.dispatch('socket/addLoading', { name: options.loading })
this.instance.send(
JSON.stringify({
jsonrpc: '2.0',
method: method,
params: params,
id: id,
method,
params,
id,
})
this.instance.send(msg)
}
)
}
}

View File

@ -1,7 +1,6 @@
import router from '@/plugins/router'
import { ActionTree } from 'vuex'
import { ConfigJson, RootState } from './types'
import { v4 as uuidv4 } from 'uuid'
export const actions: ActionTree<RootState, RootState> = {
switchToDashboard() {
@ -31,18 +30,20 @@ export const actions: ActionTree<RootState, RootState> = {
/**
* This function will parse the config.json content and config mainsail
* @param commit - vuex commit
* @param dispatch - vuex dispatch
* @param payload - content of config.json as a object
*/
importConfigJson({ commit, dispatch }, payload: ConfigJson) {
const remoteMode = 'remoteMode' in payload ? payload.remoteMode : false
const remoteMode = payload.remoteMode ?? false
if (remoteMode) {
commit('setRemoteMode', true)
if ('instances' in payload && Array.isArray(payload.instances) && payload.instances.length) {
commit('setConfigInstances', payload.instances)
}
return
}
if (payload.hostname) commit('socket/setData', { hostname: payload.hostname })
if (payload.port) commit('socket/setData', { port: parseInt(payload.port.toString()) })
},
}

View File

@ -113,7 +113,8 @@ export const actions: ActionTree<GuiState, RootState> = {
})
}
commit('setData', payload.value)
await commit('setData', payload.value)
await dispatch('socket/removeInitModule', 'gui/init', { root: true })
},
/*

View File

@ -14,9 +14,10 @@ export const actions: ActionTree<GuiWebcamState, RootState> = {
Vue.$socket.emit('server.database.get_item', { namespace: 'webcams' }, { action: 'gui/webcams/initStore' })
},
initStore({ commit }, payload) {
commit('reset')
commit('initStore', payload)
async initStore({ commit, dispatch }, payload) {
await commit('reset')
await commit('initStore', payload)
await dispatch('socket/removeInitModule', 'gui/webcam/init', { root: true })
},
upload(_, payload) {

View File

@ -10,8 +10,15 @@ export const actions: ActionTree<PrinterState, RootState> = {
commit('socket/clearLoadings', null, { root: true })
},
init() {
init({ dispatch }) {
window.console.debug('init printer')
dispatch('reset')
dispatch('socket/addInitModule', 'printer/info', { root: true })
dispatch('socket/addInitModule', 'printer/initSubscripts', { root: true })
dispatch('socket/addInitModule', 'printer/initHelpList', { root: true })
dispatch('socket/addInitModule', 'printer/initTempHistory', { root: true })
dispatch('socket/addInitModule', 'server/gcode_store', { root: true })
Vue.$socket.emit('printer.info', {}, { action: 'printer/getInfo' })
Vue.$socket.emit('printer.objects.list', {}, { action: 'printer/initSubscripts' })
@ -19,7 +26,7 @@ export const actions: ActionTree<PrinterState, RootState> = {
Vue.$socket.emit('server.gcode_store', {}, { action: 'server/getGcodeStore' })
},
getInfo({ commit }, payload) {
getInfo({ commit, dispatch }, payload) {
commit(
'server/setData',
{
@ -34,9 +41,11 @@ export const actions: ActionTree<PrinterState, RootState> = {
software_version: payload.software_version,
cpu_info: payload.cpu_info,
})
dispatch('socket/removeInitModule', 'printer/info', { root: true })
},
initSubscripts(_, payload) {
initSubscripts({ dispatch }, payload) {
let subscripts = {}
const blocklist = ['menu']
@ -49,6 +58,8 @@ export const actions: ActionTree<PrinterState, RootState> = {
if (Object.keys(subscripts).length > 0)
Vue.$socket.emit('printer.objects.subscribe', { objects: subscripts }, { action: 'printer/getInitData' })
else Vue.$socket.emit('server.temperature_store', {}, { action: 'printer/tempHistory/init' })
dispatch('socket/removeInitModule', 'printer/initSubscripts', { root: true })
},
getInitData({ dispatch }, payload) {
@ -109,8 +120,10 @@ export const actions: ActionTree<PrinterState, RootState> = {
commit('setData', payload)
},
initHelpList({ commit }, payload) {
initHelpList({ commit, dispatch }, payload) {
commit('setHelplist', payload)
dispatch('socket/removeInitModule', 'printer/initHelpList', { root: true })
},
getEndstopStatus({ commit }, payload) {

View File

@ -357,7 +357,7 @@ export const getters: GetterTree<PrinterState, RootState> = {
let controllable = controllableFans.includes(nameSplit[0].toLowerCase())
const settings = state.configfile?.settings[key.toLowerCase()] ?? {}
const power = 'speed' in value ? value.speed : 'value' in value ? value.value : 0
const rpm = 'rpm' in value ? value.rpm : false
const rpm = 'rpm' in value ? value.rpm : null
let pwm = controllable
let scale = 1
@ -373,11 +373,11 @@ export const getters: GetterTree<PrinterState, RootState> = {
const tmp = {
name: name,
type: nameSplit[0],
power: power,
controllable: controllable,
pwm: pwm,
rpm: rpm,
scale: scale,
power,
controllable,
pwm,
rpm,
scale,
object: value,
config: settings,
off_below: undefined,

View File

@ -227,6 +227,8 @@ export const actions: ActionTree<PrinterTempHistoryState, RootState> = {
commit('setUpdateSourceInterval', updateSourceInterval)
}
dispatch('socket/removeInitModule', 'printer/initTempHistory', { root: true })
},
async updateSource({ commit, rootState, rootGetters, state }) {

View File

@ -8,6 +8,9 @@ import { initableServerComponents } from '@/store/variables'
export const actions: ActionTree<ServerState, RootState> = {
reset({ commit, dispatch }) {
dispatch('stopKlippyConnectedInterval')
dispatch('stopKlippyStateInterval')
commit('reset')
dispatch('power/reset')
dispatch('updateManager/reset')
@ -16,15 +19,24 @@ export const actions: ActionTree<ServerState, RootState> = {
async init({ dispatch }) {
window.console.debug('init Server')
await dispatch('identify')
await Vue.$socket.emit('server.info', {}, { action: 'server/initServerInfo' })
await Vue.$socket.emit('server.config', {}, { action: 'server/initServerConfig' })
await Vue.$socket.emit('machine.system_info', {}, { action: 'server/initSystemInfo' })
await Vue.$socket.emit('machine.proc_stats', {}, { action: 'server/initProcStats' })
await Vue.$socket.emit('server.database.list', { root: 'config' }, { action: 'server/checkDatabases' })
dispatch('socket/addInitModule', 'server/info', { root: true })
dispatch('socket/addInitModule', 'server/config', { root: true })
dispatch('socket/addInitModule', 'server/systemInfo', { root: true })
dispatch('socket/addInitModule', 'server/procStats', { root: true })
dispatch('socket/addInitModule', 'server/databaseList', { root: true })
dispatch('identify')
Vue.$socket.emit('server.info', {}, { action: 'server/initServerInfo' })
Vue.$socket.emit('server.config', {}, { action: 'server/initServerConfig' })
Vue.$socket.emit('machine.system_info', {}, { action: 'server/initSystemInfo' })
Vue.$socket.emit('machine.proc_stats', {}, { action: 'server/initProcStats' })
Vue.$socket.emit('server.database.list', { root: 'config' }, { action: 'server/checkDatabases' })
await dispatch('socket/removeInitModule', 'server', { root: true })
},
identify({ rootState }) {
identify({ dispatch, rootState }): void {
dispatch('socket/addInitModule', 'server/identify', { root: true })
Vue.$socket.emit(
'server.connection.identify',
{
@ -37,19 +49,25 @@ export const actions: ActionTree<ServerState, RootState> = {
)
},
setConnectionId({ commit }, payload) {
setConnectionId({ commit, dispatch }, payload) {
commit('setConnectionId', payload.connection_id)
dispatch('socket/removeInitModule', 'server/identify', { root: true })
},
checkDatabases({ dispatch, commit, rootState }, payload) {
if (payload.namespaces?.includes('mainsail')) dispatch('gui/init', null, { root: true })
else dispatch('gui/initDb', null, { root: true })
if (payload.namespaces?.includes('webcams')) dispatch('gui/webcams/init', null, { root: true })
if (payload.namespaces?.includes('mainsail')) {
dispatch('socket/addInitModule', 'gui/init', { root: true })
dispatch('gui/init', null, { root: true })
} else dispatch('gui/initDb', null, { root: true })
if (payload.namespaces?.includes('webcams')) {
dispatch('socket/addInitModule', 'gui/webcam/init', { root: true })
dispatch('gui/webcams/init', null, { root: true })
}
commit('saveDbNamespaces', payload.namespaces)
Vue.$socket.emit('server.info', {}, { action: 'server/checkKlippyConnected' })
//dispatch('printer/init', null, { root: true })
dispatch('socket/removeInitModule', 'server/databaseList', { root: true })
},
initServerInfo({ dispatch, commit }, payload) {
@ -58,13 +76,14 @@ export const actions: ActionTree<ServerState, RootState> = {
if ('failed_plugins' in payload) delete payload.failed_plugins
if (payload.components?.length) {
payload.components.forEach((component: string) => {
for (let component of payload.components) {
component = camelize(component)
if (initableServerComponents.includes(component)) {
window.console.debug('init server component: ' + component)
dispatch('socket/addInitModule', 'server/' + component + '/init', { root: true })
dispatch('server/' + component + '/init', {}, { root: true })
}
})
}
}
if (payload.registered_directories?.length) {
@ -72,22 +91,30 @@ export const actions: ActionTree<ServerState, RootState> = {
}
commit('setData', payload)
dispatch('socket/removeInitModule', 'server/info', { root: true })
},
initServerConfig({ commit }, payload) {
initServerConfig({ commit, dispatch }, payload) {
commit('setConfig', payload)
dispatch('socket/removeInitModule', 'server/config', { root: true })
},
initSystemInfo({ commit }, payload) {
initSystemInfo({ commit, dispatch }, payload) {
commit('setSystemInfo', payload.system_info)
dispatch('socket/removeInitModule', 'server/systemInfo', { root: true })
},
initProcStats({ commit }, payload) {
if (payload.throttled_state !== null) commit('setThrottledState', payload.throttled_state)
initProcStats({ commit, dispatch }, payload) {
if (payload.throttled_state !== null) {
commit('setThrottledState', payload.throttled_state)
}
if (payload.system_uptime) {
const system_boot_at = new Date(new Date().getTime() - payload.system_uptime * 1000)
commit('setSystemBootAt', system_boot_at)
}
dispatch('socket/removeInitModule', 'server/procStats', { root: true })
},
updateProcStats({ commit }, payload) {
@ -97,84 +124,88 @@ export const actions: ActionTree<ServerState, RootState> = {
if ('system_cpu_usage' in payload) commit('setCpuStats', payload.system_cpu_usage)
},
setKlippyReady({ dispatch, state }) {
if (state.klippy_connected_timer !== null) dispatch('stopKlippyConnectedInterval')
if (state.klippy_state_timer !== null) dispatch('stopKlippyStateInterval')
setKlippyReady({ dispatch }) {
dispatch('stopKlippyConnectedInterval')
dispatch('stopKlippyStateInterval')
dispatch('printer/reset', null, { root: true })
dispatch('printer/init', null, { root: true })
},
async setKlippyDisconnected({ commit, dispatch, state }) {
await commit('setKlippyDisconnected', null)
if (state.klippy_state_timer !== null) await dispatch('stopKlippyStateInterval')
await dispatch('startKlippyConnectedInterval')
setKlippyDisconnected({ commit, dispatch }) {
commit('setKlippyDisconnected', null)
dispatch('stopKlippyStateInterval')
dispatch('startKlippyConnectedInterval')
},
async setKlippyShutdown({ commit, dispatch, state }) {
await commit('setKlippyShutdown', null)
if (state.klippy_state_timer !== null) await dispatch('stopKlippyStateInterval')
await dispatch('startKlippyConnectedInterval')
setKlippyShutdown({ commit, dispatch }) {
commit('setKlippyShutdown', null)
dispatch('stopKlippyStateInterval')
dispatch('startKlippyConnectedInterval')
},
startKlippyConnectedInterval({ commit, state }) {
if (state.klippy_connected_timer === null) {
const timer = setInterval(() => {
Vue.$socket.emit('server.info', {}, { action: 'server/checkKlippyConnected' })
}, 2000)
commit('setKlippyConnectedTimer', timer)
}
if (state.klippy_connected_timer) return
const timer = setInterval(() => {
Vue.$socket.emit('server.info', {}, { action: 'server/checkKlippyConnected' })
}, 2000)
commit('setKlippyConnectedTimer', timer)
},
stopKlippyConnectedInterval({ commit, state }) {
if (state.klippy_connected_timer !== null) {
clearInterval(state.klippy_connected_timer)
commit('setKlippyConnectedTimer', null)
}
if (state.klippy_connected_timer === null) return
clearInterval(state.klippy_connected_timer)
commit('setKlippyConnectedTimer', null)
},
async checkKlippyConnected({ commit, dispatch, state }, payload) {
if (payload.klippy_connected) {
await dispatch('stopKlippyConnectedInterval')
await commit('setKlippyConnected')
dispatch('checkKlippyState', { state: payload.klippy_state, state_message: null })
} else if (!payload.klippy_connected && state.klippy_connected_timer === null)
checkKlippyConnected({ commit, dispatch, state }, payload) {
if (!payload.klippy_connected) {
dispatch('startKlippyConnectedInterval')
return
}
dispatch('stopKlippyConnectedInterval')
commit('setKlippyConnected')
dispatch('checkKlippyState', { state: payload.klippy_state, state_message: null })
},
startKlippyStateInterval({ commit, state }) {
if (state.klippy_state_timer === null) {
const timer = setInterval(() => {
Vue.$socket.emit('printer.info', {}, { action: 'server/checkKlippyState' })
}, 2000)
commit('setKlippyStateTimer', timer)
}
if (state.klippy_state_timer) return
const timer = setInterval(() => {
Vue.$socket.emit('printer.info', {}, { action: 'server/checkKlippyState' })
}, 2000)
commit('setKlippyStateTimer', timer)
},
stopKlippyStateInterval({ commit, state }) {
if (state.klippy_state_timer !== null) {
clearInterval(state.klippy_state_timer)
commit('setKlippyStateTimer', null)
}
if (state.klippy_state_timer === null) return
clearInterval(state.klippy_state_timer)
commit('setKlippyStateTimer', null)
},
checkKlippyState({ commit, dispatch, state }, payload: { state: string; state_message: string | null }) {
commit('setKlippyState', payload.state)
commit('setKlippyMessage', payload.state_message)
if (payload.state !== 'ready' && state.klippy_connected && state.klippy_state_timer === null) {
if (payload.state !== 'ready') {
dispatch('startKlippyStateInterval')
} else if (payload.state === 'ready' && state.klippy_state_timer !== null) {
dispatch('stopKlippyStateInterval')
} else if (payload.state === 'ready' && state.klippy_state_timer === null) {
dispatch('printer/init', null, { root: true })
return
}
dispatch('stopKlippyConnectedInterval')
dispatch('stopKlippyStateInterval')
dispatch('printer/init', null, { root: true })
},
getData({ commit }, payload) {
commit('setData', payload)
},
getGcodeStore({ commit, rootGetters }, payload) {
getGcodeStore({ commit, dispatch, rootGetters }, payload) {
commit('clearGcodeStore')
let events: ServerStateEvent[] = payload.gcode_store
@ -199,14 +230,11 @@ export const actions: ActionTree<ServerState, RootState> = {
return false
}
if (event.date && new Date(event.date).valueOf() < cleared_since) {
return false
}
return true
return !(event.date && new Date(event.date).valueOf() < cleared_since)
})
commit('setGcodeStore', events)
dispatch('socket/removeInitModule', 'server/gcode_store', { root: true })
},
addRootDirectory({ commit, state }, data) {
@ -215,7 +243,7 @@ export const actions: ActionTree<ServerState, RootState> = {
}
},
async addEvent({ commit, rootGetters }, payload) {
addEvent({ commit, rootGetters }, payload) {
let message = payload
let type = 'response'
@ -234,7 +262,7 @@ export const actions: ActionTree<ServerState, RootState> = {
const regex = new RegExp(filter)
if (regex.test(formatMessage)) boolImport = false
} catch {
window.console.error("Custom console filter '" + filter + "' doesn't work")
window.console.error("Custom console filter '" + filter + "' doesn't work!")
}
return boolImport
@ -243,7 +271,7 @@ export const actions: ActionTree<ServerState, RootState> = {
if (boolImport) {
if (payload.type === 'command') formatMessage = '<a class="command text--blue">' + formatMessage + '</a>'
await commit('addEvent', {
commit('addEvent', {
date: new Date(),
message: message,
formatMessage: formatMessage,

View File

@ -12,7 +12,7 @@ export const actions: ActionTree<ServerAnnouncementsState, RootState> = {
Vue.$socket.emit('server.announcements.list', {}, { action: 'server/announcements/getList' })
},
getList({ commit }, payload) {
async getList({ commit, dispatch }, payload) {
if ('entries' in payload) {
const entries = payload.entries.map((entry: any) => {
const date = new Date(entry.date * 1000)
@ -22,9 +22,11 @@ export const actions: ActionTree<ServerAnnouncementsState, RootState> = {
return { ...entry, date, date_dismissed, dismiss_wake }
})
commit('setEntries', entries)
await commit('setEntries', entries)
}
if ('feeds' in payload) commit('setFeeds', payload.feeds)
if ('feeds' in payload) await commit('setFeeds', payload.feeds)
await dispatch('socket/removeInitModule', 'server/announcements/init', { root: true })
},
getDismissed({ commit }, payload) {

View File

@ -17,9 +17,9 @@ export const actions: ActionTree<ServerHistoryState, RootState> = {
commit('setTotals', payload.job_totals)
},
getHistory({ commit, dispatch, state }, payload) {
async getHistory({ commit, dispatch, state }, payload) {
if ('requestParams' in payload && 'start' in payload.requestParams && payload.requestParams.start === 0)
commit('resetJobs')
await commit('resetJobs')
payload.jobs?.forEach((job: ServerHistoryStateJob) => {
if (state.jobs.findIndex((stateJob) => stateJob.job_id === job.job_id) === -1) commit('addJob', job)
@ -34,28 +34,31 @@ export const actions: ActionTree<ServerHistoryState, RootState> = {
},
{ action: 'server/history/getHistory' }
)
else dispatch('loadHistoryNotes')
else await dispatch('loadHistoryNotes')
},
loadHistoryNotes({ rootState }) {
loadHistoryNotes({ dispatch, rootState }) {
if (rootState.server?.dbNamespaces.includes('history_notes'))
Vue.$socket.emit(
'server.database.get_item',
{ namespace: 'history_notes' },
{ action: 'server/history/initHistoryNotes' }
)
else dispatch('socket/removeInitModule', 'server/history/init', { root: true })
},
initHistoryNotes({ commit, state }, payload) {
async initHistoryNotes({ commit, dispatch, state }, payload) {
const job_ids = Object.keys(payload.value)
job_ids.forEach((job_id: string) => {
for (const job_id of job_ids) {
const noteObject: { text: string } = payload.value[job_id]
commit('setHistoryNotes', {
await commit('setHistoryNotes', {
job_id,
text: noteObject.text,
})
})
}
await dispatch('socket/removeInitModule', 'server/history/init', { root: true })
},
getChanged({ commit }, payload) {

View File

@ -17,9 +17,11 @@ export const actions: ActionTree<ServerJobQueueState, RootState> = {
if ('queue_state' in payload) commit('setQueueState', payload.queue_state)
},
getStatus({ commit }, payload) {
if ('queued_jobs' in payload) commit('setQueuedJobs', payload.queued_jobs)
if ('queue_state' in payload) commit('setQueueState', payload.queue_state)
async getStatus({ commit, dispatch }, payload) {
if ('queued_jobs' in payload) await commit('setQueuedJobs', payload.queued_jobs)
if ('queue_state' in payload) await commit('setQueueState', payload.queue_state)
await dispatch('socket/removeInitModule', 'server/jobQueue/init', { root: true })
},
async addToQueue({ state }, filenames: string[]) {

View File

@ -12,8 +12,10 @@ export const actions: ActionTree<ServerPowerState, RootState> = {
Vue.$socket.emit('machine.device_power.devices', {}, { action: 'server/power/getDevices' })
},
getDevices({ commit }, payload) {
if (!payload.error) commit('setDevices', payload.devices)
async getDevices({ commit, dispatch }, payload) {
if (!payload.error) await commit('setDevices', payload.devices)
await dispatch('socket/removeInitModule', 'server/power/init', { root: true })
},
getStatus({ commit }, payload) {

View File

@ -13,10 +13,11 @@ export const actions: ActionTree<ServerTimelapseState, RootState> = {
Vue.$socket.emit('machine.timelapse.lastframeinfo', {}, { action: 'server/timelapse/initLastFrameinfo' })
},
initSettings({ commit }, payload) {
async initSettings({ commit, dispatch }, payload) {
if ('requestParams' in payload) delete payload.requestParams
commit('setSettings', payload)
await commit('setSettings', payload)
await dispatch('socket/removeInitModule', 'server/timelapse/init', { root: true })
},
initLastFrameinfo({ commit }, payload) {

View File

@ -12,7 +12,8 @@ export const actions: ActionTree<ServerUpdateMangerState, RootState> = {
Vue.$socket.emit('machine.update.status', {}, { action: 'server/updateManager/getStatus' })
},
getStatus({ commit }, payload) {
commit('setStatus', payload)
async getStatus({ commit, dispatch }, payload) {
await commit('setStatus', payload)
await dispatch('socket/removeInitModule', 'server/updateManager/init', { root: true })
},
}

View File

@ -6,6 +6,8 @@ import { v4 as uuidv4 } from 'uuid'
export const actions: ActionTree<SocketState, RootState> = {
reset({ commit }) {
commit('setDisconnected')
commit('clearLoadings')
commit('reset')
},
@ -54,7 +56,8 @@ export const actions: ActionTree<SocketState, RootState> = {
case 'notify_klippy_ready':
commit('server/setKlippyConnected', null, { root: true })
dispatch('printer/reset', null, { root: true })
dispatch('server/stopKlippyConnectedInterval', null, { root: true })
dispatch('server/stopKlippyStateInterval', null, { root: true })
dispatch('printer/init', null, { root: true })
break
@ -123,9 +126,7 @@ export const actions: ActionTree<SocketState, RootState> = {
break
default:
if (payload.result !== 'ok' && payload.error?.message)
window.console.error('JSON-RPC: ' + payload.error.message)
else window.console.debug(payload)
window.console.debug(payload)
}
},
@ -141,6 +142,14 @@ export const actions: ActionTree<SocketState, RootState> = {
commit('clearLoadings')
},
addInitModule({ commit }, payload: string) {
commit('addInitModule', payload)
},
removeInitModule({ commit }, payload: string) {
commit('removeInitModule', payload)
},
reportDebug(_, payload) {
window.console.log(payload)
},

View File

@ -19,6 +19,7 @@ export const getDefaultState = (): SocketState => {
isConnecting: false,
connectingFailed: false,
loadings: [],
initializationList: ['server'],
connection_id: null,
}
}

View File

@ -5,7 +5,9 @@ import { SocketState } from '@/store/socket/types'
export const mutations: MutationTree<SocketState> = {
reset(state) {
Object.assign(state, getDefaultState())
const defaults = getDefaultState()
Vue.set(state, 'initializationList', defaults.initializationList)
},
setConnected(state) {
@ -18,6 +20,7 @@ export const mutations: MutationTree<SocketState> = {
Vue.set(state, 'isConnected', false)
Vue.set(state, 'isConnecting', false)
Vue.set(state, 'connectingFailed', true)
Vue.set(state, 'connection_id', null)
},
setData(state, payload) {
@ -38,6 +41,24 @@ export const mutations: MutationTree<SocketState> = {
},
clearLoadings(state) {
if (state.loadings.length) state.loadings.splice(0, state.loadings.length)
if (state.loadings.length) Vue.set(state, 'loadings', [])
},
addInitModule(state, payload) {
const list = [...state.initializationList]
const index = list.indexOf(payload)
if (index > -1) return
list.push(payload)
Vue.set(state, 'initializationList', list)
},
removeInitModule(state, payload) {
const list = [...state.initializationList]
const index = list.indexOf(payload)
if (index === -1) return
list.splice(index, 1)
Vue.set(state, 'initializationList', list)
},
}

View File

@ -7,5 +7,6 @@ export interface SocketState {
isConnecting: boolean
connectingFailed: boolean
loadings: string[]
initializationList: string[]
connection_id: number | null
}

View File

@ -25,6 +25,8 @@ export interface RootStateDependency {
}
export interface ConfigJson {
hostname?: string | null
port?: string | number | null
remoteMode?: boolean
instances?: ConfigJsonInstance[]
}