Implemented shutdown through UI and implemented router check

This commit is contained in:
2025-11-28 10:23:57 +01:00
parent 368f60d7b6
commit b2c5d08ff4
29 changed files with 639 additions and 71 deletions

View File

@@ -73,6 +73,21 @@ var MenuBar = /** @class */ (function () {
});
}); },
},
{
type: 'icon',
text: 'Shutdown',
materialIcon: 'power_settings_new',
uniqueIdentifier: 'shutdown_installation',
click: function () { return __awaiter(_this, void 0, void 0, function () {
var mobileMenu;
return __generator(this, function (_a) {
mobileMenu = document.querySelector('.mux_mobilemenu');
mobileMenu === null || mobileMenu === void 0 ? void 0 : mobileMenu.click();
this.shutdownInstallation();
return [2 /*return*/];
});
}); },
},
],
right: [
{
@@ -100,6 +115,21 @@ var MenuBar = /** @class */ (function () {
});
}); },
},
{
type: 'normal',
text: 'Shutdown',
materialIcon: 'power_settings_new',
uniqueIdentifier: 'shutdown_installation',
click: function () { return __awaiter(_this, void 0, void 0, function () {
var mobileMenu;
return __generator(this, function (_a) {
mobileMenu = document.querySelector('.mux_mobilemenu');
mobileMenu === null || mobileMenu === void 0 ? void 0 : mobileMenu.click();
this.shutdownInstallation();
return [2 /*return*/];
});
}); },
},
{
type: 'normal',
text: 'Dashboard',
@@ -215,6 +245,38 @@ var MenuBar = /** @class */ (function () {
});
});
};
MenuBar.prototype.shutdownInstallation = function () {
return __awaiter(this, void 0, void 0, function () {
var confirmed, shutdownContainer;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, morphux_1.MorphFeature.Confirm({
title: 'Shutdown Installation',
message: 'Are you sure you want to shutdown the installation?',
})];
case 1:
confirmed = _a.sent();
if (!confirmed)
return [2 /*return*/];
morphux_1.MorphFeature.Loader({
active: true,
message: 'Shutting down installation...',
});
shutdownContainer = document.querySelector('.ntsh_shutdown');
this._Main.socket.emit('shutdownInstallation', function (response) {
morphux_1.MorphFeature.Loader({ active: false });
if (!response.succeed)
return morphux_1.MorphFeature.Alert({
title: 'Error',
message: response.message,
});
shutdownContainer.style.display = 'flex';
});
return [2 /*return*/];
}
});
});
};
MenuBar.prototype.toggleServiceMode = function (mode, skipPin) {
return __awaiter(this, void 0, void 0, function () {
var newMode, servicePin;

File diff suppressed because one or more lines are too long

View File

@@ -309,6 +309,18 @@
</div>
</div>
</div>
<div class="ntsh_shutdown">
<span class="material-symbols-outlined">
power_settings_new
</span>
<div class="mux_header">
Installation has been shut down
</div>
<div class="mux_text">
You can now safely turn off the power to the device.
</div>
</div>
</div>
</body>

View File

@@ -5297,7 +5297,7 @@
var Index = {};
var name = "morphux";
var version = "2025.9.1";
var version = "2025.11.5";
var description = "Standardized Morphix UX framework.";
var main = "dist/Index.js";
var types = "dist/index.d.ts";
@@ -5347,7 +5347,7 @@
var CE = {};
Object.defineProperty(CE, "__esModule", { value: true });
CE.ce = ce;
CE.ce = void 0;
function ce(tagName, classList, attributes, innerText, innerHTML, style) {
var _a;
var element = document.createElement(tagName);
@@ -5371,6 +5371,7 @@
element.style[key] = style[key];
return element;
}
CE.ce = ce;
var baseComponent = {};
@@ -5471,7 +5472,7 @@
var TextHighlighter = {};
Object.defineProperty(TextHighlighter, "__esModule", { value: true });
TextHighlighter.generateTextHighlights = generateTextHighlights;
TextHighlighter.generateTextHighlights = void 0;
function generateTextHighlights(originalText, additionalClassnames) {
var _a;
if (additionalClassnames === void 0) { additionalClassnames = []; }
@@ -5505,6 +5506,7 @@
}
return div;
}
TextHighlighter.generateTextHighlights = generateTextHighlights;
var Sortable$2 = {exports: {}};
@@ -6880,7 +6882,7 @@
settings.disableInElementsWithTags.map(function (tagname) {
return tagname.toUpperCase();
});
this.binds[query] = { callback: callback, settings: settings };
this.binds[query] = { callback: callback, key: key, settings: settings };
};
return KeyBinderOverwrite;
}());
@@ -6928,7 +6930,7 @@
settings.disableInElementsWithTags.map(function (tagname) {
return tagname.toUpperCase();
});
this.binds[query] = { callback: callback, settings: settings };
this.binds[query] = { callback: callback, key: key, settings: settings };
};
KeyBinderBase.prototype.unbind = function (key, settings) {
if (settings == undefined)
@@ -6971,6 +6973,20 @@
.concat(Object.keys(this.binds))
.flat()));
};
KeyBinderBase.prototype.getBindsOverview = function () {
return Object.values(this.binds).map(function (_a) {
var key = _a.key, settings = _a.settings;
var combo = [];
if (settings === null || settings === void 0 ? void 0 : settings.controlKey)
combo.push('Ctrl');
if (settings === null || settings === void 0 ? void 0 : settings.shiftKey)
combo.push('Shift');
if (settings === null || settings === void 0 ? void 0 : settings.altKey)
combo.push('Alt');
combo.push(key.length < 3 ? key.toUpperCase() : key);
return [combo.join('+'), settings === null || settings === void 0 ? void 0 : settings.name];
});
};
KeyBinderBase.prototype.generateOverwriteId = function () {
while (true) {
var id = (Math.random() + 1).toString(36).substring(7);
@@ -7041,6 +7057,10 @@
var _this = _super.call(this) || this;
_this.open = true;
_this.container = (0, CE_1$7.ce)('div', 'mux_contextmenu');
if ((options === null || options === void 0 ? void 0 : options.width) != undefined) {
_this.container.style.minWidth = "".concat(options.width, "px");
_this.container.style.width = "".concat(options.width, "px");
}
var align = (_a = options === null || options === void 0 ? void 0 : options.align) !== null && _a !== void 0 ? _a : 'center';
if ((options === null || options === void 0 ? void 0 : options.materialIconColor) != undefined)
_this.container.style.setProperty('--mux-contextmenu-iconcolor', options.materialIconColor);
@@ -7220,6 +7240,29 @@
element.setAttribute('href', item.href);
if (item.tooltip != undefined)
element.title = item.tooltip;
if (item.uniqueIdentifier != undefined) {
element.setAttribute('uid', item.uniqueIdentifier);
}
if (item.enabled == false)
element.classList.add('mux_contextmenu-item-disabled');
var textContent = (0, CE_1$7.ce)('div', 'mux_contextmenu-item-content');
element.appendChild(textContent);
var itemContent = (0, CE_1$7.ce)('div', ['mux_text', 'mux_small'], null, (_b = item.text) !== null && _b !== void 0 ? _b : '');
if (item.customFontSize != undefined)
itemContent.style.fontSize = "".concat(item.customFontSize, "px");
textContent.appendChild(itemContent);
if (item.children == undefined && item.shortcut != undefined)
textContent.appendChild((0, CE_1$7.ce)('div', [
'mux_contextmenu-shortcut',
'mux_text',
'mux_tiny',
], null, (_c = item.shortcut) !== null && _c !== void 0 ? _c : ''));
if (item.children != undefined && item.children.length > 0) {
textContent.appendChild((0, CE_1$7.ce)('span', [
'material-symbols-outlined',
'mux_contextmenu-item-arrow',
], null, 'keyboard_arrow_right'));
}
if (item.materialIcon != undefined) {
var materialIcon = (0, CE_1$7.ce)('span', [
'mux_contextmenu-item-materialicon',
@@ -7234,27 +7277,6 @@
element.appendChild((0, CE_1$7.ce)('img', 'mux_contextmenu-item-icon', {
src: item.icon,
}));
if (item.uniqueIdentifier != undefined) {
element.setAttribute('uid', item.uniqueIdentifier);
}
if (item.enabled == false)
element.classList.add('mux_contextmenu-item-disabled');
var itemContent = (0, CE_1$7.ce)('div', ['mux_text', 'mux_small'], null, (_b = item.text) !== null && _b !== void 0 ? _b : '');
if (item.customFontSize != undefined)
itemContent.style.fontSize = "".concat(item.customFontSize, "px");
element.appendChild(itemContent);
if (item.children == undefined && item.shortcut != undefined)
element.appendChild((0, CE_1$7.ce)('div', [
'mux_contextmenu-shortcut',
'mux_text',
'mux_tiny',
], null, (_c = item.shortcut) !== null && _c !== void 0 ? _c : ''));
if (item.children != undefined && item.children.length > 0) {
element.appendChild((0, CE_1$7.ce)('span', [
'material-symbols-outlined',
'mux_contextmenu-item-arrow',
], null, 'keyboard_arrow_right'));
}
element.onmousemove = function () {
if (_this.subContextParent == itemId)
return;
@@ -10694,16 +10716,16 @@
var Utils = {};
Object.defineProperty(Utils, "__esModule", { value: true });
Utils.blackPixel = void 0;
Utils.isMobile = isMobile;
Utils.delay = delay;
Utils.delay = Utils.blackPixel = Utils.isMobile = void 0;
function isMobile() {
return /Android|iPhone|iPad|iPod|Opera Mini|IEMobile|WPDesktop/i.test(navigator.userAgent);
}
Utils.isMobile = isMobile;
Utils.blackPixel = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
function delay(duration) {
return new Promise(function (resolve) { return setTimeout(resolve, duration); });
}
Utils.delay = delay;
var hasRequiredComponent_ImageViewer;
@@ -10735,8 +10757,8 @@
});
};
var __generator = (commonjsGlobal && commonjsGlobal.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
@@ -11842,7 +11864,8 @@
this.container
.querySelectorAll('.mux_menubar-item')
.forEach(function (item) {
if (item.getAttribute('uid') == uniqueIdentifier)
if (item.getAttribute('uid') == uniqueIdentifier &&
uniqueIdentifier != null)
item.classList.add('mux_menubar-item-selected');
else
item.classList.remove('mux_menubar-item-selected');
@@ -13513,8 +13536,8 @@
});
};
var __generator = (commonjsGlobal && commonjsGlobal.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
@@ -14017,7 +14040,7 @@
if (hasRequiredFeature_Alert) return Feature_Alert;
hasRequiredFeature_Alert = 1;
Object.defineProperty(Feature_Alert, "__esModule", { value: true });
Feature_Alert.FeatureAlert = FeatureAlert;
Feature_Alert.FeatureAlert = void 0;
var Index_1 = requireIndex();
function FeatureAlert(options, callback) {
return new Promise(function (resolve) {
@@ -14038,6 +14061,7 @@
dialog.on('ok', function () { return res(); });
});
}
Feature_Alert.FeatureAlert = FeatureAlert;
return Feature_Alert;
}
@@ -14050,7 +14074,7 @@
if (hasRequiredFeature_Confirm) return Feature_Confirm;
hasRequiredFeature_Confirm = 1;
Object.defineProperty(Feature_Confirm, "__esModule", { value: true });
Feature_Confirm.FeatureConfirm = FeatureConfirm;
Feature_Confirm.FeatureConfirm = void 0;
var Index_1 = requireIndex();
function FeatureConfirm(options, callback) {
return new Promise(function (resolve) {
@@ -14071,6 +14095,7 @@
dialog.on('ok', function () { return res(true); });
});
}
Feature_Confirm.FeatureConfirm = FeatureConfirm;
return Feature_Confirm;
}
@@ -14083,7 +14108,7 @@
if (hasRequiredFeature_Loader) return Feature_Loader;
hasRequiredFeature_Loader = 1;
Object.defineProperty(Feature_Loader, "__esModule", { value: true });
Feature_Loader.FeatureLoader = FeatureLoader;
Feature_Loader.FeatureLoader = void 0;
var Index_1 = requireIndex();
function FeatureLoader(options) {
var _a, _b;
@@ -14095,6 +14120,7 @@
else
removeExisting();
}
Feature_Loader.FeatureLoader = FeatureLoader;
function showLoader(message, progress) {
var loader = document.querySelector('.mux_loader');
if (loader == null) {
@@ -14154,7 +14180,7 @@
if (hasRequiredFeature_Notification) return Feature_Notification;
hasRequiredFeature_Notification = 1;
Object.defineProperty(Feature_Notification, "__esModule", { value: true });
Feature_Notification.FeatureNotification = FeatureNotification;
Feature_Notification.FeatureNotification = void 0;
var Index_1 = requireIndex();
var NotificationHandler = new (/** @class */ (function () {
function class_1() {
@@ -14227,6 +14253,7 @@
return;
return NotificationHandler.append(notification);
}
Feature_Notification.FeatureNotification = FeatureNotification;
return Feature_Notification;
}
@@ -14239,7 +14266,7 @@
if (hasRequiredFeature_Prompt) return Feature_Prompt;
hasRequiredFeature_Prompt = 1;
Object.defineProperty(Feature_Prompt, "__esModule", { value: true });
Feature_Prompt.FeaturePrompt = FeaturePrompt;
Feature_Prompt.FeaturePrompt = void 0;
var Index_1 = requireIndex();
function FeaturePrompt(options, callback) {
return new Promise(function (resolve) {
@@ -14285,6 +14312,7 @@
input.container.focus();
});
}
Feature_Prompt.FeaturePrompt = FeaturePrompt;
return Feature_Prompt;
}
@@ -14320,12 +14348,13 @@
var clone$1 = {};
Object.defineProperty(clone$1, "__esModule", { value: true });
clone$1.clone = clone;
clone$1.clone = void 0;
function clone(object) {
if (typeof object !== 'object')
return object;
return JSON.parse(JSON.stringify(object !== null && object !== void 0 ? object : {}));
}
clone$1.clone = clone;
(function (exports) {
Object.defineProperty(exports, "__esModule", { value: true });
@@ -14450,6 +14479,21 @@
});
}); },
},
{
type: 'icon',
text: 'Shutdown',
materialIcon: 'power_settings_new',
uniqueIdentifier: 'shutdown_installation',
click: function () { return __awaiter$4(_this, void 0, void 0, function () {
var mobileMenu;
return __generator$4(this, function (_a) {
mobileMenu = document.querySelector('.mux_mobilemenu');
mobileMenu === null || mobileMenu === void 0 ? void 0 : mobileMenu.click();
this.shutdownInstallation();
return [2 /*return*/];
});
}); },
},
],
right: [
{
@@ -14477,6 +14521,21 @@
});
}); },
},
{
type: 'normal',
text: 'Shutdown',
materialIcon: 'power_settings_new',
uniqueIdentifier: 'shutdown_installation',
click: function () { return __awaiter$4(_this, void 0, void 0, function () {
var mobileMenu;
return __generator$4(this, function (_a) {
mobileMenu = document.querySelector('.mux_mobilemenu');
mobileMenu === null || mobileMenu === void 0 ? void 0 : mobileMenu.click();
this.shutdownInstallation();
return [2 /*return*/];
});
}); },
},
{
type: 'normal',
text: 'Dashboard',
@@ -14592,6 +14651,38 @@
});
});
};
MenuBar.prototype.shutdownInstallation = function () {
return __awaiter$4(this, void 0, void 0, function () {
var confirmed, shutdownContainer;
return __generator$4(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, morphux_1$5.MorphFeature.Confirm({
title: 'Shutdown Installation',
message: 'Are you sure you want to shutdown the installation?',
})];
case 1:
confirmed = _a.sent();
if (!confirmed)
return [2 /*return*/];
morphux_1$5.MorphFeature.Loader({
active: true,
message: 'Shutting down installation...',
});
shutdownContainer = document.querySelector('.ntsh_shutdown');
this._Main.socket.emit('shutdownInstallation', function (response) {
morphux_1$5.MorphFeature.Loader({ active: false });
if (!response.succeed)
return morphux_1$5.MorphFeature.Alert({
title: 'Error',
message: response.message,
});
shutdownContainer.style.display = 'flex';
});
return [2 /*return*/];
}
});
});
};
MenuBar.prototype.toggleServiceMode = function (mode, skipPin) {
return __awaiter$4(this, void 0, void 0, function () {
var newMode, servicePin;

File diff suppressed because one or more lines are too long

View File

@@ -17,7 +17,7 @@ body {
}
.mux_menubar-locater.mux_left {
.mux_menubar-item:not([uid="restart_installation"]) {
.mux_menubar-item:not([uid="restart_installation"], [uid="shutdown_installation"]) {
display: none;
}
}
@@ -77,4 +77,22 @@ body {
}
}
}
}
.ntsh_shutdown {
position: absolute;
inset: 0px;
z-index: 10000;
background: var(--mux-bg-color);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
gap: var(--mux-edge-offset);
.material-symbols-outlined {
margin-bottom: var(--mux-edge-offset);
font-size: 60px;
color: #919191;
}
}

View File

@@ -802,6 +802,7 @@
.mux_contextmenu {
position: absolute;
z-index: 1101;
min-width: 120px;
border-radius: var(--mux-rounding);
background: var(--mux-panel-color);
box-shadow: var(--mux-panel-shadow);
@@ -810,7 +811,7 @@
transform-origin: 50% 0%;
transform: scale(0);
user-select: none;
--mux-contextmenu-iconcolor: var(--mux-text-color);
--mux-contextmenu-iconcolor: #919191;
}
.mux_contextmenu .mux_contextmenu-item {
@@ -845,25 +846,33 @@
}
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-item-icon {
margin-right: var(--mux-edge-offset-tiny);
height: 20px;
margin-right: -2px;
height: 16px;
border-radius: var(--mux-rounding);
}
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-item-arrow {
font-size: 16px;
margin-right: -5px;
color: #fff;
}
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-item-materialicon {
margin-right: var(--mux-edge-offset);
margin-right: -2px;
color: var(--mux-contextmenu-iconcolor);
font-size: 20px;
font-size: 16px;
}
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-shortcut {
margin-left: var(--mux-edge-offset);
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-item-content {
flex-grow: 1;
display: flex;
justify-content: flex-start;
align-items: center;
gap: var(--mux-edge-offset-tiny);
padding-right: calc(var(--mux-edge-offset) * 2);
}
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-item-content .mux_contextmenu-item-arrow {
font-size: 16px;
margin-left: calc(var(--mux-edge-offset-tiny) * -1);
color: #c0c0c0;
}
.mux_contextmenu .mux_contextmenu-item .mux_contextmenu-item-content .mux_contextmenu-shortcut {
color: #b3b3b3;
}
@@ -2577,7 +2586,7 @@ body {
body:not(.ntsh_service) .ntsh_buttons {
display: none;
}
body:not(.ntsh_service) .mux_menubar-locater.mux_left .mux_menubar-item:not([uid=restart_installation]) {
body:not(.ntsh_service) .mux_menubar-locater.mux_left .mux_menubar-item:not([uid=restart_installation], [uid=shutdown_installation]) {
display: none;
}
body:not(.ntsh_service) .only-service {
@@ -2622,4 +2631,21 @@ body.ntsh_service .no-service {
color: #c7c7c7;
}
.ntsh_shutdown {
position: absolute;
inset: 0px;
z-index: 10000;
background: var(--mux-bg-color);
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
gap: var(--mux-edge-offset);
}
.ntsh_shutdown .material-symbols-outlined {
margin-bottom: var(--mux-edge-offset);
font-size: 60px;
color: #919191;
}
/*# sourceMappingURL=style.css.map */

File diff suppressed because one or more lines are too long

View File

@@ -44,6 +44,20 @@ export class MenuBar {
this.restartInstallation();
},
},
{
type: 'icon',
text: 'Shutdown',
materialIcon: 'power_settings_new',
uniqueIdentifier: 'shutdown_installation',
click: async () => {
const mobileMenu: HTMLDivElement =
document.querySelector('.mux_mobilemenu');
mobileMenu?.click();
this.shutdownInstallation();
},
},
],
right: [
{
@@ -70,6 +84,20 @@ export class MenuBar {
this.restartInstallation();
},
},
{
type: 'normal',
text: 'Shutdown',
materialIcon: 'power_settings_new',
uniqueIdentifier: 'shutdown_installation',
click: async () => {
const mobileMenu: HTMLDivElement =
document.querySelector('.mux_mobilemenu');
mobileMenu?.click();
this.shutdownInstallation();
},
},
{
type: 'normal',
text: 'Dashboard',
@@ -187,6 +215,35 @@ export class MenuBar {
);
}
async shutdownInstallation() {
const confirmed = await MorphFeature.Confirm({
title: 'Shutdown Installation',
message: 'Are you sure you want to shutdown the installation?',
});
if (!confirmed) return;
MorphFeature.Loader({
active: true,
message: 'Shutting down installation...',
});
const shutdownContainer: HTMLDivElement =
document.querySelector('.ntsh_shutdown');
this._Main.socket.emit(
'shutdownInstallation',
(response: { succeed: boolean; message?: string }) => {
MorphFeature.Loader({ active: false });
if (!response.succeed)
return MorphFeature.Alert({
title: 'Error',
message: response.message,
});
shutdownContainer.style.display = 'flex';
}
);
}
async toggleServiceMode(
mode?: boolean,
skipPin?: boolean