ui: V09 redesign - Control/Program/Console/Settings shell
Replaces the legacy side-menu chrome with a 4-tab top header. - index.pug: tablet/kiosk fit-to-viewport script, header tab nav, estop/state badges in header. - app.js: route hash to (control|program|console|<settings-family>), multi-section settings shell. - control-view: header DRO, jog grid, MDI/probe/macros panels. - program-view + program-mixin: file browser + toolpath preview + run/pause/stop, replaces the legacy 'macros' tab content. - console-view: MDI shell, message log, indicators. - settings-shell-view: rail-driven inner pages (Display & Units, Probing, G-code & Motion, Macros, Network, etc.). - settings-view: filter Svelte SettingsView to one rail section. - SettingsView.svelte: tag every section with data-sec=… so the filter above can hide non-matching ones. - style.styl: ~2700 lines of V09 layout, DRO, jog grid, status strip, and tablet/kiosk variants. No A-axis / auxiliary-axis content lives on this branch.
This commit is contained in:
125
src/js/console-view.js
Normal file
125
src/js/console-view.js
Normal file
@@ -0,0 +1,125 @@
|
||||
"use strict";
|
||||
|
||||
const api = require("./api");
|
||||
|
||||
// Console tab — MDI command input, message log and live indicators.
|
||||
// Sub-tab state syncs with the URL hash (#console:mdi |
|
||||
// #console:messages | #console:indicators) so deep links work.
|
||||
|
||||
module.exports = {
|
||||
template: "#console-view-template",
|
||||
props: ["config", "template", "state"],
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
mdi: "",
|
||||
history: [],
|
||||
sub: "mdi",
|
||||
// Local mirror of $root.messages_count so Vue 1 reactivity works.
|
||||
unread_messages_local: 0,
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
sub: function () {
|
||||
// Switching to messages marks them as seen so the header badge
|
||||
// clears.
|
||||
if (this.sub === "messages") {
|
||||
this.$root.messages_seen = this.$root.messages_log.length;
|
||||
this.unread_messages_local = 0;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
unread_messages: function () {
|
||||
return this.unread_messages_local;
|
||||
},
|
||||
|
||||
mach_state: function () {
|
||||
const cycle = this.state.cycle;
|
||||
const xx = this.state.xx;
|
||||
if (xx != "ESTOPPED" && (cycle == "jogging" || cycle == "homing")) {
|
||||
return cycle.toUpperCase();
|
||||
}
|
||||
return xx || "";
|
||||
},
|
||||
|
||||
is_idle: function () { return this.state.cycle == "idle"; },
|
||||
|
||||
can_mdi: function () {
|
||||
return this.is_idle || this.state.cycle == "mdi";
|
||||
},
|
||||
|
||||
mach_units: function () {
|
||||
return this.$root.display_units;
|
||||
},
|
||||
},
|
||||
|
||||
ready: function () {
|
||||
this._onHash = () => this.refresh_from_hash();
|
||||
window.addEventListener("hashchange", this._onHash);
|
||||
this.refresh_from_hash();
|
||||
this._poll = setInterval(() => {
|
||||
// Cheap re-poll for unread message count; Vue 1 cannot observe
|
||||
// `$root.messages_count` directly so we mirror it here.
|
||||
const c = this.$root && this.$root.messages_count;
|
||||
if (typeof c === "number" && c !== this.unread_messages_local) {
|
||||
this.unread_messages_local = c;
|
||||
}
|
||||
}, 500);
|
||||
},
|
||||
|
||||
beforeDestroy: function () {
|
||||
if (this._onHash) window.removeEventListener("hashchange", this._onHash);
|
||||
if (this._poll) clearInterval(this._poll);
|
||||
},
|
||||
|
||||
methods: {
|
||||
refresh_from_hash: function () {
|
||||
const hash = location.hash.substr(1);
|
||||
const parts = hash.split(":");
|
||||
const sub = parts[0] === "console" ? (parts[1] || "mdi") : "mdi";
|
||||
this.sub = sub;
|
||||
if (sub === "messages" && this.$root) {
|
||||
this.$root.messages_seen = this.$root.messages_log.length;
|
||||
this.unread_messages_local = 0;
|
||||
}
|
||||
},
|
||||
|
||||
select_sub: function (name) {
|
||||
this.sub = name;
|
||||
// Update URL hash for deep links / back-button.
|
||||
const h = "#console" + (name && name !== "mdi" ? ":" + name : "");
|
||||
if (location.hash !== h) {
|
||||
history.replaceState(null, "", h);
|
||||
}
|
||||
if (name === "messages") {
|
||||
this.$root.messages_seen = this.$root.messages_log.length;
|
||||
this.unread_messages_local = 0;
|
||||
}
|
||||
},
|
||||
|
||||
prepend: function (token) {
|
||||
this.mdi = token + this.mdi.trimStart();
|
||||
},
|
||||
|
||||
append: function (token) {
|
||||
const tail = this.mdi.endsWith(" ") || !this.mdi ? "" : " ";
|
||||
this.mdi = this.mdi + tail + token;
|
||||
},
|
||||
|
||||
submit_mdi: function () {
|
||||
if (!this.mdi) return;
|
||||
this.$dispatch("send", this.mdi);
|
||||
if (!this.history.length || this.history[0] != this.mdi) {
|
||||
this.history.unshift(this.mdi);
|
||||
}
|
||||
this.mdi = "";
|
||||
},
|
||||
|
||||
load_history: function (index) {
|
||||
this.mdi = this.history[index];
|
||||
},
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user