mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-27 17:01:08 -04: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:
parent
5ea8a3469a
commit
53fc814ff8
23 changed files with 2330 additions and 1254 deletions
3
.github/workflows/automated-tests.yaml
vendored
3
.github/workflows/automated-tests.yaml
vendored
|
@ -18,7 +18,7 @@ jobs:
|
|||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.x, 20.x, 21.x]
|
||||
node-version: [20.x, 22.x]
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@v4
|
||||
|
@ -26,6 +26,7 @@ jobs:
|
|||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
check-latest: true
|
||||
cache: "npm"
|
||||
- name: "Install dependencies"
|
||||
run: |
|
||||
|
|
8
.github/workflows/electronRebuild.yaml
vendored
8
.github/workflows/electronRebuild.yaml
vendored
|
@ -6,9 +6,17 @@ jobs:
|
|||
rebuild:
|
||||
name: Run electron-rebuild
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [20.x, 22.x]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: "Use Node.js ${{ matrix.node-version }}"
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
check-latest: true
|
||||
- name: Install MagicMirror
|
||||
run: npm run install-mm
|
||||
- name: Install @electron/rebuild
|
||||
|
|
45
CHANGELOG.md
45
CHANGELOG.md
|
@ -5,6 +5,39 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
|||
|
||||
❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/#donate) With your help we can continue to improve the MagicMirror².
|
||||
|
||||
## [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)
|
||||
|
||||
## [2.27.0] - 2024-04-01
|
||||
|
||||
Thanks to: @bugsounet, @crazyscot, @illimarkangur, @jkriegshauser, @khassel, @KristjanESPERANTO, @Paranoid93, @rejas, @sdetweil and @vppencilsharpener.
|
||||
|
@ -16,7 +49,7 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T
|
|||
### Added
|
||||
|
||||
- Output of system information to the console for troubleshooting (#3328 and #3337), ignore errors under aarch64 (#3349)
|
||||
- [chore] Add `eslint-plugin-package-json` to lint the `package.json` files (#3368)
|
||||
- [core] Add `eslint-plugin-package-json` to lint the `package.json` files (#3368)
|
||||
- [weather] `showHumidity` config is now a string describing where to show this element. Supported values: "wind", "temp", "feelslike", "below", "none". (#3330)
|
||||
- electron-rebuild test suite for electron and 3rd party modules compatibility (#3392)
|
||||
- Create MM² icon and attach it to electron process (#3407)
|
||||
|
@ -28,8 +61,8 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T
|
|||
- Use node prefix for build-in modules (#3340)
|
||||
- Rework logging colors (#3350)
|
||||
- Update pm2 to v5.3.1 with no allow-ghsas (#3364)
|
||||
- [chore] Update husky and let lint-staged fix ESLint issues
|
||||
- [chore] Update dependencies including electron to v29 (#3357) and node-ical
|
||||
- [core] Update husky and let lint-staged fix ESLint issues
|
||||
- [core] Update dependencies including electron to v29 (#3357) and node-ical
|
||||
- Update translations for estonian (#3371)
|
||||
- Update electron to v29 and update other dependencies
|
||||
- [calendar] fullDay events over several days now show the left days from the first day on and 'today' on the last day
|
||||
|
@ -51,9 +84,9 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T
|
|||
- added message in case where config.js is missing the module.export line PR #3383
|
||||
- Fixed an issue where recurring events could extend past their recurrence end date (#3393)
|
||||
- Don't display any `npm WARN <....>` on install (#3399)
|
||||
- Fixed move suncalc dependency to production from dev, as it is used by clock module
|
||||
- [core] Moved suncalc dependency to production from dev, as it is used by clock module
|
||||
- [compliments] Fix mirror not responding anymore when no compliments are to be shown (#3385)
|
||||
- [chore] Fixed mastermerge workflow (#3415)
|
||||
- [core] Fixed mastermerge workflow (#3415)
|
||||
|
||||
### Deleted
|
||||
|
||||
|
@ -87,7 +120,7 @@ This release also marks the latest release by Michael Teeuw. For more info, plea
|
|||
- Update electron to v27 and update other dependencies as well as github actions
|
||||
- Update newsfeed: Use `html-to-text` instead of regex for transform description
|
||||
- Review ESLint config (#3269)
|
||||
- Updated dependencies
|
||||
- Update dependencies
|
||||
- Clock module: optionally display current moon phase in addition to rise/set times
|
||||
- electron is now per default started without gpu, if needed it must be enabled with new env var `ELECTRON_ENABLE_GPU=1` on startup (#3226)
|
||||
- Replace prettier by stylistic in ESLint config to lint JavaScript (and disable some rules for `config/config.js*` files)
|
||||
|
|
|
@ -67,11 +67,10 @@ let config = {
|
|||
module: "weather",
|
||||
position: "top_right",
|
||||
config: {
|
||||
weatherProvider: "openweathermap",
|
||||
weatherProvider: "openmeteo",
|
||||
type: "current",
|
||||
location: "New York",
|
||||
locationID: "5128581", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city
|
||||
apiKey: "YOUR_OPENWEATHER_API_KEY"
|
||||
lat: 40.776676,
|
||||
lon: -73.971321
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -79,11 +78,10 @@ let config = {
|
|||
position: "top_right",
|
||||
header: "Weather Forecast",
|
||||
config: {
|
||||
weatherProvider: "openweathermap",
|
||||
weatherProvider: "openmeteo",
|
||||
type: "forecast",
|
||||
location: "New York",
|
||||
locationID: "5128581", //ID from http://bulk.openweathermap.org/sample/city.list.json.gz; unzip the gz file and find your city
|
||||
apiKey: "YOUR_OPENWEATHER_API_KEY"
|
||||
lat: 40.776676,
|
||||
lon: -73.971321
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
16
fonts/package-lock.json
generated
16
fonts/package-lock.json
generated
|
@ -9,19 +9,19 @@
|
|||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fontsource/roboto": "^5.0.12",
|
||||
"@fontsource/roboto-condensed": "^5.0.15"
|
||||
"@fontsource/roboto": "^5.0.13",
|
||||
"@fontsource/roboto-condensed": "^5.0.16"
|
||||
}
|
||||
},
|
||||
"node_modules/@fontsource/roboto": {
|
||||
"version": "5.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.0.12.tgz",
|
||||
"integrity": "sha512-x0o17jvgoSSbS9OZnUX2+xJmVRvVCfeaYJjkS7w62iN7CuJWtMf5vJj8LqgC7ibqIkitOHVW+XssRjgrcHn62g=="
|
||||
"version": "5.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.0.13.tgz",
|
||||
"integrity": "sha512-j61DHjsdUCKMXSdNLTOxcG701FWnF0jcqNNQi2iPCDxU8seN/sMxeh62dC++UiagCWq9ghTypX+Pcy7kX+QOeQ=="
|
||||
},
|
||||
"node_modules/@fontsource/roboto-condensed": {
|
||||
"version": "5.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.0.15.tgz",
|
||||
"integrity": "sha512-0AFvcI/8JQ5+FZE12hdaE1W/1ooJUzd5XP7jD74+SP+PArsswJ+6OV/oKTasgeQeZlvGrcD3chO6yr5K4JGwzA=="
|
||||
"version": "5.0.16",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-5.0.16.tgz",
|
||||
"integrity": "sha512-pjO80g5x/hkqzWCIafvkS3JrkBDxSiTjEy4LdqQKJYrmoGx8x2AlhSUMgzIzG/ge4kT98bA7+gmm7yquzrrZ/w=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
"name": "magicmirror-fonts",
|
||||
"version": "1.0.0",
|
||||
"description": "Package for fonts use by MagicMirror² core.",
|
||||
"bugs": {
|
||||
"url": "https://github.com/MagicMirrorOrg/MagicMirror/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MagicMirrorOrg/MagicMirror"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/MagicMirrorOrg/MagicMirror/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/roboto": "^5.0.12",
|
||||
"@fontsource/roboto-condensed": "^5.0.15"
|
||||
"@fontsource/roboto": "^5.0.13",
|
||||
"@fontsource/roboto-condensed": "^5.0.16"
|
||||
}
|
||||
}
|
||||
|
|
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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -29,6 +29,7 @@ Module.register("calendar", {
|
|||
dateEndFormat: "LT",
|
||||
fullDayEventDateFormat: "MMM Do",
|
||||
showEnd: false,
|
||||
showEndsOnlyWithDuration: false,
|
||||
getRelative: 6,
|
||||
hidePrivate: false,
|
||||
hideOngoing: false,
|
||||
|
@ -388,7 +389,11 @@ Module.register("calendar", {
|
|||
|
||||
// Add endDate to dataheaders if showEnd is enabled
|
||||
if (this.config.showEnd) {
|
||||
timeWrapper.innerHTML += ` - ${CalendarUtils.capFirst(moment(event.endDate, "x").format("LT"))}`;
|
||||
if (this.config.showEndsOnlyWithDuration && event.startDate === event.endDate) {
|
||||
// no duration here, don't display end
|
||||
} else {
|
||||
timeWrapper.innerHTML += ` - ${CalendarUtils.capFirst(moment(event.endDate, "x").format("LT"))}`;
|
||||
}
|
||||
}
|
||||
|
||||
eventWrapper.appendChild(timeWrapper);
|
||||
|
@ -407,8 +412,12 @@ Module.register("calendar", {
|
|||
timeWrapper.innerHTML = CalendarUtils.capFirst(moment(event.startDate, "x").format(this.config.dateFormat));
|
||||
// Add end time if showEnd
|
||||
if (this.config.showEnd) {
|
||||
timeWrapper.innerHTML += "-";
|
||||
timeWrapper.innerHTML += CalendarUtils.capFirst(moment(event.endDate, "x").format(this.config.dateEndFormat));
|
||||
if (this.config.showEndsOnlyWithDuration && event.startDate === event.endDate) {
|
||||
// no duration here, don't display end
|
||||
} else {
|
||||
timeWrapper.innerHTML += "-";
|
||||
timeWrapper.innerHTML += CalendarUtils.capFirst(moment(event.endDate, "x").format(this.config.dateEndFormat));
|
||||
}
|
||||
}
|
||||
// For full day events we use the fullDayEventDateFormat
|
||||
if (event.fullDayEvent) {
|
||||
|
|
|
@ -15,7 +15,8 @@ Module.register("compliments", {
|
|||
morningEndTime: 12,
|
||||
afternoonStartTime: 12,
|
||||
afternoonEndTime: 17,
|
||||
random: true
|
||||
random: true,
|
||||
specialDayUnique: false
|
||||
},
|
||||
lastIndexUsed: -1,
|
||||
// Set currentweather from module
|
||||
|
@ -98,6 +99,10 @@ Module.register("compliments", {
|
|||
// Add compliments for special days
|
||||
for (let entry in this.config.compliments) {
|
||||
if (new RegExp(entry).test(date)) {
|
||||
// Only display compliments configured for the day if specialDayUnique is set to true
|
||||
if (this.config.specialDayUnique) {
|
||||
compliments.length = 0;
|
||||
}
|
||||
Array.prototype.push.apply(compliments, this.config.compliments[entry]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const Exec = require("node:child_process").exec;
|
||||
const Spawn = require("node:child_process").spawn;
|
||||
const pm2 = require("pm2");
|
||||
const fs = require("node:fs");
|
||||
|
||||
const Log = require("logger");
|
||||
|
||||
|
@ -139,6 +139,7 @@ class Updater {
|
|||
// restart MagicMiror with "pm2"
|
||||
pm2Restart () {
|
||||
Log.info("updatenotification: PM2 will restarting MagicMirror...");
|
||||
const pm2 = require("pm2");
|
||||
pm2.restart(this.PM2, (err, proc) => {
|
||||
if (err) {
|
||||
Log.error("updatenotification:[PM2] restart Error", err);
|
||||
|
@ -160,6 +161,14 @@ class Updater {
|
|||
check_PM2_Process () {
|
||||
Log.info("updatenotification: Checking PM2 using...");
|
||||
return new Promise((resolve) => {
|
||||
if (fs.existsSync("/.dockerenv")) {
|
||||
Log.info("updatenotification: Running in docker container, not using PM2 ...");
|
||||
this.usePM2 = false;
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const pm2 = require("pm2");
|
||||
pm2.connect((err) => {
|
||||
if (err) {
|
||||
Log.error("updatenotification: [PM2]", err);
|
||||
|
|
|
@ -398,14 +398,14 @@ WeatherProvider.register("openmeteo", {
|
|||
currentWeather.windFromDirection = weather.winddirection_10m_dominant;
|
||||
currentWeather.sunrise = weather.sunrise;
|
||||
currentWeather.sunset = weather.sunset;
|
||||
currentWeather.temperature = parseFloat((weather.apparent_temperature_max + weather.apparent_temperature_min) / 2);
|
||||
currentWeather.minTemperature = parseFloat(weather.apparent_temperature_min);
|
||||
currentWeather.maxTemperature = parseFloat(weather.apparent_temperature_max);
|
||||
currentWeather.weatherType = this.convertWeatherType(weather.weathercode, currentWeather.isDayTime());
|
||||
currentWeather.temperature = parseFloat((weather.temperature_2m_max + weather.temperature_2m_min) / 2);
|
||||
currentWeather.minTemperature = parseFloat(weather.temperature_2m_min);
|
||||
currentWeather.maxTemperature = parseFloat(weather.temperature_2m_max);
|
||||
currentWeather.weatherType = this.convertWeatherType(weather.weathercode, true);
|
||||
currentWeather.rain = parseFloat(weather.rain_sum);
|
||||
currentWeather.snow = parseFloat(weather.snowfall_sum * 10);
|
||||
currentWeather.precipitationAmount = parseFloat(weather.precipitation_sum);
|
||||
currentWeather.precipitationProbability = parseFloat(weather.precipitation_probability);
|
||||
currentWeather.precipitationProbability = parseFloat(weather.precipitation_hours * 100 / 24);
|
||||
currentWeather.uv_index = parseFloat(weather.uv_index_max);
|
||||
|
||||
days.push(currentWeather);
|
||||
|
@ -420,7 +420,7 @@ WeatherProvider.register("openmeteo", {
|
|||
const now = moment();
|
||||
|
||||
weathers.hourly.forEach((weather, i) => {
|
||||
if ((hours.length === 0 && weather.time.hour() <= now.hour()) || hours.length >= this.config.maxEntries) {
|
||||
if ((hours.length === 0 && weather.time <= now) || hours.length >= this.config.maxEntries) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -432,9 +432,9 @@ WeatherProvider.register("openmeteo", {
|
|||
currentWeather.windFromDirection = weather.winddirection_10m;
|
||||
currentWeather.sunrise = weathers.daily[h].sunrise;
|
||||
currentWeather.sunset = weathers.daily[h].sunset;
|
||||
currentWeather.temperature = parseFloat(weather.apparent_temperature);
|
||||
currentWeather.minTemperature = parseFloat(weathers.daily[h].apparent_temperature_min);
|
||||
currentWeather.maxTemperature = parseFloat(weathers.daily[h].apparent_temperature_max);
|
||||
currentWeather.temperature = parseFloat(weather.temperature_2m);
|
||||
currentWeather.minTemperature = parseFloat(weathers.daily[h].temperature_2m_min);
|
||||
currentWeather.maxTemperature = parseFloat(weathers.daily[h].temperature_2m_max);
|
||||
currentWeather.weatherType = this.convertWeatherType(weather.weathercode, currentWeather.isDayTime());
|
||||
currentWeather.humidity = parseFloat(weather.relativehumidity_2m);
|
||||
currentWeather.rain = parseFloat(weather.rain);
|
||||
|
|
|
@ -211,7 +211,7 @@ WeatherProvider.register("weathergov", {
|
|||
currentWeather.minTemperature = currentWeatherData.minTemperatureLast24Hours.value;
|
||||
currentWeather.maxTemperature = currentWeatherData.maxTemperatureLast24Hours.value;
|
||||
currentWeather.humidity = Math.round(currentWeatherData.relativeHumidity.value);
|
||||
currentWeather.precipitationAmount = currentWeatherData.precipitationLastHour.value;
|
||||
currentWeather.precipitationAmount = currentWeatherData.precipitationLastHour.value ? currentWeatherData.precipitationLastHour.value : currentWeatherData.precipitationLast3Hours.value;
|
||||
if (currentWeatherData.heatIndex.value !== null) {
|
||||
currentWeather.feelsLikeTemp = currentWeatherData.heatIndex.value;
|
||||
} else if (currentWeatherData.windChill.value !== null) {
|
||||
|
|
3140
package-lock.json
generated
3140
package-lock.json
generated
File diff suppressed because it is too large
Load diff
105
package.json
105
package.json
|
@ -1,7 +1,27 @@
|
|||
{
|
||||
"name": "magicmirror",
|
||||
"version": "2.27.0",
|
||||
"version": "2.28.0",
|
||||
"description": "The open source modular smart mirror platform.",
|
||||
"keywords": [
|
||||
"magic mirror",
|
||||
"magicmirror",
|
||||
"smart mirror",
|
||||
"mirror UI",
|
||||
"modular"
|
||||
],
|
||||
"homepage": "https://magicmirror.builders",
|
||||
"bugs": {
|
||||
"url": "https://github.com/MagicMirrorOrg/MagicMirror/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MagicMirrorOrg/MagicMirror"
|
||||
},
|
||||
"license": "MIT",
|
||||
"author": "Michael Teeuw",
|
||||
"contributors": [
|
||||
"https://github.com/MagicMirrorOrg/MagicMirror/graphs/contributors"
|
||||
],
|
||||
"main": "js/electron.js",
|
||||
"scripts": {
|
||||
"start": "DISPLAY=\"${DISPLAY:=:0}\" ./node_modules/.bin/electron js/electron.js",
|
||||
|
@ -28,50 +48,14 @@
|
|||
"lint:staged": "lint-staged",
|
||||
"prepare": "[ -f node_modules/.bin/husky ] && husky || echo no husky installed."
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MagicMirrorOrg/MagicMirror"
|
||||
},
|
||||
"keywords": [
|
||||
"magic mirror",
|
||||
"magicmirror",
|
||||
"smart mirror",
|
||||
"mirror UI",
|
||||
"modular"
|
||||
],
|
||||
"author": "Michael Teeuw",
|
||||
"contributors": [
|
||||
"https://github.com/MagicMirrorOrg/MagicMirror/graphs/contributors"
|
||||
],
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/MagicMirrorOrg/MagicMirror/issues"
|
||||
},
|
||||
"homepage": "https://magicmirror.builders",
|
||||
"devDependencies": {
|
||||
"@stylistic/eslint-plugin": "^1.7.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jest": "^27.9.0",
|
||||
"eslint-plugin-jsdoc": "^48.2.2",
|
||||
"eslint-plugin-package-json": "^0.12.1",
|
||||
"eslint-plugin-unicorn": "^51.0.1",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"husky": "^9.0.11",
|
||||
"jest": "^29.7.0",
|
||||
"jsdom": "^24.0.0",
|
||||
"lint-staged": "^15.2.2",
|
||||
"playwright": "^1.42.1",
|
||||
"prettier": "^3.2.5",
|
||||
"sinon": "^17.0.1",
|
||||
"stylelint": "^16.3.1",
|
||||
"stylelint-config-standard": "^36.0.0",
|
||||
"stylelint-prettier": "^5.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"electron": "^29.1.6"
|
||||
"lint-staged": {
|
||||
"*": "prettier --write",
|
||||
"*.js": "eslint --fix",
|
||||
"*.css": "stylelint --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansis": "^2.3.0",
|
||||
"ajv": "^8.16.0",
|
||||
"ansis": "^3.2.0",
|
||||
"console-stamp": "^3.1.2",
|
||||
"envsub": "^4.1.0",
|
||||
"eslint": "^8.57.0",
|
||||
|
@ -84,21 +68,38 @@
|
|||
"module-alias": "^2.2.3",
|
||||
"moment": "^2.30.1",
|
||||
"node-ical": "^0.18.0",
|
||||
"pm2": "^5.3.1",
|
||||
"pm2": "^5.4.1",
|
||||
"socket.io": "^4.7.5",
|
||||
"suncalc": "^1.9.0",
|
||||
"systeminformation": "^5.22.6"
|
||||
"systeminformation": "^5.22.11"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*": "prettier --write",
|
||||
"*.js": "eslint --fix",
|
||||
"*.css": "stylelint --fix"
|
||||
"devDependencies": {
|
||||
"@stylistic/eslint-plugin": "^1.8.1",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jest": "^28.6.0",
|
||||
"eslint-plugin-jsdoc": "^48.5.0",
|
||||
"eslint-plugin-package-json": "^0.15.0",
|
||||
"eslint-plugin-unicorn": "^54.0.0",
|
||||
"express-basic-auth": "^1.2.1",
|
||||
"husky": "^9.0.11",
|
||||
"jest": "^29.7.0",
|
||||
"jsdom": "^24.1.0",
|
||||
"lint-staged": "^15.2.7",
|
||||
"playwright": "^1.45.0",
|
||||
"prettier": "^3.3.2",
|
||||
"sinon": "^18.0.0",
|
||||
"stylelint": "^16.6.1",
|
||||
"stylelint-config-standard": "^36.0.1",
|
||||
"stylelint-prettier": "^5.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"electron": "^31.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"_moduleAliases": {
|
||||
"node_helper": "js/node_helper.js",
|
||||
"logger": "js/logger.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
let config = {
|
||||
modules: [
|
||||
{
|
||||
module: "compliments",
|
||||
position: "middle_center",
|
||||
config: {
|
||||
specialDayUnique: false,
|
||||
compliments: {
|
||||
anytime: [
|
||||
"Typical message 1",
|
||||
"Typical message 2",
|
||||
"Typical message 3"
|
||||
],
|
||||
"....-..-..": ["Special day message"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||
if (typeof module !== "undefined") { module.exports = config; }
|
|
@ -0,0 +1,22 @@
|
|||
let config = {
|
||||
modules: [
|
||||
{
|
||||
module: "compliments",
|
||||
position: "middle_center",
|
||||
config: {
|
||||
specialDayUnique: true,
|
||||
compliments: {
|
||||
anytime: [
|
||||
"Typical message 1",
|
||||
"Typical message 2",
|
||||
"Typical message 3"
|
||||
],
|
||||
"....-..-..": ["Special day message"]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||
if (typeof module !== "undefined") { module.exports = config; }
|
|
@ -54,4 +54,28 @@ describe("Compliments module", () => {
|
|||
await expect(doTest(["Remote compliment file works!"])).resolves.toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Feature specialDayUnique in compliments module", () => {
|
||||
describe("specialDayUnique is false", () => {
|
||||
beforeAll(async () => {
|
||||
await helpers.startApplication("tests/configs/modules/compliments/compliments_specialDayUnique_false.js");
|
||||
await helpers.getDocument();
|
||||
});
|
||||
|
||||
it("compliments array can contain all values", async () => {
|
||||
await expect(doTest(["Special day message", "Typical message 1", "Typical message 2", "Typical message 3"])).resolves.toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("specialDayUnique is true", () => {
|
||||
beforeAll(async () => {
|
||||
await helpers.startApplication("tests/configs/modules/compliments/compliments_specialDayUnique_true.js");
|
||||
await helpers.getDocument();
|
||||
});
|
||||
|
||||
it("compliments array contains only special value", async () => {
|
||||
await expect(doTest(["Special day message"])).resolves.toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
8
vendor/package-lock.json
generated
vendored
8
vendor/package-lock.json
generated
vendored
|
@ -9,7 +9,7 @@
|
|||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.5.1",
|
||||
"@fortawesome/fontawesome-free": "^6.5.2",
|
||||
"animate.css": "^4.1.1",
|
||||
"moment": "^2.30.1",
|
||||
"moment-timezone": "^0.5.45",
|
||||
|
@ -19,9 +19,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@fortawesome/fontawesome-free": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.1.tgz",
|
||||
"integrity": "sha512-CNy5vSwN3fsUStPRLX7fUYojyuzoEMSXPl7zSLJ8TgtRfjv24LOnOWKT2zYwaHZCJGkdyRnTmstR0P+Ah503Gw==",
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.5.2.tgz",
|
||||
"integrity": "sha512-hRILoInAx8GNT5IMkrtIt9blOdrqHOnPBH+k70aWUAqPZPgopb9G5EQJFpaBx/S8zp2fC+mPW349Bziuk1o28Q==",
|
||||
"hasInstallScript": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
|
|
8
vendor/package.json
vendored
8
vendor/package.json
vendored
|
@ -2,16 +2,16 @@
|
|||
"name": "magicmirror-vendors",
|
||||
"version": "1.0.0",
|
||||
"description": "Package for vendors use by MagicMirror² core.",
|
||||
"bugs": {
|
||||
"url": "https://github.com/MagicMirrorOrg/MagicMirror/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MagicMirrorOrg/MagicMirror"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/MagicMirrorOrg/MagicMirror/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.5.1",
|
||||
"@fortawesome/fontawesome-free": "^6.5.2",
|
||||
"animate.css": "^4.1.1",
|
||||
"moment": "^2.30.1",
|
||||
"moment-timezone": "^0.5.45",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue