Skip to content

Commit

Permalink
Merge branch 'develop' into refactor/machine-settings-panel
Browse files Browse the repository at this point in the history
  • Loading branch information
meteyou authored Sep 7, 2024
2 parents 7785c21 + 0ac902f commit d21ec58
Show file tree
Hide file tree
Showing 22 changed files with 711 additions and 324 deletions.
39 changes: 17 additions & 22 deletions src/components/TheConnectingDialog.vue
Original file line number Diff line number Diff line change
@@ -1,35 +1,30 @@
<style scoped></style>

<template>
<v-dialog v-model="showDialog" persistent :width="400">
<v-card>
<v-toolbar flat dense>
<v-toolbar-title>
<span class="subheading">
<v-icon left>{{ mdiConnection }}</v-icon>
{{ titleText }}
</span>
</v-toolbar-title>
</v-toolbar>
<panel :title="titleText" :icon="mdiConnection" card-class="the-connection-dialog" :margin-bottom="false">
<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>
<connection-status :moonraker="false" />
<p class="text-center mt-3 mb-0">
{{ $t('ConnectionDialog.CannotConnectTo', { host: formatHostname }) }}
</p>
<p v-if="connectionFailedMessage" class="text-center mt-1 red--text">
{{ $t('ConnectionDialog.ErrorMessage', { message: connectionFailedMessage }) }}
</p>
<template v-if="counter > 2">
<v-divider class="my-3"></v-divider>
<v-divider class="my-3" />
<p>{{ $t('ConnectionDialog.CheckMoonrakerLog') }}</p>
<ul>
<li>~/printer_data/logs/moonraker.log</li>
</ul>
<v-divider class="mt-4 mb-5"></v-divider>
<v-divider class="mt-4 mb-5" />
</template>
<div class="text-center">
<div class="text-center mt-3">
<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="progressBarColor" indeterminate></v-progress-linear>
<v-progress-linear :color="progressBarColor" indeterminate />
</v-card-text>
</v-card>
</panel>
</v-dialog>
</template>

Expand All @@ -52,10 +47,6 @@ export default class TheConnectingDialog extends Mixins(BaseMixin, ThemeMixin) {
counter = 0
get protocol() {
return this.$store.state.socket.protocol
}
get hostname() {
return this.$store.state.socket.hostname
}
Expand Down Expand Up @@ -94,6 +85,10 @@ export default class TheConnectingDialog extends Mixins(BaseMixin, ThemeMixin) {
return this.formatHostname
}
get connectionFailedMessage() {
return this.$store.state.socket.connectionFailedMessage ?? null
}
reconnect() {
this.counter++
this.$store.dispatch('socket/setData', { connectingFailed: false })
Expand Down
141 changes: 133 additions & 8 deletions src/components/TheEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
<v-icon small class="mr-1">{{ mdiHelp }}</v-icon>
{{ $t('Editor.ConfigReference') }}
</v-btn>
<v-btn v-if="configFileStructure" text tile class="d-none d-md-flex" @click="showFileStructure()">
<v-icon small class="mr-1">{{ mdiFormatListCheckbox }}</v-icon>
{{ $t('Editor.FileStructure') }}
</v-btn>
<v-btn
v-if="restartServiceNameExists"
color="primary"
Expand All @@ -48,17 +52,50 @@
<v-icon>{{ mdiCloseThick }}</v-icon>
</v-btn>
</template>
<v-card-text class="pa-0">
<v-card-text class="pa-0 d-flex">
<codemirror-async
v-if="show"
ref="editor"
v-model="sourcecode"
:name="filename"
:file-extension="fileExtension" />
:file-extension="fileExtension"
class="codemirror"
@lineChange="lineChanges" />
<div v-if="fileStructureSidebar" class="d-none d-md-flex structure-sidebar">
<v-treeview
activatable
dense
:active="structureActive"
:open="structureOpen"
item-key="line"
:items="configFileStructure"
class="w-100"
@update:active="activeChanges">
<template #label="{ item }">
<div
class="cursor-pointer _structure-sidebar-item"
:class="item.type == 'item' ? 'ͼp' : 'ͼt'">
{{ item.name }}
</div>
</template>
<template v-if="restartServiceName === 'klipper'" #append="{ item }">
<v-btn
v-if="item.type == 'section'"
icon
small
plain
color="grey darken-2"
:href="klipperConfigReference + '#' + item.name.split(' ')[0]"
target="_blank">
<v-icon small class="mr-1">{{ mdiHelpCircle }}</v-icon>
</v-btn>
</template>
</v-treeview>
</div>
</v-card-text>
</panel>
</v-dialog>
<v-snackbar v-model="loaderBool" :timeout="-1" :value="true" fixed right bottom>
<v-snackbar v-model="loaderBool" :timeout="-1" fixed right bottom>
<div>
{{ snackbarHeadline }}
<br />
Expand Down Expand Up @@ -123,7 +160,7 @@
</template>

<script lang="ts">
import { Component, Mixins, Watch } from 'vue-property-decorator'
import { Component, Mixins, Ref, Watch } from 'vue-property-decorator'
import BaseMixin from '@/components/mixins/base'
import { capitalize, formatFilesize, windowBeforeUnloadFunction } from '@/plugins/helpers'
import Panel from '@/components/ui/Panel.vue'
Expand All @@ -139,16 +176,20 @@ import {
mdiHelpCircle,
mdiRestart,
mdiUsb,
mdiFormatListCheckbox,
} from '@mdi/js'
import type Codemirror from '@/components/inputs/Codemirror.vue'
import DevicesDialog from '@/components/dialogs/DevicesDialog.vue'
import { ConfigFileSection } from '@/store/files/types'
@Component({
components: { DevicesDialog, Panel, CodemirrorAsync },
})
export default class TheEditor extends Mixins(BaseMixin) {
dialogConfirmChange = false
dialogDevices = false
fileStructureSidebar = true
structureActive: number[] = []
structureOpen: number[] = []
formatFilesize = formatFilesize
Expand All @@ -164,10 +205,10 @@ export default class TheEditor extends Mixins(BaseMixin) {
mdiFileDocumentEditOutline = mdiFileDocumentEditOutline
mdiFileDocumentOutline = mdiFileDocumentOutline
mdiUsb = mdiUsb
mdiFormatListCheckbox = mdiFormatListCheckbox
declare $refs: {
editor: Codemirror
}
//@ts-ignore
@Ref('editor') editor!: CodemirrorAsync
get changed() {
return this.$store.state.editor.changed ?? false
Expand Down Expand Up @@ -305,6 +346,48 @@ export default class TheEditor extends Mixins(BaseMixin) {
return url
}
get configFileStructure() {
if (!['conf', 'cfg'].includes(this.fileExtension)) {
this.fileStructureSidebar = false
return null
}
const lines = this.sourcecode.split(/\n/gi)
const regex = /^[^#\S]*?(\[(?<section>.*?)]|(?<name>\w+)\s*?[:=])/gim
const structure: ConfigFileSection[] = []
for (let i = 0; i < lines.length; i++) {
const line = lines[i]
const matches = [...line.matchAll(regex)]
// break if no matches were found
if (matches.length === 0) continue
const match = matches[0]
if (match['groups']['section']) {
structure.push({
name: match['groups']['section'],
type: 'section',
line: i + 1,
children: [],
})
continue
}
if (match['groups']['name']) {
structure[structure.length - 1]['children'].push({
name: match['groups']['name'],
type: 'item',
line: i + 1,
})
}
}
this.fileStructureSidebar = true
return structure
}
cancelDownload() {
this.$store.dispatch('editor/cancelLoad')
}
Expand Down Expand Up @@ -337,6 +420,29 @@ export default class TheEditor extends Mixins(BaseMixin) {
})
}
showFileStructure() {
this.fileStructureSidebar = !this.fileStructureSidebar
}
activeChanges(key: any) {
this.editor?.gotoLine(key)
}
lineChanges(line: number) {
this.configFileStructure?.map((item) => {
if (item.line == line) {
this.structureActive = [line]
} else {
item.children?.map((child) => {
if (child.line == line) {
this.structureActive = [line]
if (!this.structureOpen.includes(item.line)) this.structureOpen.push(item.line)
}
})
}
})
}
@Watch('changed')
changedChanged(newVal: boolean) {
if (!this.confirmUnsavedChanges) return
Expand Down Expand Up @@ -398,4 +504,23 @@ export default class TheEditor extends Mixins(BaseMixin) {
background-color: var(--color-primary);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E %3Cpath d='M15.88 8.29L10 14.17l-1.88-1.88a.996.996 0 1 0-1.41 1.41l2.59 2.59c.39.39 1.02.39 1.41 0L17.3 9.7a.996.996 0 0 0 0-1.41c-.39-.39-1.03-.39-1.42 0z' fill='%23fffff'/%3E %3C/svg%3E");
}
@media screen and (min-width: 960px) {
.codemirror {
width: calc(100% - 300px);
}
}
.structure-sidebar {
width: 300px;
overflow-y: auto;
}
._structure-sidebar-item {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
::v-deep .v-treeview-node__level + .v-treeview-node__level {
width: 12px;
}
</style>
50 changes: 50 additions & 0 deletions src/components/dialogs/CancelJobDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<template>
<v-dialog :value="showDialog" width="400" persistent>
<panel
:title="$t('CancelJobDialog.CancelJob')"
toolbar-color="normal"
card-class="cancel-job-dialog"
:icon="mdiStopCircleOutline"
:margin-bottom="false">
<template #buttons>
<v-btn icon tile @click="closePrompt">
<v-icon>{{ mdiCloseThick }}</v-icon>
</v-btn>
</template>
<v-card-text>{{ $t('CancelJobDialog.AreYouSure') }}</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn text @click="closePrompt">{{ $t('CancelJobDialog.No') }}</v-btn>
<v-btn color="primary" text @click="cancelJob">{{ $t('CancelJobDialog.Yes') }}</v-btn>
</v-card-actions>
</panel>
</v-dialog>
</template>

<script lang="ts">
import { Component, Mixins, Prop } from 'vue-property-decorator'
import BaseMixin from '@/components/mixins/base'
import Panel from '@/components/ui/Panel.vue'
import { mdiCloseThick, mdiStopCircleOutline } from '@mdi/js'
@Component({
components: { Panel },
})
export default class CancelJobDialog extends Mixins(BaseMixin) {
mdiCloseThick = mdiCloseThick
mdiStopCircleOutline = mdiStopCircleOutline
@Prop({ type: Boolean, default: false }) showDialog!: boolean
cancelJob() {
this.$emit('cancel-job')
}
closePrompt() {
this.$emit('close')
}
}
</script>

<style scoped></style>
26 changes: 19 additions & 7 deletions src/components/inputs/Codemirror.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<template>
<div class="vue-codemirror">
<div ref="codemirror" v-observe-visibility="visibilityChanged"></div>
<div ref="editor" v-observe-visibility="visibilityChanged"></div>
</div>
</template>

<script lang="ts">
// Inspired by these repo: https://github.com/surmon-china/vue-codemirror
// Inspired by this repo: https://github.com/surmon-china/vue-codemirror
import { Component, Mixins, Prop, Watch } from 'vue-property-decorator'
import { Component, Mixins, Prop, Ref, Watch } from 'vue-property-decorator'
import BaseMixin from '../mixins/base'
import { basicSetup } from 'codemirror'
import { EditorView, keymap } from '@codemirror/view'
Expand All @@ -27,9 +27,7 @@ export default class Codemirror extends Mixins(BaseMixin) {
private codemirror: null | EditorView = null
private cminstance: null | EditorView = null
declare $refs: {
codemirror: HTMLElement
}
@Ref('editor') editor!: HTMLElement
@Prop({ required: false, default: '' })
declare readonly code: string
Expand Down Expand Up @@ -65,7 +63,7 @@ export default class Codemirror extends Mixins(BaseMixin) {
initialize() {
this.codemirror = new EditorView({
parent: this.$refs.codemirror,
parent: this.editor,
})
this.cminstance = this.codemirror
Expand All @@ -88,6 +86,10 @@ export default class Codemirror extends Mixins(BaseMixin) {
indentUnit.of(' '.repeat(this.tabSize)),
keymap.of([indentWithTab]),
EditorView.updateListener.of((update) => {
if (update.selectionSet) {
const line = this.cminstance?.state?.doc.lineAt(this.cminstance?.state?.selection.main.head).number
this.$emit('lineChange', line)
}
this.content = update.state?.doc.toString()
if (this.$emit) {
this.$emit('input', this.content)
Expand All @@ -110,5 +112,15 @@ export default class Codemirror extends Mixins(BaseMixin) {
get tabSize() {
return this.$store.state.gui.editor.tabSize || 2
}
gotoLine(line: number) {
const l = this.cminstance?.state?.doc.line(line)
if (!l) return
this.cminstance?.dispatch({
selection: { head: l.from, anchor: l.to },
scrollIntoView: true,
})
}
}
</script>
Loading

0 comments on commit d21ec58

Please sign in to comment.