From 2e9b0aecb30521010435ace6964dc710fed90cb8 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Sat, 3 Aug 2024 16:35:44 -0500 Subject: [PATCH 1/6] add support for custom regions, by detecting what is used in index.html --- CHANGELOG.md | 3 ++- js/app.js | 29 ++++++++++++++++++++--------- js/check_config.js | 22 +++++----------------- js/utils.js | 33 ++++++++++++++++++++++++++++++--- 4 files changed, 57 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0569cd369..f5003c74a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,12 +20,13 @@ _This release is scheduled to be released on 2024-10-01._ - [weather] Updated `apiVersion` default from 2.5 to 3.0 (#3424) - [core] Updated dependencies -- [core] Allow custom module positions by setting `allowCustomModulePositions` in `config.js` (fixes #3504, related to https://github.com/MagicMirrorOrg/MagicMirror/pull/3445) +- [core] Allow custom module positions by reading index.html for the defined regions (fixes #3504, fixes runtime and config:check) ### Fixed - Fixed `checks` badge in README.md - [weather] Fixed issue with the UK Met Office provider following a change in their API paths and header info. +- [core] add check for node_helper loading for multiple instances of same module (#3502) ## [2.28.0] - 2024-07-01 diff --git a/js/app.js b/js/app.js index f9313ed403..36eba3f819 100644 --- a/js/app.js +++ b/js/app.js @@ -9,6 +9,7 @@ const Log = require("logger"); const Server = require(`${__dirname}/server`); const Utils = require(`${__dirname}/utils`); const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`); +const helperhash = {}; // Get version number. global.version = require(`${__dirname}/../package.json`).version; @@ -175,14 +176,21 @@ function App () { const helperPath = `${moduleFolder}/node_helper.js`; - let loadHelper = true; - try { - fs.accessSync(helperPath, fs.R_OK); - } catch (e) { - loadHelper = false; - Log.log(`No helper found for module: ${moduleName}.`); - } + // find out if helper was loaded before for this module + // only load it once + let loadHelper = helperhash[moduleName] ? false : true; + // if this is the 1st time for this module, check for helper file + // otherwise, its already loaded, if found + if (loadHelper) { + try { + fs.accessSync(helperPath, fs.R_OK); + } catch (e) { + loadHelper = false; + Log.log(`No helper found for module: ${moduleName}.`); + } + } + // if already loaded or require successful if (loadHelper) { const Module = require(helperPath); let m = new Module(); @@ -255,6 +263,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; @@ -262,10 +273,10 @@ function App () { if (Utils.moduleHasValidPosition(module.position) || typeof (module.position) === "undefined") { 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)}`); } } diff --git a/js/check_config.js b/js/check_config.js index 6a514de3eb..2df47b7df8 100644 --- a/js/check_config.js +++ b/js/check_config.js @@ -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)); } diff --git a/js/utils.js b/js/utils.js index df2e91757d..d1a8e43217 100644 --- a/js/utils.js +++ b/js/utils.js @@ -1,7 +1,16 @@ 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"; + module.exports = { async logSystemInformation () { @@ -29,13 +38,31 @@ 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); + } + }); + // return the list to the caller + return modulePositions; } }; From a7d05ca04c153c8153b3337f53147022130a10a3 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Sun, 4 Aug 2024 16:30:56 -0500 Subject: [PATCH 2/6] add fix for main.js having hard coded positions, start on testcases --- index.html | 1 + js/app.js | 1 + js/loader.js | 4 ++- js/main.js | 3 +- js/utils.js | 4 +++ tests/configs/customregions.js | 23 ++++++++++++++ tests/e2e/helpers/global-setup.js | 31 +++++++++++++++++++ .../e2e/modules/custom_module_regions_spec.js | 26 ++++++++++++++++ 8 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 tests/configs/customregions.js create mode 100644 tests/e2e/modules/custom_module_regions_spec.js diff --git a/index.html b/index.html index b97124be10..09addfe37f 100644 --- a/index.html +++ b/index.html @@ -55,6 +55,7 @@ + diff --git a/js/app.js b/js/app.js index 36eba3f819..fcbd5e0c43 100644 --- a/js/app.js +++ b/js/app.js @@ -271,6 +271,7 @@ function App () { if (module.disabled) continue; if (module.module) { if (Utils.moduleHasValidPosition(module.position) || typeof (module.position) === "undefined") { + console.log(`pushing module=${module.module}`); modules.push(module.module); } else { Log.warn("Invalid module position found for this configuration:" + `\n${JSON.stringify(module, null, 2)}`); diff --git a/js/loader.js b/js/loader.js index 1ce6f27bd1..e0dff9fa8e 100644 --- a/js/loader.js +++ b/js/loader.js @@ -50,7 +50,9 @@ 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)); + console.log(`all modules pre=${JSON.stringify(config.modules)}`); + const AllModules = config.modules.filter((module) => (module.module !== undefined) && (MM.getAvailableModulePositions.indexOf(module.position) > -1 || typeof (module.position) === "undefined")); + console.log(`all modules=${JSON.stringify(AllModules)}`); return AllModules; }; diff --git a/js/main.js b/js/main.js index bc69f0bb93..e50a67f0fc 100644 --- a/js/main.js +++ b/js/main.js @@ -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) { diff --git a/js/utils.js b/js/utils.js index d1a8e43217..ede7f546c2 100644 --- a/js/utils.js +++ b/js/utils.js @@ -10,6 +10,7 @@ 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 = { @@ -38,6 +39,7 @@ module.exports = { // return all available module positions getAvailableModulePositions () { + console.log(`modules positions=${JSON.stringify(modulePositions)}`); return modulePositions; }, @@ -58,10 +60,12 @@ module.exports = { if (results && results.length > 0) { // get the postition parts and replace space with underscore const positionName = results[1].replace(" ", "_"); + console.log(`saving module position=${positionName}`); // add it to the list modulePositions.push(positionName); } }); + fs.writeFileSync(discoveredPositionsJSFilename, `const modulePositions=${JSON.stringify(modulePositions)}`); // return the list to the caller return modulePositions; } diff --git a/tests/configs/customregions.js b/tests/configs/customregions.js new file mode 100644 index 0000000000..5fe4ee28c4 --- /dev/null +++ b/tests/configs/customregions.js @@ -0,0 +1,23 @@ +let config = { + modules: + // Using exotic content. This is why don't accept go to JSON configuration file + (() => { + let positions = ["row3_left", "top3_left1"]; + let modules = Array(); + for (let idx in positions) { + modules.push({ + module: "helloworld", + position: positions[idx], + config: { + text: `Text in ${positions[idx]}` + } + }); + } + return modules; + })() +}; + +/*************** DO NOT EDIT THE LINE BELOW ***************/ +if (typeof module !== "undefined") { + module.exports = config; +} diff --git a/tests/e2e/helpers/global-setup.js b/tests/e2e/helpers/global-setup.js index 31a3e036c2..70bb3fe284 100644 --- a/tests/e2e/helpers/global-setup.js +++ b/tests/e2e/helpers/global-setup.js @@ -1,5 +1,15 @@ +const os = require("node:os"); +const fs = require("node:fs"); const jsdom = require("jsdom"); +const indexFile = "index.html"; +const cssFile = "css/custom.css"; +var indexData = []; +var cssData = []; +const sampleCss = ".region.row3 { top: 0;}\ +.region.row3.left {top: 100%;}"; + + exports.startApplication = async (configFilename, exec) => { jest.resetModules(); if (global.app) { @@ -91,3 +101,24 @@ exports.testMatch = async (element, regex) => { expect(elem.textContent).toMatch(regex); return true; }; + +exports.fixupIndex = () => { + cssData = fs.readFileSync(cssFile).toString(); + indexData = fs.readFileSync(indexFile).toString(); + let workIndexLines = indexData.split(os.EOL); + for (let l in workIndexLines) { + if (workIndexLines[l].includes("region top right")) { + workIndexLines.splice(l, 0, "
"); + break; + } + } + fs.writeFileSync(indexFile, workIndexLines.join(os.EOL), { flush: true }); + fs.writeFileSync(cssFile, sampleCss, { flush: true }); +}; + +exports.restoreIndex = () => { + if (indexData.length > 1) { + fs.writeFileSync(indexFile, indexData, { flush: true }); + fs.writeFileSync(cssFile, cssData, { flush: true }); + } +}; diff --git a/tests/e2e/modules/custom_module_regions_spec.js b/tests/e2e/modules/custom_module_regions_spec.js new file mode 100644 index 0000000000..9791dd149b --- /dev/null +++ b/tests/e2e/modules/custom_module_regions_spec.js @@ -0,0 +1,26 @@ +const helpers = require("../helpers/global-setup"); + +helpers.fixupIndex(); + +describe("Position of modules", () => { + beforeAll(async () => { + await helpers.startApplication("tests/configs/customregions.js"); + await helpers.getDocument(); + }); + afterAll(async () => { + await helpers.stopApplication(); + }); + + const positions = ["row3_left", "top3_left1"]; + + for (const position of positions) { + const className = position.replace("_", "."); + it(`should show text in ${position}`, async () => { + const elem = await helpers.waitForElement(`.${className}`); + expect(elem).not.toBeNull(); + expect(elem.textContent).toContain(`Text in ${position}`); + }); + } +}); + +helpers.restoreIndex(); From 7fe1f508d114e57ce8dd13094940a6360ee6f654 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Sat, 17 Aug 2024 14:13:54 -0500 Subject: [PATCH 3/6] add testcases for custom module regions --- CHANGELOG.md | 2 +- js/app.js | 1 - js/loader.js | 2 - js/utils.js | 2 - tests/e2e/custom_module_regions_spec.js | 32 +++++++++++ tests/e2e/helpers/global-setup.js | 54 +++++++++++++------ .../e2e/modules/custom_module_regions_spec.js | 26 --------- 7 files changed, 71 insertions(+), 48 deletions(-) create mode 100644 tests/e2e/custom_module_regions_spec.js delete mode 100644 tests/e2e/modules/custom_module_regions_spec.js diff --git a/CHANGELOG.md b/CHANGELOG.md index f5003c74a9..18d6659c69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,7 @@ _This release is scheduled to be released on 2024-10-01._ - [weather] Updated `apiVersion` default from 2.5 to 3.0 (#3424) - [core] Updated dependencies -- [core] Allow custom module positions by reading index.html for the defined regions (fixes #3504, fixes runtime and config:check) +- [core] Allow custom module positions by reading index.html for the defined regions (fixes #3504, fixes runtime and config:check, add testcases) ### Fixed diff --git a/js/app.js b/js/app.js index d51f203afc..d5a3c2a409 100644 --- a/js/app.js +++ b/js/app.js @@ -273,7 +273,6 @@ function App () { if (module.disabled) continue; if (module.module) { if (Utils.moduleHasValidPosition(module.position) || typeof (module.position) === "undefined") { - console.log(`pushing module=${module.module}`); modules.push(module.module); } else { Log.warn("Invalid module position found for this configuration:" + `\n${JSON.stringify(module, null, 2)}`); diff --git a/js/loader.js b/js/loader.js index e0dff9fa8e..e8dff1907c 100644 --- a/js/loader.js +++ b/js/loader.js @@ -50,9 +50,7 @@ const Loader = (function () { * @returns {object[]} module data as configured in config */ const getAllModules = function () { - console.log(`all modules pre=${JSON.stringify(config.modules)}`); const AllModules = config.modules.filter((module) => (module.module !== undefined) && (MM.getAvailableModulePositions.indexOf(module.position) > -1 || typeof (module.position) === "undefined")); - console.log(`all modules=${JSON.stringify(AllModules)}`); return AllModules; }; diff --git a/js/utils.js b/js/utils.js index ede7f546c2..a8211a3a7b 100644 --- a/js/utils.js +++ b/js/utils.js @@ -39,7 +39,6 @@ module.exports = { // return all available module positions getAvailableModulePositions () { - console.log(`modules positions=${JSON.stringify(modulePositions)}`); return modulePositions; }, @@ -60,7 +59,6 @@ module.exports = { if (results && results.length > 0) { // get the postition parts and replace space with underscore const positionName = results[1].replace(" ", "_"); - console.log(`saving module position=${positionName}`); // add it to the list modulePositions.push(positionName); } diff --git a/tests/e2e/custom_module_regions_spec.js b/tests/e2e/custom_module_regions_spec.js new file mode 100644 index 0000000000..411c65e941 --- /dev/null +++ b/tests/e2e/custom_module_regions_spec.js @@ -0,0 +1,32 @@ +const helpers = require("./helpers/global-setup"); + +describe("Custom Position of modules", () => { + beforeAll(async () => { + await helpers.fixupIndex(); + await helpers.startApplication("tests/configs/customregions.js"); + await helpers.getDocument(); + }); + afterAll(async () => { + await helpers.stopApplication(); + await helpers.restoreIndex(); + }); + + const positions = ["row3_left", "top3_left1"]; + + for (let i in positions) { + const className = positions[i].replace("_", "."); + if (i === 0) { + it(`should show text in ${positions[i]}`, async () => { + const elem = await helpers.waitForElement(`.${className}`); + expect(elem).not.toBeNull(); + expect(elem.textContent).toContain(`Text in ${positions[i]}`); + }); + } + else { + it(`should NOT show text in ${positions[i]}`, async () => { + const elem = await helpers.waitForElement(`.${className}`, "", 1500); + expect(elem).toBeNull(); + }, 1510); + } + } +}); diff --git a/tests/e2e/helpers/global-setup.js b/tests/e2e/helpers/global-setup.js index 70bb3fe284..ef90c0fdd9 100644 --- a/tests/e2e/helpers/global-setup.js +++ b/tests/e2e/helpers/global-setup.js @@ -2,13 +2,18 @@ const os = require("node:os"); const fs = require("node:fs"); const jsdom = require("jsdom"); -const indexFile = "index.html"; -const cssFile = "css/custom.css"; +const indexFile = `${__dirname}/../../../index.html`; +const cssFile = `${__dirname}/../../../css/custom.css`; +const sampleCss = [ + ".region.row3 {", + " top: 0;", + "}", + ".region.row3.left {", + " top: 100%;", + "}" +]; var indexData = []; var cssData = []; -const sampleCss = ".region.row3 { top: 0;}\ -.region.row3.left {top: 100%;}"; - exports.startApplication = async (configFilename, exec) => { jest.resetModules(); @@ -55,11 +60,12 @@ exports.getDocument = () => { }); }; -exports.waitForElement = (selector, ignoreValue = "") => { +exports.waitForElement = (selector, ignoreValue = "", timeout = 0) => { return new Promise((resolve) => { let oldVal = "dummy12345"; + let element = null; const interval = setInterval(() => { - const element = document.querySelector(selector); + element = document.querySelector(selector); if (element) { let newVal = element.textContent; if (newVal === oldVal) { @@ -74,6 +80,12 @@ exports.waitForElement = (selector, ignoreValue = "") => { } } }, 100); + if (timeout !== 0) { + setTimeout(() => { + if (interval) clearInterval(interval); + resolve(null); + }, timeout); + } }); }; @@ -102,23 +114,33 @@ exports.testMatch = async (element, regex) => { return true; }; -exports.fixupIndex = () => { - cssData = fs.readFileSync(cssFile).toString(); - indexData = fs.readFileSync(indexFile).toString(); +exports.fixupIndex = async () => { + // read and save the git level index file + indexData = (await fs.promises.readFile(indexFile)).toString(); + // make lines of the content let workIndexLines = indexData.split(os.EOL); + // loop thru the lines to find place to insert new region for (let l in workIndexLines) { if (workIndexLines[l].includes("region top right")) { - workIndexLines.splice(l, 0, "
"); + // insert a new line with new region definition + workIndexLines.splice(l, 0, "
"); break; } } - fs.writeFileSync(indexFile, workIndexLines.join(os.EOL), { flush: true }); - fs.writeFileSync(cssFile, sampleCss, { flush: true }); + // write out the new index.html file, not append + await fs.promises.writeFile(indexFile, workIndexLines.join(os.EOL), { flush: true }); + // read in the current custom.css + cssData = (await fs.promises.readFile(cssFile)).toString(); + // write out the custom.css for this testcase, matching the new region name + await fs.promises.writeFile(cssFile, sampleCss.join(os.EOL), { flush: true }); }; -exports.restoreIndex = () => { +exports.restoreIndex = async () => { + // if we read in data if (indexData.length > 1) { - fs.writeFileSync(indexFile, indexData, { flush: true }); - fs.writeFileSync(cssFile, cssData, { flush: true }); + //write out saved index.html + await fs.promises.writeFile(indexFile, indexData, { flush: true }); + // write out saved custom.css + await fs.promises.writeFile(cssFile, cssData, { flush: true }); } }; diff --git a/tests/e2e/modules/custom_module_regions_spec.js b/tests/e2e/modules/custom_module_regions_spec.js deleted file mode 100644 index 9791dd149b..0000000000 --- a/tests/e2e/modules/custom_module_regions_spec.js +++ /dev/null @@ -1,26 +0,0 @@ -const helpers = require("../helpers/global-setup"); - -helpers.fixupIndex(); - -describe("Position of modules", () => { - beforeAll(async () => { - await helpers.startApplication("tests/configs/customregions.js"); - await helpers.getDocument(); - }); - afterAll(async () => { - await helpers.stopApplication(); - }); - - const positions = ["row3_left", "top3_left1"]; - - for (const position of positions) { - const className = position.replace("_", "."); - it(`should show text in ${position}`, async () => { - const elem = await helpers.waitForElement(`.${className}`); - expect(elem).not.toBeNull(); - expect(elem.textContent).toContain(`Text in ${position}`); - }); - } -}); - -helpers.restoreIndex(); From 4afdd256d286705e45970d82f13b81de0ab51cdb Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Sat, 17 Aug 2024 14:28:43 -0500 Subject: [PATCH 4/6] fix race condition in testcase --- tests/e2e/custom_module_regions_spec.js | 32 ++++++++++++------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/tests/e2e/custom_module_regions_spec.js b/tests/e2e/custom_module_regions_spec.js index 411c65e941..48d09712da 100644 --- a/tests/e2e/custom_module_regions_spec.js +++ b/tests/e2e/custom_module_regions_spec.js @@ -12,21 +12,19 @@ describe("Custom Position of modules", () => { }); const positions = ["row3_left", "top3_left1"]; - - for (let i in positions) { - const className = positions[i].replace("_", "."); - if (i === 0) { - it(`should show text in ${positions[i]}`, async () => { - const elem = await helpers.waitForElement(`.${className}`); - expect(elem).not.toBeNull(); - expect(elem.textContent).toContain(`Text in ${positions[i]}`); - }); - } - else { - it(`should NOT show text in ${positions[i]}`, async () => { - const elem = await helpers.waitForElement(`.${className}`, "", 1500); - expect(elem).toBeNull(); - }, 1510); - } - } + let i = 0; + const className1 = positions[i].replace("_", "."); + let message1 = positions[i]; + it(`should show text in ${message1}`, async () => { + const elem = await helpers.waitForElement(`.${className1}`); + expect(elem).not.toBeNull(); + expect(elem.textContent).toContain(`Text in ${message1}`); + }); + i = 1; + const className2 = positions[i].replace("_", "."); + let message2 = positions[i]; + it(`should NOT show text in ${message2}`, async () => { + const elem = await helpers.waitForElement(`.${className2}`, "", 1500); + expect(elem).toBeNull(); + }, 1510); }); From 8ce819efac7964f810d0826999795a0a6a21ef12 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Tue, 20 Aug 2024 11:00:42 -0500 Subject: [PATCH 5/6] fix CHANGELOG for interim PR merges --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9db5f2669a..c06146ae71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,8 +20,8 @@ _This release is scheduled to be released on 2024-10-01._ - [weather] Updated `apiVersion` default from 2.5 to 3.0 (#3424) - [core] Updated dependencies including stylistic-eslint -- [core] Allow custom module positions by setting `allowCustomModulePositions` in `config.js` (fixes #3504, related to https://github.com/MagicMirrorOrg/MagicMirror/pull/3445) - [core] Updated SocketIO catch all to new API +- [core] Allow custom modules positions by scanning index.html for the defined regions, instead of hard coded(fixes #3504) ### Fixed From 0e44d57b58d70e52eabb52a54cb6e70fa3b5eaa8 Mon Sep 17 00:00:00 2001 From: sam detweiler Date: Tue, 27 Aug 2024 07:53:52 -0500 Subject: [PATCH 6/6] remove property no longer used --- js/defaults.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/defaults.js b/js/defaults.js index 1cbef63566..c4efa77e95 100644 --- a/js/defaults.js +++ b/js/defaults.js @@ -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: [ {