mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-08-21 04:45:17 +00:00
Release 2.28.0 (#3490)
## [2.28.0] - 2024-07-01 Thanks to: @btoconnor, @bugsounet, @JasonStieber, @khassel, @kleinmantara and @WallysWellies. > ⚠️ This release needs nodejs version >= v20 ### Added - [calendar] Added config option "showEndsOnlyWithDuration" for default calendar - [compliments] Added `specialDayUnique` config option, defaults to `false` (#3465) - [weather] Provider weathergov: Use `precipitationLast3Hours` if `precipitationLastHour` is `null` (#3124) ### Removed - [tests] delete node v18 support (#3462) ### Updated - [core] Update dependencies including electron to v31 - [core] use node >= v20 (#3462) - [core] Update `config.js.sample` to use openmeteo as weather provider which needs no api key - [tests] Use latest@version of node for `automated-tests.yaml` (#3483) - [updatenotification] Avoid using pm2 when running in docker container ### Fixed - [core] Fixed crash possibility if `module: <name>` is not defined and on `postion: <positon>` mistake (#3445) - [weather] Fixed precipitationProbability in forecast for provider openmeteo (#3446) - [weather] Fixed type=daily for provider openmeteo having no data when running after 23:00 (#3449) - [weather] Fixed type=daily for provider openmeteo showing nightly icons in forecast when current time is "nightly" (#3458) - [weather] Fixed forecast and hourly weather for provider openmeteo to use real temperatures, not apparent temperatures (#3466) - [tests] Fixed e2e tests running in docker container which needs `address: "0.0.0.0"` (#3479) --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Michael Teeuw <michael@xonaymedia.nl> Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ross Younger <crazyscot@gmail.com> Co-authored-by: Veeck <github@veeck.de> Co-authored-by: Bugsounet - Cédric <github@bugsounet.fr> Co-authored-by: jkriegshauser <joshuakr@nvidia.com> Co-authored-by: illimarkangur <116028111+illimarkangur@users.noreply.github.com> Co-authored-by: sam detweiler <sdetweil@gmail.com> Co-authored-by: vppencilsharpener <tim.pray@gmail.com> Co-authored-by: veeck <michael.veeck@nebenan.de> Co-authored-by: Paranoid93 <6515818+Paranoid93@users.noreply.github.com> Co-authored-by: Brian O'Connor <btoconnor@users.noreply.github.com> Co-authored-by: WallysWellies <59727507+WallysWellies@users.noreply.github.com> Co-authored-by: Jason Stieber <jrstieber@gmail.com>
This commit is contained in:
15
js/app.js
15
js/app.js
@@ -58,6 +58,10 @@ function App () {
|
||||
async function loadConfig () {
|
||||
Log.log("Loading config ...");
|
||||
const defaults = require(`${__dirname}/defaults`);
|
||||
if (process.env.JEST_WORKER_ID !== undefined) {
|
||||
// if we are running with jest
|
||||
defaults.address = "0.0.0.0";
|
||||
}
|
||||
|
||||
// For this check proposed to TestSuite
|
||||
// https://forum.magicmirror.builders/topic/1456/test-suite-for-magicmirror/8
|
||||
@@ -253,8 +257,15 @@ function App () {
|
||||
|
||||
let modules = [];
|
||||
for (const module of config.modules) {
|
||||
if (!modules.includes(module.module) && !module.disabled) {
|
||||
modules.push(module.module);
|
||||
if (module.disabled) continue;
|
||||
if (module.module) {
|
||||
if (Utils.moduleHasValidPosition(module.position) || typeof (module.position) === "undefined") {
|
||||
modules.push(module.module);
|
||||
} else {
|
||||
Log.warn("Invalid module position found for this configuration:", module);
|
||||
}
|
||||
} else {
|
||||
Log.warn("No module name found for this configuration:", module);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -5,6 +5,10 @@ const { Linter } = require("eslint");
|
||||
|
||||
const linter = new Linter();
|
||||
|
||||
const Ajv = require("ajv");
|
||||
|
||||
const ajv = new Ajv();
|
||||
|
||||
const rootPath = path.resolve(`${__dirname}/../`);
|
||||
const Log = require(`${rootPath}/js/logger.js`);
|
||||
|
||||
@@ -59,6 +63,68 @@ function checkConfigFile () {
|
||||
for (const error of errors) {
|
||||
Log.error(`Line ${error.line} column ${error.column}: ${error.message}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Log.info("Checking modules structure configuration... ");
|
||||
|
||||
// Make Ajv schema confguration of modules config
|
||||
// only scan "module" and "position"
|
||||
const schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
modules: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "object",
|
||||
properties: {
|
||||
module: {
|
||||
type: "string"
|
||||
},
|
||||
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"
|
||||
]
|
||||
}
|
||||
},
|
||||
required: ["module"]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// scan all modules
|
||||
const validate = ajv.compile(schema);
|
||||
const data = require(configFileName);
|
||||
|
||||
const valid = validate(data);
|
||||
if (!valid) {
|
||||
let module = validate.errors[0].instancePath.split("/")[2];
|
||||
let position = validate.errors[0].instancePath.split("/")[3];
|
||||
|
||||
Log.error(colors.red("This module configuration contains errors:"));
|
||||
Log.error(data.modules[module]);
|
||||
if (position) {
|
||||
Log.error(colors.red(`${position}: ${validate.errors[0].message}`));
|
||||
Log.error(validate.errors[0].params.allowedValues);
|
||||
} else {
|
||||
Log.error(colors.red(validate.errors[0].message));
|
||||
}
|
||||
} else {
|
||||
Log.info(colors.green("Your modules structure configuration doesn't contain errors :)"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -50,7 +50,8 @@ const Loader = (function () {
|
||||
* @returns {object[]} module data as configured in config
|
||||
*/
|
||||
const getAllModules = function () {
|
||||
return config.modules;
|
||||
const AllModules = config.modules.filter((module) => (module.module !== undefined) && (MM.getAvailableModulePositions.indexOf(module.position) > -1 || typeof (module.position) === "undefined"));
|
||||
return AllModules;
|
||||
};
|
||||
|
||||
/**
|
||||
|
11
js/main.js
11
js/main.js
@@ -450,10 +450,10 @@ 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 updateWrapperStates = function () {
|
||||
const positions = ["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 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"];
|
||||
|
||||
positions.forEach(function (position) {
|
||||
const updateWrapperStates = function () {
|
||||
modulePositions.forEach(function (position) {
|
||||
const wrapper = selectWrapper(position);
|
||||
const moduleWrappers = wrapper.getElementsByClassName("module");
|
||||
|
||||
@@ -701,7 +701,10 @@ const MM = (function () {
|
||||
showModule (module, speed, callback, options) {
|
||||
// do not change module.hidden yet, only if we really show it later
|
||||
showModule(module, speed, callback, options);
|
||||
}
|
||||
},
|
||||
|
||||
// return all available module postions.
|
||||
getAvailableModulePositions: modulePositions
|
||||
};
|
||||
}());
|
||||
|
||||
|
11
js/utils.js
11
js/utils.js
@@ -25,5 +25,16 @@ module.exports = {
|
||||
} catch (e) {
|
||||
Log.error(e);
|
||||
}
|
||||
},
|
||||
|
||||
// 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 if postion is on modulePositions Array (true/false)
|
||||
moduleHasValidPosition (position) {
|
||||
if (this.getAvailableModulePositions().indexOf(position) === -1) return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user