feat(Console): Change from Helplist to Printer.Gcode (#2033)

This commit is contained in:
Stefan Dej 2024-11-06 20:14:53 +01:00 committed by GitHub
parent 58d4a2a9fe
commit 66160594d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 129 additions and 115 deletions

View File

@ -33,42 +33,24 @@
<v-col>
<v-text-field
v-model="cmdListSearch"
label="Search"
:label="$t('Console.Search')"
outlined
hide-details
clearable
dense></v-text-field>
dense />
</v-col>
</v-row>
</v-card-title>
<v-divider></v-divider>
<v-divider />
<overlay-scrollbars class="command-help-content" :class="isMobile ? 'mobileHeight' : 'height300'">
<v-card-text class="pt-0">
<v-row>
<v-col>
<v-list>
<v-list-item
v-for="cmd of helplistFiltered"
:key="cmd.commandLow"
class="px-0"
two-line>
<v-list-item-content class="px-0">
<v-list-item-title
class="primary--text font-weight-bold cursor-pointer"
@click="
$emit('onCommand', cmd.command)
isOpen = false
">
{{ cmd.command }}
</v-list-item-title>
<v-list-item-subtitle class="text-wrap">
{{ cmd.description }}
</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</v-list>
</v-col>
</v-row>
<v-list>
<command-help-modal-entry
v-for="command of helplistFiltered"
:key="command"
:command="command"
@click-on-command="onCommand" />
</v-list>
</v-card-text>
</overlay-scrollbars>
</panel>
@ -77,15 +59,15 @@
</template>
<script lang="ts">
import BaseMixin from './mixins/base'
import { CommandHelp } from '@/store/printer/types'
import BaseMixin from '@/components/mixins/base'
import { Mixins, Prop, Watch } from 'vue-property-decorator'
import Component from 'vue-class-component'
import Panel from '@/components/ui/Panel.vue'
import { mdiHelp, mdiCloseThick } from '@mdi/js'
import CommandHelpModalEntry from '@/components/console/CommandHelpModalEntry.vue'
@Component({
components: { Panel },
components: { CommandHelpModalEntry, Panel },
})
export default class CommandHelpModal extends Mixins(BaseMixin) {
@Prop({ required: false, default: false }) declare isMini: boolean
@ -101,25 +83,26 @@ export default class CommandHelpModal extends Mixins(BaseMixin) {
mdiHelp = mdiHelp
mdiCloseThick = mdiCloseThick
get helplist(): CommandHelp[] {
return this.$store.state.printer.helplist ?? []
get helplist(): string[] {
return Object.keys(this.$store.state.printer.gcode?.commands ?? {})
}
get helplistFiltered(): CommandHelp[] {
get helplistFiltered(): string[] {
return this.helplist
.filter(
(cmd) =>
typeof cmd.description === 'string' &&
(!this.cmdListSearch || cmd.commandLow.includes(this.cmdListSearch.toLowerCase()))
)
.sort((a, b) => a.commandLow.localeCompare(b.commandLow))
.filter((cmd) => cmd.includes(this.cmdListSearch.toUpperCase()))
.sort((a, b) => a.localeCompare(b))
}
onCommand(gcode: string): void {
this.$emit('onCommand', gcode)
this.isOpen = false
}
@Watch('isOpen')
onIsOpen(val: boolean): void {
if (!val) {
this.cmdListSearch = ''
}
if (val) return
this.cmdListSearch = ''
}
}
</script>

View File

@ -0,0 +1,41 @@
<template>
<v-list-item class="px-0" :two-line="twoLine">
<v-list-item-content class="px-0">
<v-list-item-title class="primary--text font-weight-bold cursor-pointer" @click="onCommand">
{{ command }}
</v-list-item-title>
<v-list-item-subtitle v-if="description" class="text-wrap">{{ description }}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</template>
<script lang="ts">
import BaseMixin from '@/components/mixins/base'
import { Mixins, Prop } from 'vue-property-decorator'
import Component from 'vue-class-component'
@Component
export default class CommandHelpModalEntry extends Mixins(BaseMixin) {
@Prop({ required: true, type: String }) declare command: string
get commands(): { [key: string]: { help?: string } } {
return this.$store.state.printer.gcode?.commands ?? {}
}
get commandObject(): { help?: string } {
return this.commands[this.command] ?? {}
}
get description(): string | null {
return this.commandObject.help ?? null
}
get twoLine(): boolean {
return this.description !== null
}
onCommand() {
this.$emit('click-on-command', this.command)
}
}
</script>

View File

@ -13,7 +13,7 @@
:key="index"
class="consoleTableRow"
:event="event"
@command-click="commandClick"></console-table-entry>
@command-click="commandClick" />
</template>
</div>
</template>

View File

@ -100,8 +100,8 @@ export default class ConsoleTextarea extends Mixins(BaseMixin, ConsoleMixin) {
const lastNewlineIndex = beforeCursor.lastIndexOf('\n')
const currentLine = beforeCursor.substring(lastNewlineIndex + 1)
const currentLineLowerCase = currentLine.toLowerCase()
const commands = this.helplist.filter((element) => element.commandLow.startsWith(currentLineLowerCase))
const currentLineUpperCase = currentLine.toUpperCase()
const commands = this.helplist.filter((element) => element.command.startsWith(currentLineUpperCase))
if (commands.length === 0) return
@ -116,8 +116,7 @@ export default class ConsoleTextarea extends Mixins(BaseMixin, ConsoleMixin) {
let output = ''
commands.forEach(
(command) =>
(output += `<a class="command font-weight-bold">${command.command}</a>: ${command.description}<br />`)
(command) => (output += `<a class="command font-weight-bold">${command.command}</a>: ${command.help}<br />`)
)
this.$store.dispatch('server/addEvent', { message: output, type: 'autocomplete' })

View File

@ -1,12 +1,18 @@
import Vue from 'vue'
import Component from 'vue-class-component'
import { CommandHelp } from '@/store/printer/types'
import { GuiConsoleStateFilter } from '@/store/gui/console/types'
@Component
export default class ConsoleMixin extends Vue {
get helplist(): CommandHelp[] {
return this.$store.state.printer.helplist ?? []
get helplist() {
const commands: { [key: string]: { help?: string } } = this.$store.state.printer.gcode?.commands ?? {}
const helplist: { command: string; help: string }[] = []
for (const [key, values] of Object.entries(commands)) {
helplist.push({ command: key, help: values.help ?? '' })
}
return helplist
}
get consoleDirection() {

View File

@ -91,7 +91,7 @@ import BaseMixin from '@/components/mixins/base'
import ConsoleTable from '@/components/console/ConsoleTable.vue'
import Panel from '@/components/ui/Panel.vue'
import { mdiCog, mdiConsoleLine, mdiTrashCan } from '@mdi/js'
import CommandHelpModal from '@/components/CommandHelpModal.vue'
import CommandHelpModal from '@/components/console/CommandHelpModal.vue'
import ConsoleMixin from '@/components/mixins/console'
import ConsoleTextarea from '@/components/inputs/ConsoleTextarea.vue'

View File

@ -165,6 +165,7 @@
"Empty": "Empty",
"HideTemperatures": "Hide temperatures",
"HideTimelapse": "Hide Timelapse",
"Search": "Search",
"SendCode": "Send code...",
"SetupConsole": "Setup Console"
},

View File

@ -83,7 +83,7 @@
import { Component, Mixins, Ref, Watch } from 'vue-property-decorator'
import BaseMixin from '@/components/mixins/base'
import ConsoleTable from '@/components/console/ConsoleTable.vue'
import CommandHelpModal from '@/components/CommandHelpModal.vue'
import CommandHelpModal from '@/components/console/CommandHelpModal.vue'
import { mdiCog, mdiTrashCan } from '@mdi/js'
import ConsoleMixin from '@/components/mixins/console'
import ConsoleTextarea from '@/components/inputs/ConsoleTextarea.vue'

View File

@ -179,7 +179,7 @@ export class WebSocketClient {
)
}
async emitAndWait(method: string, params: Params, options: emitOptions = {}): Promise<any> {
async emitAndWait(method: string, params: Params | undefined = undefined, options: emitOptions = {}): Promise<any> {
return new Promise((resolve, reject) => {
if (this.instance?.readyState !== WebSocket.OPEN) reject()

View File

@ -16,14 +16,13 @@ export const actions: ActionTree<PrinterState, RootState> = {
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' })
Vue.$socket.emit('printer.gcode.help', {}, { action: 'printer/initHelpList' })
Vue.$socket.emit('server.gcode_store', {}, { action: 'server/getGcodeStore' })
dispatch('initSubscripts')
},
getInfo({ commit, dispatch }, payload) {
@ -46,7 +45,9 @@ export const actions: ActionTree<PrinterState, RootState> = {
dispatch('socket/removeInitModule', 'printer/info', { root: true })
},
initSubscripts({ dispatch }, payload) {
async initSubscripts({ dispatch }) {
const payload = await Vue.$socket.emitAndWait('printer.objects.list')
let subscripts = {}
const blocklist = ['menu']
@ -56,31 +57,25 @@ export const actions: ActionTree<PrinterState, RootState> = {
if (!blocklist.includes(nameSplit[0])) subscripts = { ...subscripts, [key]: null }
})
if (Object.keys(subscripts).length > 0)
Vue.$socket.emit('printer.objects.subscribe', { objects: subscripts }, { action: 'printer/getInitData' })
else
Vue.$socket.emit(
'server.temperature_store',
{ include_monitors: true },
{ action: 'printer/tempHistory/init' }
)
if (Object.keys(subscripts).length > 0) {
const result = await Vue.$socket.emitAndWait('printer.objects.subscribe', { objects: subscripts }, {})
dispatch('socket/removeInitModule', 'printer/initSubscripts', { root: true })
},
// reset screws_tilt_adjust if it exists
if ('screws_tilt_adjust' in result.status) {
result.status.screws_tilt_adjust.error = false
result.status.screws_tilt_adjust.results = {}
}
getInitData({ dispatch }, payload) {
if ('screws_tilt_adjust' in payload.status) {
payload.status.screws_tilt_adjust.error = false
payload.status.screws_tilt_adjust.results = {}
dispatch('getData', result)
setTimeout(() => {
dispatch('initExtruderCanExtrude')
}, 200)
}
dispatch('getData', payload)
Vue.$socket.emit('server.temperature_store', { include_monitors: true }, { action: 'printer/tempHistory/init' })
setTimeout(() => {
dispatch('initExtruderCanExtrude')
}, 200)
dispatch('socket/removeInitModule', 'printer/initSubscripts', { root: true })
},
getData({ commit, dispatch, state }, payload) {
@ -135,7 +130,13 @@ export const actions: ActionTree<PrinterState, RootState> = {
commit('setData', payload)
},
initExtruderCanExtrude({ state }) {
async initGcodes({ commit }) {
const gcodes = await Vue.$socket.emitAndWait('printer.objects.query', { objects: { gcode: ['commands'] } }, {})
commit('setData', gcodes.status)
},
async initExtruderCanExtrude({ dispatch, state }) {
const extruderList: string[] = Object.keys(state).filter((name) => name.startsWith('extruder'))
const reInitList: { [key: string]: string[] } = {}
@ -143,13 +144,8 @@ export const actions: ActionTree<PrinterState, RootState> = {
reInitList[extruderName] = ['can_extrude']
})
Vue.$socket.emit('printer.objects.query', { objects: reInitList }, { action: 'printer/getData' })
},
initHelpList({ commit, dispatch }, payload) {
commit('setHelplist', payload)
dispatch('socket/removeInitModule', 'printer/initHelpList', { root: true })
const result = await Vue.$socket.emitAndWait('printer.objects.query', { objects: reInitList }, {})
dispatch('getData', result.status)
},
getEndstopStatus({ commit }, payload) {
@ -165,9 +161,10 @@ export const actions: ActionTree<PrinterState, RootState> = {
if (payload.toLowerCase().trim() === 'm112') {
Vue.$socket.emit('printer.emergency_stop', {}, { loading: 'sendGcode' })
} else {
Vue.$socket.emit('printer.gcode.script', { script: payload }, { loading: 'sendGcode' })
return
}
Vue.$socket.emit('printer.gcode.script', { script: payload }, { loading: 'sendGcode' })
},
clearScrewsTiltAdjust({ commit }) {

View File

@ -2,7 +2,6 @@ import Vue from 'vue'
import { getDefaultState } from './index'
import { MutationTree } from 'vuex'
import { PrinterState } from '@/store/printer/types'
import { setDataDeep } from '@/plugins/helpers'
export const mutations: MutationTree<PrinterState> = {
reset(state) {
@ -20,7 +19,20 @@ export const mutations: MutationTree<PrinterState> = {
},
setData(state, payload) {
setDataDeep(state, payload)
Object.keys(payload).forEach((key) => {
const value = payload[key]
if (typeof value !== 'object' || value === null || !(key in state)) {
Vue.set(state, key, value)
return
}
if (typeof value === 'object') {
Object.keys(value).forEach((subkey) => {
Vue.set(state[key], subkey, value[subkey])
})
}
})
},
setBedMeshProfiles(state, payload) {
@ -29,20 +41,6 @@ export const mutations: MutationTree<PrinterState> = {
}
},
setHelplist(state, payload) {
const helplist = []
for (const [command, description] of Object.entries(payload)) {
helplist.push({
commandLow: command.toLowerCase(),
command: command,
description: description,
})
}
Vue.set(state, 'helplist', helplist)
},
clearCurrentFile(state) {
Vue.set(state, 'current_file', {})
},

View File

@ -6,21 +6,9 @@ export interface VTextareaType extends HTMLInputElement {
}
}
export interface CommandHelp {
command: string
commandLow: string
description?: string | Record<string, unknown>
}
export interface ConsoleCommandHelp {
command: CommandHelp | null
original: string
}
export interface PrinterState {
// eslint-disable-next-line
[key: string]: any
helplist?: CommandHelp[]
tempHistory?: PrinterTempHistoryState
}

View File

@ -170,6 +170,7 @@ export const actions: ActionTree<ServerState, RootState> = {
dispatch('stopKlippyConnectedInterval')
commit('setKlippyConnected')
dispatch('printer/initGcodes', null, { root: true })
dispatch('checkKlippyState', { state: payload.klippy_state, state_message: null })
},