add support for custom regions, by detecting what is used in index.html (#3518)

read index.html to discover the regions used, make them the list checked
by app.js and check:config test

fixes #3504   supercedes #3506 

no config.js param required
This commit is contained in:
sam detweiler
2024-08-27 15:52:59 -05:00
committed by GitHub
parent 56736786fd
commit 2b97e0d26e
11 changed files with 154 additions and 29 deletions

View File

@@ -256,6 +256,9 @@ function App () {
Log.setLogLevel(config.logLevel);
// get the used module positions
Utils.getModulePositions();
let modules = [];
for (const module of config.modules) {
if (module.disabled) continue;
@@ -266,10 +269,10 @@ function App () {
modules.push(module.module);
}
} else {
Log.warn("Invalid module position found for this configuration:", module);
Log.warn("Invalid module position found for this configuration:" + `\n${JSON.stringify(module, null, 2)}`);
}
} else {
Log.warn("No module name found for this configuration:", module);
Log.warn("No module name found for this configuration:" + `\n${JSON.stringify(module, null, 2)}`);
}
}

View File

@@ -11,6 +11,7 @@ const ajv = new Ajv();
const rootPath = path.resolve(`${__dirname}/../`);
const Log = require(`${rootPath}/js/logger.js`);
const Utils = require(`${rootPath}/js/utils.js`);
/**
* Returns a string with path of configuration file.
@@ -68,6 +69,7 @@ function checkConfigFile () {
Log.info("Checking modules structure configuration... ");
const position_list = Utils.getModulePositions();
// Make Ajv schema confguration of modules config
// only scan "module" and "position"
const schema = {
@@ -83,21 +85,7 @@ function checkConfigFile () {
},
position: {
type: "string",
enum: [
"top_bar",
"top_left",
"top_center",
"top_right",
"upper_third",
"middle_center",
"lower_third",
"bottom_left",
"bottom_center",
"bottom_right",
"bottom_bar",
"fullscreen_above",
"fullscreen_below"
]
enum: position_list
}
},
required: ["module"]
@@ -116,10 +104,10 @@ function checkConfigFile () {
let position = validate.errors[0].instancePath.split("/")[3];
Log.error(colors.red("This module configuration contains errors:"));
Log.error(data.modules[module]);
Log.error(`\n${JSON.stringify(data.modules[module], null, 2)}`);
if (position) {
Log.error(colors.red(`${position}: ${validate.errors[0].message}`));
Log.error(validate.errors[0].params.allowedValues);
Log.error(`\n${JSON.stringify(validate.errors[0].params.allowedValues, null, 2).slice(1, -1)}`);
} else {
Log.error(colors.red(validate.errors[0].message));
}

View File

@@ -27,7 +27,6 @@ const defaults = {
// (interval 30 seconds). If startup-timestamp has changed the client reloads the magicmirror webpage.
checkServerInterval: 30 * 1000,
reloadAfterServerRestart: false,
allowCustomModulePositions: false,
modules: [
{

View File

@@ -50,7 +50,7 @@ const Loader = (function () {
* @returns {object[]} module data as configured in config
*/
const getAllModules = function () {
const AllModules = config.modules.filter((module) => (module.module !== undefined) && (MM.getAvailableModulePositions.indexOf(module.position) > -1 || typeof (module.position) === "undefined" || config.allowCustomModulePositions));
const AllModules = config.modules.filter((module) => (module.module !== undefined) && (MM.getAvailableModulePositions.indexOf(module.position) > -1 || typeof (module.position) === "undefined"));
return AllModules;
};

View File

@@ -1,4 +1,4 @@
/* global Loader, defaults, Translator, addAnimateCSS, removeAnimateCSS, AnimateCSSIn, AnimateCSSOut */
/* global Loader, defaults, Translator, addAnimateCSS, removeAnimateCSS, AnimateCSSIn, AnimateCSSOut, modulePositions */
const MM = (function () {
let modules = [];
@@ -450,7 +450,6 @@ const MM = (function () {
* an ugly top margin. By using this function, the top bar will be hidden if the
* update notification is not visible.
*/
const modulePositions = ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"];
const updateWrapperStates = function () {
modulePositions.forEach(function (position) {

View File

@@ -1,7 +1,17 @@
const execSync = require("node:child_process").execSync;
const Log = require("logger");
const path = require("node:path");
const rootPath = path.resolve(`${__dirname}/../`);
const Log = require(`${rootPath}/js/logger.js`);
const os = require("node:os");
const fs = require("node:fs");
const si = require("systeminformation");
const modulePositions = []; // will get list from index.html
const regionRegEx = /"region ([^"]*)/i;
const indexFileName = "index.html";
const discoveredPositionsJSFilename = "js/positions.js";
module.exports = {
async logSystemInformation () {
@@ -29,13 +39,32 @@ module.exports = {
// return all available module positions
getAvailableModulePositions () {
return ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"];
return modulePositions;
},
// return if postion is on modulePositions Array (true/false)
moduleHasValidPosition (position) {
if (config.allowCustomModulePositions) return true;
if (this.getAvailableModulePositions().indexOf(position) === -1) return false;
return true;
},
getModulePositions () {
// get the lines of the index.html
const lines = fs.readFileSync(indexFileName).toString().split(os.EOL);
// loop thru the lines
lines.forEach((line) => {
// run the regex on each line
const results = regionRegEx.exec(line);
// if the regex returned something
if (results && results.length > 0) {
// get the postition parts and replace space with underscore
const positionName = results[1].replace(" ", "_");
// add it to the list
modulePositions.push(positionName);
}
});
fs.writeFileSync(discoveredPositionsJSFilename, `const modulePositions=${JSON.stringify(modulePositions)}`);
// return the list to the caller
return modulePositions;
}
};