From 9042a98ef618b740233e2d3c2f87870055c3ccd6 Mon Sep 17 00:00:00 2001
From: Peter
Date: Fri, 22 Mar 2024 14:45:16 +0000
Subject: [PATCH 01/23] Log Service : When sql syntax error occurs, log sql in
error level. (#2443)
* Factory : nameFilter protect against multiple `-` in search term.
* LogService : When sql syntax error occurs, log sql in error level.
---
lib/Factory/BaseFactory.php | 13 ++++++++++---
lib/Service/LogService.php | 11 +++++++----
lib/Service/LogServiceInterface.php | 10 +++++-----
lib/Storage/PdoStorageService.php | 11 ++++++++---
4 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/lib/Factory/BaseFactory.php b/lib/Factory/BaseFactory.php
index 082939a82a..42ba87340f 100644
--- a/lib/Factory/BaseFactory.php
+++ b/lib/Factory/BaseFactory.php
@@ -362,8 +362,15 @@ protected function parseComparisonOperator($variable)
* @param array $params Array of parameters passed by reference
* @param bool $useRegex flag to match against a regex pattern
*/
- public function nameFilter($tableName, $tableColumn, $terms, &$body, &$params, $useRegex = false, $logicalOperator = 'OR')
- {
+ public function nameFilter(
+ $tableName,
+ $tableColumn,
+ $terms,
+ &$body,
+ &$params,
+ $useRegex = false,
+ $logicalOperator = 'OR'
+ ) {
$i = 0;
$tableAndColumn = $tableName . '.' . $tableColumn;
@@ -377,7 +384,7 @@ public function nameFilter($tableName, $tableColumn, $terms, &$body, &$params, $
$searchName = trim($searchName);
// Discard any incompatible
- if ($searchName === '-' || empty($searchName)) {
+ if (empty(ltrim($searchName, '-')) || empty($searchName)) {
continue;
}
diff --git a/lib/Service/LogService.php b/lib/Service/LogService.php
index fa35672a8d..eda228990b 100644
--- a/lib/Service/LogService.php
+++ b/lib/Service/LogService.php
@@ -1,6 +1,6 @@
mode) == 'test') {
+ if (strtolower($this->mode) == 'test' || $logAsError) {
$paramSql = '';
foreach ($params as $key => $param) {
$paramSql .= 'SET @' . $key . '=\'' . $param . '\';' . PHP_EOL;
}
- $this->log->debug($paramSql . str_replace(':', '@', $sql));
+
+ ($logAsError)
+ ? $this->log->error($paramSql . str_replace(':', '@', $sql))
+ : $this->log->debug($paramSql . str_replace(':', '@', $sql));
}
}
diff --git a/lib/Service/LogServiceInterface.php b/lib/Service/LogServiceInterface.php
index 6ffa11ced4..57674625bf 100644
--- a/lib/Service/LogServiceInterface.php
+++ b/lib/Service/LogServiceInterface.php
@@ -1,8 +1,8 @@
errorInfo[1] ?? $PDOException->getCode();
+
+ // syntax error, log the sql and params in error level.
+ if ($errorCode == 1064 && $this->log != null) {
+ $this->log->sql($sql, $params, true);
+ }
+
// Throw if we're not expected to reconnect.
if (!$reconnect) {
throw $PDOException;
}
- $errorCode = $PDOException->errorInfo[1] ?? $PDOException->getCode();
-
if ($errorCode != 2006) {
throw $PDOException;
} else {
From 6b6db379c002f3ea5c7f9abfa116219e826d9c4c Mon Sep 17 00:00:00 2001
From: Peter
Date: Fri, 22 Mar 2024 14:46:04 +0000
Subject: [PATCH 02/23] Playlist Editor : Fix issue with importing already
existing media from provider. (#2442)
---
lib/Controller/Playlist.php | 5 +++--
ui/src/playlist-editor/main.js | 13 +++++++++----
ui/src/playlist-editor/playlist.js | 9 +++++++--
3 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/lib/Controller/Playlist.php b/lib/Controller/Playlist.php
index 6d62b2fb3d..3b04978812 100644
--- a/lib/Controller/Playlist.php
+++ b/lib/Controller/Playlist.php
@@ -1,6 +1,6 @@
getIntArray('media');
- if (count($media) <= 0)
+ if (empty($media)) {
throw new InvalidArgumentException(__('Please provide Media to Assign'), 'media');
+ }
// Optional Duration
$duration = ($sanitizedParams->getInt('duration'));
diff --git a/ui/src/playlist-editor/main.js b/ui/src/playlist-editor/main.js
index 4d07dcacd6..9ad43e42bc 100644
--- a/ui/src/playlist-editor/main.js
+++ b/ui/src/playlist-editor/main.js
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2023 Xibo Signage Ltd
+ * Copyright (C) 2024 Xibo Signage Ltd
*
- * Xibo - Digital Signage - http://www.xibo.org.uk
+ * Xibo - Digital Signage - https://xibosignage.com
*
* This file is part of Xibo.
*
@@ -289,8 +289,13 @@ pE.selectObject = function({
// simulate to add those items to a object
if (target.data('type') == 'region') {
pE.importFromProvider(this.toolbar.selectedQueue).then((res) => {
- // Add media queue to playlist
- this.playlist.addMedia(res, positionToAdd);
+ // If res is empty, it means that the import failed
+ if (res.length === 0) {
+ console.error(errorMessagesTrans.failedToImportMedia);
+ } else {
+ // Add media queue to playlist
+ this.playlist.addMedia(res, positionToAdd);
+ }
}).catch(function() {
toastr.error(errorMessagesTrans.importingMediaFailed);
});
diff --git a/ui/src/playlist-editor/playlist.js b/ui/src/playlist-editor/playlist.js
index 9cae4198e9..52036a7d95 100644
--- a/ui/src/playlist-editor/playlist.js
+++ b/ui/src/playlist-editor/playlist.js
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 Xibo Signage Ltd
+ * Copyright (C) 2024 Xibo Signage Ltd
*
* Xibo - Digital Signage - https://xibosignage.com
*
@@ -167,7 +167,12 @@ Playlist.prototype.addObject = function(
if (draggableType == 'media') { // Adding media from search tab to a region
if ($(draggable).hasClass('from-provider')) {
pE.importFromProvider([$(draggable).data('providerData')]).then((res) => {
- this.addMedia(res, addToPosition);
+ // If res is empty, it means that the import failed
+ if (res.length === 0) {
+ console.error(errorMessagesTrans.failedToImportMedia);
+ } else {
+ this.addMedia(res, addToPosition);
+ }
}).catch(function() {
toastr.error(errorMessagesTrans.importingMediaFailed);
});
From 974b7a7046550d26099df22c75c9e89c0b72f216 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mauro=20Ferr=C3=A3o?=
Date: Tue, 26 Mar 2024 10:40:33 +0000
Subject: [PATCH 03/23] Inline Playlist Editor: Rich text same colour as
layout's (#2447)
relates to xibosignage/xibo#3377
---
ui/src/helpers/form-helpers.js | 47 ++++++++++++++++++++++++----------
1 file changed, 34 insertions(+), 13 deletions(-)
diff --git a/ui/src/helpers/form-helpers.js b/ui/src/helpers/form-helpers.js
index 19bb8df893..ea0582f4ae 100644
--- a/ui/src/helpers/form-helpers.js
+++ b/ui/src/helpers/form-helpers.js
@@ -539,14 +539,24 @@ const formHelpers = function() {
// COLORS
// Background color for the editor
- const backgroundColor =
- (
- this.mainObject != undefined &&
- typeof this.mainObject.backgroundColor != 'undefined' &&
- this.mainObject.backgroundColor != null
- ) ?
- this.mainObject.backgroundColor :
- this.defaultBackgroundColor;
+ let backgroundColor = this.defaultBackgroundColor;
+
+ // From layout editor
+ if (
+ this.mainObject != undefined &&
+ typeof this.mainObject.backgroundColor != 'undefined' &&
+ this.mainObject.backgroundColor != null
+ ) {
+ backgroundColor = this.mainObject.backgroundColor;
+ }
+
+ // From inline playlist editor
+ if (
+ this.namespace.inline &&
+ lD && lD.layout && lD.layout.backgroundColor
+ ) {
+ backgroundColor = lD.layout.backgroundColor;
+ }
// Choose a complementary color
const color = $c.complement(backgroundColor);
@@ -1936,14 +1946,25 @@ const formHelpers = function() {
});
// Add same background colour to editor container as the layout's
- const backgroundColor =
- (
+ let backgroundColor = self.defaultBackgroundColor;
+
+ // From layout editor
+ if (
self.mainObject != undefined &&
typeof self.mainObject.backgroundColor != 'undefined' &&
self.mainObject.backgroundColor != null
- ) ?
- self.mainObject.backgroundColor :
- self.defaultBackgroundColor;
+ ) {
+ backgroundColor = self.mainObject.backgroundColor;
+ }
+
+ // From inline playlist editor
+ if (
+ self.namespace.inline &&
+ lD && lD.layout && lD.layout.backgroundColor
+ ) {
+ backgroundColor = lD.layout.backgroundColor;
+ }
+
$editorContainer.parent().css('background-color', backgroundColor);
// Get button container
From c4b20e92e53fff2edaf42eac26693fcbdd303977 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mauro=20Ferr=C3=A3o?=
Date: Tue, 26 Mar 2024 10:41:46 +0000
Subject: [PATCH 04/23] Editor: Can't edit sharing for a widget in a zone
(#2445)
relates to xibosignage/xibo#3372
---
ui/src/layout-editor/main.js | 14 ++++++++++----
ui/src/templates/context-menu.hbs | 2 +-
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/ui/src/layout-editor/main.js b/ui/src/layout-editor/main.js
index 31118362bd..db76f64980 100644
--- a/ui/src/layout-editor/main.js
+++ b/ui/src/layout-editor/main.js
@@ -3003,10 +3003,13 @@ lD.openContextMenu = function(obj, position = {x: 0, y: 0}) {
layoutObject.type === 'element-group'
);
- // If target is a frame, send single widget info
+ // If target is a frame or zone, send single widget info
const singleWidget = (
layoutObject.type === 'region' &&
- layoutObject.subType === 'frame'
+ (
+ layoutObject.subType === 'frame' ||
+ layoutObject.subType === 'zone'
+ )
) ? Object.values(layoutObject.widgets)[0] : {};
// If target is group or element group, send parent widget
@@ -3397,12 +3400,15 @@ lD.openContextMenu = function(obj, position = {x: 0, y: 0}) {
const property = target.data('property');
const propertyType = target.data('propertyType');
- // If we're editing permissions and it's a frame
+ // If we're editing permissions and it's a frame ( or zone )
// edit the widget's permissions instead
if (
property === 'PermissionsWidget' &&
layoutObject.type === 'region' &&
- layoutObject.subType === 'frame'
+ (
+ layoutObject.subType === 'frame' ||
+ layoutObject.subType === 'zone'
+ )
) {
// Call edit for widget instead
const regionWidget = Object.values(layoutObject.widgets)[0];
diff --git a/ui/src/templates/context-menu.hbs b/ui/src/templates/context-menu.hbs
index c13b848a59..ee2ef59151 100644
--- a/ui/src/templates/context-menu.hbs
+++ b/ui/src/templates/context-menu.hbs
@@ -67,7 +67,7 @@
{{/if}}
- {{#if isFrame}}
+ {{#if isFrameOrZone}}
{{#if widget.isPermissionsModifiable}}
]]>
From 24c90f17aef61fd5bb78cf3f6ad245b46c422552 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mauro=20Ferr=C3=A3o?=
Date: Tue, 26 Mar 2024 15:41:51 +0000
Subject: [PATCH 07/23] Stock Template 2: Remove Items Per Page option (#2451)
relates to xibosignage/xibo#3389
---
modules/templates/stock-static.xml | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/modules/templates/stock-static.xml b/modules/templates/stock-static.xml
index 8467f5046c..d9bf8bc87c 100644
--- a/modules/templates/stock-static.xml
+++ b/modules/templates/stock-static.xml
@@ -495,9 +495,7 @@ $(target).xiboLayoutAnimate(properties);
The format to apply to all dates returned by the Widget.
#DATE_FORMAT#
-
- Items per Page
- This is the intended number of items on each page.
+
1
From b9497f106b17be1ecdca276ccaba5eac4e0cf762 Mon Sep 17 00:00:00 2001
From: Dan Garner
Date: Thu, 28 Mar 2024 16:47:05 +0000
Subject: [PATCH 08/23] User: update helptext to be clearer (#2461)
fixes xibosignage/xibo#3376
---
views/user-form-preferences.twig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/views/user-form-preferences.twig b/views/user-form-preferences.twig
index da9bc5162e..defbb864da 100644
--- a/views/user-form-preferences.twig
+++ b/views/user-form-preferences.twig
@@ -52,7 +52,7 @@
{% endif %}
{% set title %}{% trans "Force current Library duration?" %}{% endset %}
- {% set helpText %}{% trans "Assign all Media items based on their Library duration, and make it sticky so that changes in the library are not pulled into Layouts." %}{% endset %}
+ {% set helpText %}{% trans "Assign all Media items to Playlists based on their Library duration, and make it sticky so that changes in the library are not pulled into Layouts." %}{% endset %}
{{ forms.checkbox("useLibraryDuration", title, currentUser.getOptionValue("useLibraryDuration", 0), helpText) }}
{% set title %}{% trans "Auto show thumbnail column?" %}{% endset %}
From 55adf27de9e1807d2734978b1b16e727bb23ff20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mauro=20Ferr=C3=A3o?=
Date: Tue, 2 Apr 2024 10:42:41 +0100
Subject: [PATCH 09/23] Editor: Layout exchange cards open new tab when
selected (#2459)
relates to xibosignage/xibo#3393
---
ui/src/style/toolbar.scss | 11 ++++++++---
ui/src/templates/toolbar-card-layout-template.hbs | 12 +++++++++---
ui/src/templates/toolbar-card-media.hbs | 12 +++++++++---
3 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/ui/src/style/toolbar.scss b/ui/src/style/toolbar.scss
index 63558cc579..15456e9858 100644
--- a/ui/src/style/toolbar.scss
+++ b/ui/src/style/toolbar.scss
@@ -493,20 +493,25 @@
}
.provider {
- background-color: $xibo-color-neutral-0;
position: absolute;
opacity: 0.6;
bottom: 0;
right: 0;
- width: 60%;
+ width: 60px;
+ height: 40px;
+ display: flex;
+ justify-content: flex-end;
+ align-items: flex-end;
&:hover {
opacity: 0.8;
}
img {
- width: 100%;
+ max-width: 100%;
+ max-height: 100%;
padding: 2px 6px;
+ background-color: $xibo-color-neutral-0;
}
}
diff --git a/ui/src/templates/toolbar-card-layout-template.hbs b/ui/src/templates/toolbar-card-layout-template.hbs
index c68be5dd58..482f22f95c 100644
--- a/ui/src/templates/toolbar-card-layout-template.hbs
+++ b/ui/src/templates/toolbar-card-layout-template.hbs
@@ -11,9 +11,15 @@
{{#if provider}}
-
-
-
+ {{#neq provider.link "#"}}
+
+
+
+ {{else}}
+
+
+
+ {{/neq}}
{{/if}}
{{#if duration}}
diff --git a/ui/src/templates/toolbar-card-media.hbs b/ui/src/templates/toolbar-card-media.hbs
index 8e1699b76c..2d1e483f38 100644
--- a/ui/src/templates/toolbar-card-media.hbs
+++ b/ui/src/templates/toolbar-card-media.hbs
@@ -32,9 +32,15 @@
{{/eq}}
{{#if provider}}
-
-
-
+ {{#neq provider.link "#"}}
+
+
+
+ {{else}}
+
+
+
+ {{/neq}}
{{/if}}
{{#if mediaDuration}}
From 31e71dfbf8e12dd83687a0155feb21d3bee96280 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mauro=20Ferr=C3=A3o?=
Date: Tue, 2 Apr 2024 10:43:06 +0100
Subject: [PATCH 10/23] Widget: Required elements only work per widget (#2457)
relates to xibosignage/xibo#3379
- Warning message for required elements
- Sample data shown as info
---
lib/Entity/Layout.php | 26 ----
ui/src/editor-core/properties-panel.js | 8 +-
ui/src/layout-editor/viewer.js | 169 +++++++++++++++++--------
ui/src/style/layout-editor.scss | 35 +++--
ui/src/templates/forms/widget.hbs | 4 +
5 files changed, 153 insertions(+), 89 deletions(-)
diff --git a/lib/Entity/Layout.php b/lib/Entity/Layout.php
index a17ca54872..6214eecd15 100644
--- a/lib/Entity/Layout.php
+++ b/lib/Entity/Layout.php
@@ -1812,32 +1812,6 @@ public function assessWidgetStatus(Module $module, Widget $widget, int &$status)
$template
->decorateProperties($widget)
->validateProperties('status');
- } else if ($templateId === 'elements' && $module->hasRequiredElements()) {
- // Make sure our required element is present.
- $providedElements = [];
-
- $widgetElements = $widget->getOptionValue('elements', null);
- if (!empty($widgetElements)) {
- // Elements will be JSON
- $widgetElements = json_decode($widgetElements, true);
-
- // go through the arrays to get properties array inside of elements
- // find fontFamily property, add it to fonts array if we do not already have it there
- foreach (($widgetElements ?? []) as $widgetElement) {
- foreach (($widgetElement['elements'] ?? []) as $element) {
- $providedElements[] = $element['id'];
- }
- }
- }
-
- $missingElements = array_diff($module->requiredElements, $providedElements);
-
- if (count($missingElements) > 0) {
- throw new NotFoundException(
- __('Missing one or more required elements'),
- implode(',', $missingElements),
- );
- }
}
// If we have validator interfaces, then use it now
diff --git a/ui/src/editor-core/properties-panel.js b/ui/src/editor-core/properties-panel.js
index 86d22681bc..b17345d766 100644
--- a/ui/src/editor-core/properties-panel.js
+++ b/ui/src/editor-core/properties-panel.js
@@ -575,11 +575,11 @@ PropertiesPanel.prototype.render = function(
dataToRender.repeatDataActive = hasData;
// Check required elements
- const errorMessage = target.checkRequiredElements();
+ const warningMessage = target.checkRequiredElements();
- if (errorMessage != '') {
- dataToRender.showErrorMessage = true;
- dataToRender.errorMessage = errorMessage;
+ if (warningMessage != '') {
+ dataToRender.showWarningMessage = true;
+ dataToRender.warningMessage = warningMessage;
}
}
diff --git a/ui/src/layout-editor/viewer.js b/ui/src/layout-editor/viewer.js
index d64877b0e3..45b62eb950 100644
--- a/ui/src/layout-editor/viewer.js
+++ b/ui/src/layout-editor/viewer.js
@@ -1650,7 +1650,7 @@ Viewer.prototype.renderElementContent = function(
template.stencil : template.parent.stencil;
let hbsTemplate = Handlebars.compile(
(stencil?.hbs) ?
- stencil.hbs:
+ stencil.hbs :
'',
);
@@ -1661,7 +1661,7 @@ Viewer.prototype.renderElementContent = function(
) {
const styleTemplate = Handlebars.compile(
(stencil?.style) ?
- stencil.style:
+ stencil.style :
'',
);
@@ -1853,7 +1853,7 @@ Viewer.prototype.renderElementContent = function(
}
if (element.elementType === 'dataset' && elData) {
- if (extendOverrideKey !==null) {
+ if (extendOverrideKey !== null) {
convertedProperties[extendOverrideKey] =
elData.hasOwnProperty(convertedProperties.datasetField) ?
elData[convertedProperties.datasetField] : '';
@@ -1965,18 +1965,28 @@ Viewer.prototype.validateElement = function(
'canvas',
);
- // Get error message ( from element or group )
+ // Get error message container
let $messageContainer = (hasGroup) ?
- $groupContainer.find('> .invalid-parent') :
- $elementContainer.find('> .invalid-parent');
+ $groupContainer.find('> .message-container') :
+ $elementContainer.find('> .message-container');
+
+ // If there's no message container, add it
+ if ($messageContainer.length === 0) {
+ $messageContainer = $('');
+
+ if (hasGroup) {
+ $messageContainer.appendTo($groupContainer);
+ } else {
+ $messageContainer.appendTo($elementContainer);
+ }
+ }
+
+ // Get error message
+ let $errorMessage = $messageContainer.find('.error-message');
// Is widget not valid?
const isNotValid = (
- !$.isEmptyObject(parentWidget.validateData) ||
- (
- parentWidget.requiredElements &&
- parentWidget.requiredElements.valid === false
- )
+ !$.isEmptyObject(parentWidget.validateData)
);
// If parent widget isn't valid, show error message
@@ -1984,19 +1994,75 @@ Viewer.prototype.validateElement = function(
const errorArray = [];
// Create message container if it doesn't exist
- if ($messageContainer.length === 0) {
- $messageContainer = $(
- `
+ if ($errorMessage.length === 0) {
+ $errorMessage = $(
+ `
+
+
`);
+
+ if (hasGroup) {
+ // Remove message from element if we're going to create the group one
+ $elementContainer.find('.error-message').remove();
+ }
+
+ $errorMessage.appendTo($messageContainer);
+ }
+
+ // Request message
+ (parentWidget.validateData.errorMessage) &&
+ errorArray.push(
+ '
' +
+ parentWidget.validateData.errorMessage +
+ '
');
+
+ // Sample data message
+ (parentWidget.validateData.sampleDataMessage) &&
+ errorArray.push(
+ '
( ' +
+ parentWidget.validateData.sampleDataMessage +
+ ' )
');
+
+ // Set title/tooltip
+ $errorMessage.tooltip('dispose')
+ .prop('title', '
' +
+ errorArray.join('') + '
');
+ $errorMessage.tooltip();
+
+ // Show tooltip
+ $errorMessage.removeClass('d-none');
+ } else {
+ // Remove error message
+ $errorMessage.remove();
+ }
+
+ // Get warning message ( from element or group )
+ let $warningMessage = (hasGroup) ?
+ $groupContainer.find('.warning-message') :
+ $elementContainer.find('.warning-message');
+
+ // Needs warning message?
+ const needsWarningMessage = (
+ parentWidget.requiredElements &&
+ parentWidget.requiredElements.valid === false
+ );
+
+ // Warning message needed
+ if (needsWarningMessage) {
+ const errorArray = [];
+
+ // Create message container if it doesn't exist
+ if ($warningMessage.length === 0) {
+ $warningMessage = $(
+ `
`);
if (hasGroup) {
// Remove message from element if we're going to create the group one
- $elementContainer.find('> .invalid-parent').remove();
- $messageContainer.appendTo($groupContainer);
- } else {
- $messageContainer.appendTo($elementContainer);
+ $elementContainer.find('.warning-message').remove();
}
+
+ $warningMessage.appendTo($messageContainer);
}
// Check required elements
@@ -2018,31 +2084,17 @@ Viewer.prototype.validateElement = function(
requiredElementsErrorMessage +
'');
- // Request message
- (parentWidget.validateData.errorMessage) &&
- errorArray.push(
- '
' +
- parentWidget.validateData.errorMessage +
- '
');
-
- // Sample data message
- (parentWidget.validateData.sampleDataMessage) &&
- errorArray.push(
- '
( ' +
- parentWidget.validateData.sampleDataMessage +
- ' )
');
-
// Set title/tooltip
- $messageContainer.tooltip('dispose')
+ $warningMessage.tooltip('dispose')
.prop('title', '
' +
- errorArray.join('') + '
');
- $messageContainer.tooltip();
+ errorArray.join('') + '
');
+ $warningMessage.tooltip();
// Show tooltip
- $messageContainer.removeClass('d-none');
+ $warningMessage.removeClass('d-none');
} else {
// Remove error message
- $messageContainer.remove();
+ $warningMessage.remove();
}
};
@@ -2061,10 +2113,26 @@ Viewer.prototype.validateElementData = function(
$elementContainer.parents('.designer-element-group');
const hasGroup = Boolean(element.groupId);
- // Get error message ( from element or group )
+ // Get error message container
let $messageContainer = (hasGroup) ?
- $groupContainer.find('> .empty-element-data') :
- $elementContainer.find('> .empty-element-data');
+ $groupContainer.find('> .message-container') :
+ $elementContainer.find('> .message-container');
+
+ // If there's no message container, add it
+ if ($messageContainer.length === 0) {
+ $messageContainer = $('');
+
+ if (hasGroup) {
+ $messageContainer.appendTo($groupContainer);
+ } else {
+ $messageContainer.appendTo($elementContainer);
+ }
+ }
+
+ // Get error message ( from element or group )
+ let $message = (hasGroup) ?
+ $groupContainer.find('.empty-element-data') :
+ $elementContainer.find('.empty-element-data');
const isNotValid =
!widgetData || typeof widgetData === 'undefined' || widgetData === '';
@@ -2074,19 +2142,18 @@ Viewer.prototype.validateElementData = function(
const elementType = element.elementType;
// Create message if doesn't exist
- if ($messageContainer.length === 0) {
- $messageContainer = $(
+ if ($message.length === 0) {
+ $message = $(
`
-
+
`);
if (hasGroup) {
// Remove message from element if we're going to create the group one
- $elementContainer.find('> .empty-element-data').remove();
- $messageContainer.appendTo($groupContainer);
- } else {
- $messageContainer.appendTo($elementContainer);
+ $elementContainer.find('.empty-element-data').remove();
}
+
+ $message.appendTo($messageContainer);
}
errorArray.push(
@@ -2102,16 +2169,16 @@ Viewer.prototype.validateElementData = function(
'
');
// Set title/tooltip
- $messageContainer.tooltip('dispose')
+ $message.tooltip('dispose')
.prop('title', '' +
errorArray.join('') + '
');
- $messageContainer.tooltip();
+ $message.tooltip();
// Show tooltip
- $messageContainer.removeClass('d-none');
+ $message.removeClass('d-none');
} else {
// Remove message
- $messageContainer.remove();
+ $message.remove();
}
};
diff --git a/ui/src/style/layout-editor.scss b/ui/src/style/layout-editor.scss
index 9fa7474467..af455c32d1 100644
--- a/ui/src/style/layout-editor.scss
+++ b/ui/src/style/layout-editor.scss
@@ -1243,7 +1243,7 @@ body.editor-opened {
opacity: 0.3;
}
- & > .invalid-parent, & > .empty-element-data {
+ & > .message-container {
z-index: $viewer-object-group-bts-z-index !important;
}
@@ -1271,24 +1271,43 @@ body.editor-opened {
}
.designer-element, .designer-element-group {
- .invalid-parent, .empty-element-data {
+ .message-container {
+ display: flex;
+ flex-direction: column-reverse;
+ gap: 4px;
position: absolute;
- padding: 2px 5px;
- border-radius: 4px;
- font-weight: bold;
- z-index: 100;
left: auto;
top: auto;
right: 2px;
bottom: 2px;
+ z-index: 100;
+ }
+
+ .error-message, .empty-element-data, .warning-message {
+ padding: 2px 5px;
+ border-radius: 4px;
+ font-weight: bold;
background-color: $xibo-color-semantic-error;
color: $xibo-color-neutral-0;
opacity: 0.6;
}
+ .warning-message {
+ color: $xibo-color-neutral-1000;
+ background-color: $xibo-color-semantic-warning;
+ }
+
+ .empty-element-data {
+ background-color: $xibo-color-semantic-info;
+ }
+
&:hover {
- .invalid-parent, .empty-element-data {
+ .error-message, .empty-element-data, .warning-message {
opacity: 0.8;
+
+ &:hover {
+ opacity: 1;
+ }
}
}
}
@@ -1992,7 +2011,7 @@ div#bg_media_name {
}
}
- .error-message {
+ .error-message, .warning-message {
display: none;
}
}
diff --git a/ui/src/templates/forms/widget.hbs b/ui/src/templates/forms/widget.hbs
index 546c56d56a..ed980ae868 100644
--- a/ui/src/templates/forms/widget.hbs
+++ b/ui/src/templates/forms/widget.hbs
@@ -11,6 +11,10 @@
{{> inputs/message variant="danger" customClass="mt-2 mb-2" title=errorMessage}}
{{/if}}
+ {{#if showWarningMessage}}
+ {{> inputs/message variant="warning" customClass="mt-2 mb-2" title=warningMessage}}
+ {{/if}}
+
From 3e4b9557ead211f6657bf806db9eb03ce1fed019 Mon Sep 17 00:00:00 2001
From: Ruben Pingol <128448242+rubenpingol-xibo@users.noreply.github.com>
Date: Tue, 2 Apr 2024 20:18:50 +0800
Subject: [PATCH 11/23] Elements: Fix pin slot (#2465)
relates to xibosignage/xibo#3367
---
modules/src/xibo-player.js | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/modules/src/xibo-player.js b/modules/src/xibo-player.js
index df2519cb87..e14eb77c39 100644
--- a/modules/src/xibo-player.js
+++ b/modules/src/xibo-player.js
@@ -335,6 +335,7 @@ const XiboPlayer = function() {
if (data.length > 0) {
let lastSlotFilled = null;
+ const filledPinnedSlot = [];
dataLoop: for (const [dataItemKey] of Object.entries(data)) {
let hasSlotFilled = false;
@@ -356,6 +357,11 @@ const XiboPlayer = function() {
const slotItems = itemObj.items;
const pinnedItems = itemObj.pinnedItems;
const currentSlot = itemObj.slot;
+ let nextSlot = currentSlot + 1;
+
+ if (nextSlot > maxSlot) {
+ nextSlot = currentSlot;
+ }
// Skip if currentKey is less than the currentSlot
// This occurs when a data slot has been skipped
@@ -411,6 +417,13 @@ const XiboPlayer = function() {
lastSlotFilled = currentSlot;
}
+ if (pinnedSlots.includes(currentSlot) &&
+ lastSlotFilled === currentSlot &&
+ !filledPinnedSlot.includes(currentSlot)
+ ) {
+ filledPinnedSlot.push(currentSlot);
+ }
+
itemObj.dataKeys = [
...itemObj.dataKeys,
currentKey,
@@ -420,6 +433,18 @@ const XiboPlayer = function() {
hasSlotFilled = false;
if (lastSlotFilled % maxSlot === 0) {
lastSlotFilled = null;
+ } else if (currentKey > maxSlot &&
+ nextSlot !== currentSlot &&
+ pinnedSlots.includes(nextSlot) &&
+ filledPinnedSlot.includes(nextSlot)
+ ) {
+ // Next slot is a pinned slot and has been filled
+ // So, current item must be passed to next non-pinned slot
+ if (nextSlot === maxSlot) {
+ lastSlotFilled = null;
+ } else {
+ lastSlotFilled = nextSlot;
+ }
}
break;
From db8b071e6ce59151736a50da2e502e89aeeb15d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mauro=20Ferr=C3=A3o?=
Date: Tue, 2 Apr 2024 17:22:48 +0100
Subject: [PATCH 12/23] Remove webpack-bundle-analyzer package (#2467)
relates to xibosignage/xibo#3396
---
package-lock.json | 575 +---------------------------------------------
package.json | 1 -
2 files changed, 2 insertions(+), 574 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index b4379f4e9f..fcb3bf87b2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3704,16 +3704,6 @@
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
"dev": true
},
- "accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
- "dev": true,
- "requires": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- }
- },
"acorn": {
"version": "5.7.4",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz",
@@ -3740,12 +3730,6 @@
}
}
},
- "acorn-walk": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
- "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
- "dev": true
- },
"aggregate-error": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
@@ -3844,12 +3828,6 @@
"sprintf-js": "~1.0.2"
}
},
- "array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
- "dev": true
- },
"array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
@@ -3882,12 +3860,6 @@
"resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
"integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ=="
},
- "async-limiter": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
- "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
- "dev": true
- },
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -5019,18 +4991,6 @@
"tweetnacl": "^0.14.3"
}
},
- "bfj": {
- "version": "6.1.2",
- "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz",
- "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==",
- "dev": true,
- "requires": {
- "bluebird": "^3.5.5",
- "check-types": "^8.0.3",
- "hoopy": "^0.1.4",
- "tryer": "^1.0.1"
- }
- },
"big.js": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
@@ -5090,52 +5050,6 @@
"integrity": "sha512-FPbl2VMophcudvT2Li+y10RtKT4l7wBto1NZycXoVQb1JVlo8QbjDgEqL9Ph41/rUl4dTOv3mqWPoxqCHA1b7A==",
"optional": true
},
- "body-parser": {
- "version": "1.20.0",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz",
- "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==",
- "dev": true,
- "requires": {
- "bytes": "3.1.2",
- "content-type": "~1.0.4",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "http-errors": "2.0.0",
- "iconv-lite": "0.4.24",
- "on-finished": "2.4.1",
- "qs": "6.10.3",
- "raw-body": "2.5.1",
- "type-is": "~1.6.18",
- "unpipe": "1.0.0"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- },
- "qs": {
- "version": "6.10.3",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
- "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
- "dev": true,
- "requires": {
- "side-channel": "^1.0.4"
- }
- }
- }
- },
"bootbox": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/bootbox/-/bootbox-5.5.3.tgz",
@@ -5230,12 +5144,6 @@
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
- "bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
- "dev": true
- },
"cacache": {
"version": "15.3.0",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz",
@@ -5436,12 +5344,6 @@
"integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==",
"dev": true
},
- "check-types": {
- "version": "8.0.3",
- "resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz",
- "integrity": "sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==",
- "dev": true
- },
"chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@@ -5740,29 +5642,6 @@
"typedarray": "^0.0.6"
}
},
- "content-disposition": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
- "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
- "dev": true,
- "requires": {
- "safe-buffer": "5.2.1"
- },
- "dependencies": {
- "safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "dev": true
- }
- }
- },
- "content-type": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
- "dev": true
- },
"convert-source-map": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
@@ -5772,18 +5651,6 @@
"safe-buffer": "~5.1.1"
}
},
- "cookie": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
- "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
- "dev": true
- },
- "cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
- "dev": true
- },
"copy-anything": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz",
@@ -6534,23 +6401,11 @@
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"dev": true
},
- "depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
- "dev": true
- },
"desandro-matches-selector": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/desandro-matches-selector/-/desandro-matches-selector-2.0.2.tgz",
"integrity": "sha512-+1q0nXhdzg1IpIJdMKalUwvvskeKnYyEe3shPRwedNcWtnhEKT3ZxvFjzywHDeGcKViIxTCAoOYQWP1qD7VNyg=="
},
- "destroy": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
- "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
- "dev": true
- },
"detect-indent": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
@@ -6587,12 +6442,6 @@
"resolved": "https://registry.npmjs.org/dom-to-image/-/dom-to-image-2.6.0.tgz",
"integrity": "sha512-Dt0QdaHmLpjURjU7Tnu3AgYSF2LuOmksSGsUcE6ItvJoCWTBEmiMXcqBdNSAm9+QbbwD7JMoVsuuKX6ZVQv1qA=="
},
- "duplexer": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
- "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
- "dev": true
- },
"duplexify": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
@@ -6615,18 +6464,6 @@
"safer-buffer": "^2.1.0"
}
},
- "ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
- "dev": true
- },
- "ejs": {
- "version": "2.7.4",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
- "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
- "dev": true
- },
"ekko-lightbox": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/ekko-lightbox/-/ekko-lightbox-5.3.0.tgz",
@@ -6650,12 +6487,6 @@
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
"dev": true
},
- "encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
- "dev": true
- },
"end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
@@ -6720,12 +6551,6 @@
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true
},
- "escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
- "dev": true
- },
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
@@ -7228,12 +7053,6 @@
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
},
- "etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "dev": true
- },
"ev-emitter": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ev-emitter/-/ev-emitter-1.1.1.tgz",
@@ -7329,77 +7148,6 @@
"pify": "^2.2.0"
}
},
- "express": {
- "version": "4.18.1",
- "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz",
- "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==",
- "dev": true,
- "requires": {
- "accepts": "~1.3.8",
- "array-flatten": "1.1.1",
- "body-parser": "1.20.0",
- "content-disposition": "0.5.4",
- "content-type": "~1.0.4",
- "cookie": "0.5.0",
- "cookie-signature": "1.0.6",
- "debug": "2.6.9",
- "depd": "2.0.0",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "finalhandler": "1.2.0",
- "fresh": "0.5.2",
- "http-errors": "2.0.0",
- "merge-descriptors": "1.0.1",
- "methods": "~1.1.2",
- "on-finished": "2.4.1",
- "parseurl": "~1.3.3",
- "path-to-regexp": "0.1.7",
- "proxy-addr": "~2.0.7",
- "qs": "6.10.3",
- "range-parser": "~1.2.1",
- "safe-buffer": "5.2.1",
- "send": "0.18.0",
- "serve-static": "1.15.0",
- "setprototypeof": "1.2.0",
- "statuses": "2.0.1",
- "type-is": "~1.6.18",
- "utils-merge": "1.0.1",
- "vary": "~1.1.2"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- },
- "qs": {
- "version": "6.10.3",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
- "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
- "dev": true,
- "requires": {
- "side-channel": "^1.0.4"
- }
- },
- "safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "dev": true
- }
- }
- },
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -7594,12 +7342,6 @@
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-1.3.8.tgz",
"integrity": "sha512-spKHSBQIxxS81N/O21WmuXA2F6wppUCsutpzenOeZzOCCJ5gEfcbqJP983IrpLXzYmXnMUa6J03SubcNPdKrlg=="
},
- "filesize": {
- "version": "3.6.1",
- "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",
- "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==",
- "dev": true
- },
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
@@ -7609,38 +7351,6 @@
"to-regex-range": "^5.0.1"
}
},
- "finalhandler": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
- "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
- "dev": true,
- "requires": {
- "debug": "2.6.9",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "on-finished": "2.4.1",
- "parseurl": "~1.3.3",
- "statuses": "2.0.1",
- "unpipe": "~1.0.0"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- }
- },
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- }
- }
- },
"find-cache-dir": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
@@ -7745,23 +7455,11 @@
"resolved": "https://registry.npmjs.org/form-serializer/-/form-serializer-2.5.0.tgz",
"integrity": "sha512-/ywBrSMOWrbpVYJFuin0OuOnqTas7gER1Eimi43D1iqQvNF6z1vY8KcWkC/YGt8zPE9k8KmyDVwIth6e5C1nxg=="
},
- "forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "dev": true
- },
"framework-utils": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/framework-utils/-/framework-utils-1.1.0.tgz",
"integrity": "sha512-KAfqli5PwpFJ8o3psRNs8svpMGyCSAe8nmGcjQ0zZBWN2H6dZDnq+ABp3N3hdUmFeMrLtjOCTXD4yplUJIWceg=="
},
- "fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
- "dev": true
- },
"from2": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
@@ -7988,24 +7686,6 @@
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="
},
- "gzip-size": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz",
- "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==",
- "dev": true,
- "requires": {
- "duplexer": "^0.1.1",
- "pify": "^4.0.1"
- },
- "dependencies": {
- "pify": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
- "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
- "dev": true
- }
- }
- },
"handlebars": {
"version": "4.7.7",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
@@ -8125,30 +7805,11 @@
"os-tmpdir": "^1.0.1"
}
},
- "hoopy": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
- "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==",
- "dev": true
- },
"html-to-image": {
"version": "1.10.8",
"resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.10.8.tgz",
"integrity": "sha512-t+JyFJwKDCp4ZwBp4iC/wqw0meQDDc77Qs8OFl5P7RGlIP3LQMvwpD7VXxqQfC7/TfC+GKYlFP6WDYfXTmXHfw=="
},
- "http-errors": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
- "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
- "dev": true,
- "requires": {
- "depd": "2.0.0",
- "inherits": "2.0.4",
- "setprototypeof": "1.2.0",
- "statuses": "2.0.1",
- "toidentifier": "1.0.1"
- }
- },
"http-signature": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz",
@@ -8392,12 +8053,6 @@
"loose-envify": "^1.0.0"
}
},
- "ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "dev": true
- },
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@@ -9179,18 +8834,6 @@
"resolved": "https://registry.npmjs.org/material-design-icons/-/material-design-icons-3.0.1.tgz",
"integrity": "sha512-t19Z+QZBwSZulxptEu05kIm+UyfIdJY1JDwI+nx02j269m6W414whiQz9qfvQIiLrdx71RQv+T48nHhuQXOCIQ=="
},
- "media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
- "dev": true
- },
- "merge-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
- "dev": true
- },
"merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -9203,12 +8846,6 @@
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"dev": true
},
- "methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
- "dev": true
- },
"micromatch": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
@@ -9223,7 +8860,8 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "dev": true
+ "dev": true,
+ "optional": true
},
"mime-db": {
"version": "1.52.0",
@@ -9431,12 +9069,6 @@
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
},
- "negotiator": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
- "dev": true
- },
"neo-async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
@@ -9491,15 +9123,6 @@
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
},
- "on-finished": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
- "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
- "dev": true,
- "requires": {
- "ee-first": "1.1.1"
- }
- },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -9516,12 +9139,6 @@
"mimic-fn": "^1.0.0"
}
},
- "opener": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
- "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
- "dev": true
- },
"optionator": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
@@ -9641,12 +9258,6 @@
"json-parse-better-errors": "^1.0.1"
}
},
- "parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
- "dev": true
- },
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -9675,12 +9286,6 @@
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
- "path-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
- "dev": true
- },
"path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
@@ -10635,16 +10240,6 @@
"integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
"dev": true
},
- "proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "dev": true,
- "requires": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- }
- },
"proxy-from-env": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
@@ -10735,24 +10330,6 @@
"safe-buffer": "^5.1.0"
}
},
- "range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "dev": true
- },
- "raw-body": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
- "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
- "dev": true,
- "requires": {
- "bytes": "3.1.2",
- "http-errors": "2.0.0",
- "iconv-lite": "0.4.24",
- "unpipe": "1.0.0"
- }
- },
"raw-loader": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz",
@@ -11149,46 +10726,6 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="
},
- "send": {
- "version": "0.18.0",
- "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
- "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
- "dev": true,
- "requires": {
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "fresh": "0.5.2",
- "http-errors": "2.0.0",
- "mime": "1.6.0",
- "ms": "2.1.3",
- "on-finished": "2.4.1",
- "range-parser": "~1.2.1",
- "statuses": "2.0.1"
- },
- "dependencies": {
- "debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "requires": {
- "ms": "2.0.0"
- },
- "dependencies": {
- "ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- }
- }
- }
- }
- },
"serialize-javascript": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz",
@@ -11197,24 +10734,6 @@
"randombytes": "^2.1.0"
}
},
- "serve-static": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
- "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
- "dev": true,
- "requires": {
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "parseurl": "~1.3.3",
- "send": "0.18.0"
- }
- },
- "setprototypeof": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
- "dev": true
- },
"shallow-clone": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
@@ -11332,12 +10851,6 @@
"minipass": "^3.1.1"
}
},
- "statuses": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
- "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
- "dev": true
- },
"stream-each": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
@@ -11643,12 +11156,6 @@
"jquery": ">=1.12.0"
}
},
- "toidentifier": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
- "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
- "dev": true
- },
"tough-cookie": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
@@ -11667,12 +11174,6 @@
"integrity": "sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==",
"dev": true
},
- "tryer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
- "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
- "dev": true
- },
"tslib": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
@@ -11708,16 +11209,6 @@
"integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
"dev": true
},
- "type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
- "dev": true,
- "requires": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- }
- },
"typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
@@ -11979,12 +11470,6 @@
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
"dev": true
},
- "unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
- "dev": true
- },
"untildify": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
@@ -12080,12 +11565,6 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
- "utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
- "dev": true
- },
"uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
@@ -12098,12 +11577,6 @@
"integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
"dev": true
},
- "vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
- "dev": true
- },
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
@@ -12246,41 +11719,6 @@
}
}
},
- "webpack-bundle-analyzer": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.0.tgz",
- "integrity": "sha512-Ob8amZfCm3rMB1ScjQVlbYYUEJyEjdEtQ92jqiFUYt5VkEeO2v5UMbv49P/gnmCZm3A6yaFQzCBvpZqN4MUsdA==",
- "dev": true,
- "requires": {
- "acorn": "^7.1.1",
- "acorn-walk": "^7.1.1",
- "bfj": "^6.1.1",
- "chalk": "^2.4.1",
- "commander": "^2.18.0",
- "ejs": "^2.6.1",
- "express": "^4.16.3",
- "filesize": "^3.6.1",
- "gzip-size": "^5.0.0",
- "lodash": "^4.17.19",
- "mkdirp": "^0.5.1",
- "opener": "^1.5.1",
- "ws": "^6.0.0"
- },
- "dependencies": {
- "acorn": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
- "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
- "dev": true
- },
- "commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true
- }
- }
- },
"webpack-cli": {
"version": "4.10.0",
"resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz",
@@ -12495,15 +11933,6 @@
"mkdirp": "^0.5.1"
}
},
- "ws": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz",
- "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==",
- "dev": true,
- "requires": {
- "async-limiter": "~1.0.0"
- }
- },
"xibo-interactive-control": {
"version": "git+https://github.com/xibosignage/xibo-interactive-control.git#44ad744a5a2a0af9e7fcdb828dbdbeff45cc40f0",
"from": "git+https://github.com/xibosignage/xibo-interactive-control.git#44ad744a5a2a0af9e7fcdb828dbdbeff45cc40f0"
diff --git a/package.json b/package.json
index d82dacf204..25d4350925 100644
--- a/package.json
+++ b/package.json
@@ -55,7 +55,6 @@
"uglifyjs-webpack-plugin": "^2.2.0",
"url-loader": "^1.1.2",
"webpack": "^5.90.3",
- "webpack-bundle-analyzer": "^3.6.1",
"webpack-cli": "^4.5.0",
"webpack-merge": "^4.2.2"
},
From 80265108f1efab37b6b80d6854f9322ef3a169ac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mauro=20Ferr=C3=A3o?=
Date: Wed, 3 Apr 2024 08:48:49 +0100
Subject: [PATCH 13/23] World Clock: Background color not displaying on Windows
Player (#2449)
relates to xibosignage/xibo#3369
---
modules/templates/article-static.xml | 14 +++++++-------
modules/templates/dataset-static.xml | 6 +++---
modules/templates/event-static.xml | 2 +-
modules/templates/forecast-static.xml | 10 ++++++++--
modules/templates/stock-static.xml | 4 ++--
modules/text.xml | 2 +-
modules/worldclock-analogue.xml | 2 +-
modules/worldclock-digital-date.xml | 6 +++---
modules/worldclock-digital-text.xml | 2 +-
9 files changed, 27 insertions(+), 21 deletions(-)
diff --git a/modules/templates/article-static.xml b/modules/templates/article-static.xml
index d545b9c869..d39e4dd156 100644
--- a/modules/templates/article-static.xml
+++ b/modules/templates/article-static.xml
@@ -102,7 +102,7 @@
{% if css or itemsSideBySide or backgroundColor or textDirection == "rtl" %}
{% if itemsSideBySide %}.text-render-item, .page { float: left; }{% endif %}
{% if textDirection == "rtl" %}#content { direction: rtl; }{% endif %}
- {% if backgroundColor %}body { background-color: {{backgroundColor}}; }{% endif %}
+ {% if backgroundColor %}body { background-color: {{backgroundColor}} !important; }{% endif %}
{{css|raw}}
{% endif %}
]]>
@@ -207,7 +207,7 @@ $(target).xiboLayoutAnimate(properties);
}
{% if backgroundColor %}
body {
- background-color: {{backgroundColor}};
+ background-color: {{backgroundColor}} !important;
}
{% endif %}
{% if copyright %}
@@ -382,7 +382,7 @@ html {
{% if backgroundColor %}
body {
- background-color: {{backgroundColor}};
+ background-color: {{backgroundColor}} !important;
}
{% endif %}
@@ -591,7 +591,7 @@ html {
{% if backgroundColor %}
body {
- background-color: {{backgroundColor}};
+ background-color: {{backgroundColor}} !important;
}
{% endif %}
@@ -827,7 +827,7 @@ html {
{% if backgroundColor %}
body {
- background-color: {{backgroundColor}};
+ background-color: {{backgroundColor}} !important;
}
{% endif %}
@@ -1043,7 +1043,7 @@ html {
{% if backgroundColor %}
body {
- background-color: {{backgroundColor}};
+ background-color: {{backgroundColor}} !important;
}
{% endif %}
@@ -1296,7 +1296,7 @@ $(target).xiboLayoutAnimate(properties);
]]>
@@ -3305,7 +3305,7 @@ $(target).xiboLayoutAnimate(properties);
]]>
diff --git a/modules/templates/forecast-static.xml b/modules/templates/forecast-static.xml
index b391aa7a00..95c6d7c54b 100644
--- a/modules/templates/forecast-static.xml
+++ b/modules/templates/forecast-static.xml
@@ -5560,7 +5560,6 @@ h1 {
}
body {
- background-color: #000;
{% if fontFamily %}
font-family: {{fontFamily}};
{% else %}
@@ -5569,6 +5568,10 @@ body {
line-height: 1;
}
+#content > div {
+ background-color: #000;
+}
+
.container {
width: 960px !important;
height: 180px !important;
@@ -5909,7 +5912,6 @@ h1 {
}
body {
- background-color: #000;
{% if fontFamily %}
font-family: {{fontFamily}};
{% else %}
@@ -5918,6 +5920,10 @@ body {
line-height: 1;
}
+#content > div {
+ background-color: #000;
+}
+
.container {
width: 189px !important;
height: 900px !important;
diff --git a/modules/templates/stock-static.xml b/modules/templates/stock-static.xml
index d9bf8bc87c..65a98558fc 100644
--- a/modules/templates/stock-static.xml
+++ b/modules/templates/stock-static.xml
@@ -216,7 +216,7 @@ body {
height: 420px !important;
}
-{% if backgroundColor %}body { background-color: {{backgroundColor}}; }{% endif %}
+{% if backgroundColor %}body { background-color: {{backgroundColor}} !important; }{% endif %}
.text-right {
text-align: right;
@@ -539,7 +539,7 @@ body {
line-height: 1;
}
-{% if backgroundColor %}body { background-color: {{backgroundColor}}; }{% endif %}
+{% if backgroundColor %}body { background-color: {{backgroundColor}} !important; }{% endif %}
.text-right {
text-align: right;
diff --git a/modules/text.xml b/modules/text.xml
index c64f37d954..ed64dc488b 100755
--- a/modules/text.xml
+++ b/modules/text.xml
@@ -103,7 +103,7 @@
]]>
diff --git a/modules/worldclock-analogue.xml b/modules/worldclock-analogue.xml
index 38a44a5152..182c7dc0e1 100644
--- a/modules/worldclock-analogue.xml
+++ b/modules/worldclock-analogue.xml
@@ -316,7 +316,7 @@
Date: Thu, 4 Apr 2024 10:37:57 +0100
Subject: [PATCH 14/23] Widget: Stocks and Currencies use maxItemsPerPage
instead of itemsPerPage. Also improve error responses from
AlphaVantageConnector. (#2462)
fixes xibosignage/xibo#3368
---
lib/Connector/AlphaVantageConnector.php | 10 +++++++---
lib/Widget/CurrenciesAndStocksProvider.php | 2 +-
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/lib/Connector/AlphaVantageConnector.php b/lib/Connector/AlphaVantageConnector.php
index 3e30eb0602..8c36343109 100644
--- a/lib/Connector/AlphaVantageConnector.php
+++ b/lib/Connector/AlphaVantageConnector.php
@@ -1,6 +1,6 @@
getDataProvider()->setCacheTtl($this->getSetting('cachePeriod', 3600));
} catch (\Exception $exception) {
$this->getLogger()->error('onDataRequest: Failed to get results. e = ' . $exception->getMessage());
- $dataProvider->addError(__('Unable to contact the AlphaVantage API'));
+ if ($exception instanceof InvalidArgumentException) {
+ $dataProvider->addError($exception->getMessage());
+ } else {
+ $dataProvider->addError(__('Unable to contact the AlphaVantage API'));
+ }
}
}
}
@@ -231,7 +235,7 @@ private function getStockResults(DataProviderInterface $dataProvider): void
if ($items == '') {
$this->getLogger()->error('Missing Items for Stocks Module with WidgetId ' . $dataProvider->getWidgetId());
- throw new InvalidArgumentException(__('Missing Items for Stocks Module'), 'items');
+ throw new InvalidArgumentException(__('Add some stock symbols'), 'items');
}
// Parse items out into an array
diff --git a/lib/Widget/CurrenciesAndStocksProvider.php b/lib/Widget/CurrenciesAndStocksProvider.php
index b20e5f5257..706458e8d4 100644
--- a/lib/Widget/CurrenciesAndStocksProvider.php
+++ b/lib/Widget/CurrenciesAndStocksProvider.php
@@ -74,7 +74,7 @@ public function fetchDuration(DurationProviderInterface $durationProvider): Widg
if ($numItems > 1) {
// If we have paging involved then work out the page count.
- $itemsPerPage = $durationProvider->getWidget()->getOptionValue('itemsPerPage', 0);
+ $itemsPerPage = $durationProvider->getWidget()->getOptionValue('maxItemsPerPage', 0);
if ($itemsPerPage > 0) {
$numItems = ceil($numItems / $itemsPerPage);
}
From ecafbdd0521861e958b229a169cdb260f3554a9e Mon Sep 17 00:00:00 2001
From: Dan Garner
Date: Fri, 5 Apr 2024 08:34:47 +0100
Subject: [PATCH 15/23] Widget: DataSet issues with duration is per item and
freshness timeout (#2460)
* Widget: dataset to base duration on numItems when durationIsPerItem selected
fixes xibosignage/xibo#3392
* Widget: dataset freshness timeout updated to work for elements.
fixes xibosignage/xibo#3358
---
lib/Widget/DataSetProvider.php | 6 ++----
modules/dataset.xml | 30 ++++++++++++++++++++----------
modules/src/xibo-dataset-render.js | 10 +++++++---
3 files changed, 29 insertions(+), 17 deletions(-)
diff --git a/lib/Widget/DataSetProvider.php b/lib/Widget/DataSetProvider.php
index 2584300785..60070843de 100644
--- a/lib/Widget/DataSetProvider.php
+++ b/lib/Widget/DataSetProvider.php
@@ -1,6 +1,6 @@
getLog()->debug('fetchDuration: duration is per item');
// Count of rows
- $lowerLimit = $durationProvider->getWidget()->getOptionValue('lowerLimit', 0);
- $upperLimit = $durationProvider->getWidget()->getOptionValue('upperLimit', 15);
- $numItems = $upperLimit - $lowerLimit;
+ $numItems = $durationProvider->getWidget()->getOptionValue('numItems', 0);
// Workaround: dataset static (from v3 dataset view) has rowsPerPage instead.
$rowsPerPage = $durationProvider->getWidget()->getOptionValue('rowsPerPage', 0);
diff --git a/modules/dataset.xml b/modules/dataset.xml
index c015028480..48d8a321f4 100755
--- a/modules/dataset.xml
+++ b/modules/dataset.xml
@@ -81,10 +81,6 @@
0
-
- 1
- 0
-
@@ -106,6 +102,12 @@
+
+
+ 1
+ 0
+
+
Duration is per item
@@ -257,6 +259,13 @@
// meta: Metadata
// properties: The properties for the widget
+// Do we have a freshnessTimeout?
+if (properties.freshnessTimeout > 0
+ && moment(meta.cacheDt).add(properties.freshnessTimeout, 'minutes').isBefore(moment())
+ ) {
+ return {dataItems: []};
+}
+
// Filter the items array we have been given
if (parseInt(properties.randomiseItems) === 1) {
// Sort the items in a random order (considering the entire list)
@@ -317,13 +326,14 @@ return {dataItems: items};
0) {
- // Get the now moment time
- var now = moment();
- // Set up an interval to check whether or not we have exceeded our freshness
- var timer = setInterval(function() {
+ // Set up an interval to check whether we have exceeded our freshness
+ if (window.freshnessTimer) {
+ clearInterval(window.freshnessTimer);
+ }
+ window.freshnessTimer = setInterval(function() {
if (moment(meta.cacheDt).add(properties.freshnessTimeout, 'minutes').isBefore(moment())) {
- $("#content").empty().append(properties.noDataMessage);
- clearInterval(timer);
+ // Reload the widget data.
+ XiboPlayer.playerWidgets[id].render();
}
}, 10000);
}
diff --git a/modules/src/xibo-dataset-render.js b/modules/src/xibo-dataset-render.js
index eb90f8aeeb..141e70c357 100644
--- a/modules/src/xibo-dataset-render.js
+++ b/modules/src/xibo-dataset-render.js
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2023 Xibo Signage Ltd
+ * Copyright (C) 2024 Xibo Signage Ltd
*
- * Xibo - Digital Signage - http://www.xibo.org.uk
+ * Xibo - Digital Signage - https://xibosignage.com
*
* This file is part of Xibo.
*
@@ -40,7 +40,11 @@ jQuery.fn.extend({
if (options.rowsPerPage > 0) {
// Cycle handles this for us
- $(el).cycle({
+ if ($(el).prop('isCycle')) {
+ $(el).cycle('destroy');
+ }
+
+ $(el).prop('isCycle', true).cycle({
fx: options.transition,
timeout: duration * 1000,
slides: '> table',
From d4f0b598b70dc64c71bf14d055563c6b617952ef Mon Sep 17 00:00:00 2001
From: Dan Garner
Date: Fri, 5 Apr 2024 12:35:31 +0100
Subject: [PATCH 16/23] DataSet: error viewing DataSet RSS feed. (#2473)
fixes xibosignage/xibo#3381
---
lib/Controller/DataSetRss.php | 38 +++++++++++++++++++++--------------
lib/routes.php | 9 +++++----
2 files changed, 28 insertions(+), 19 deletions(-)
diff --git a/lib/Controller/DataSetRss.php b/lib/Controller/DataSetRss.php
index 0729018eaf..f293a2304f 100644
--- a/lib/Controller/DataSetRss.php
+++ b/lib/Controller/DataSetRss.php
@@ -1,8 +1,8 @@
dataSetFactory->getById($feed->dataSetId);
// What is the edit date of this data set
- $dataSetEditDate = ($dataSet->lastDataEdit == 0) ? Carbon::now()->subMonths(2) : Carbon::createFromTimestamp($dataSet->lastDataEdit);
+ $dataSetEditDate = ($dataSet->lastDataEdit == 0)
+ ? Carbon::now()->subMonths(2)
+ : Carbon::createFromTimestamp($dataSet->lastDataEdit);
// Do we have this feed in the cache?
$cache = $this->pool->getItem('/dataset/rss/' . $feed->id);
@@ -692,7 +692,10 @@ public function feed(Request $request, Response $response, $psk)
if ($cache->isMiss() || $cache->getCreation() < $dataSetEditDate) {
// We need to recache
- $this->getLog()->debug('Generating RSS feed and saving to cache. Created on ' . (($cache->getCreation() !== false) ? $cache->getCreation()->format(DateFormatHelper::getSystemFormat()) : 'never'));
+ $this->getLog()->debug('Generating RSS feed and saving to cache. Created on '
+ . ($cache->getCreation()
+ ? $cache->getCreation()->format(DateFormatHelper::getSystemFormat())
+ : 'never'));
$output = $this->generateFeed($feed, $dataSetEditDate, $dataSet);
@@ -705,10 +708,10 @@ public function feed(Request $request, Response $response, $psk)
$response->withHeader('Content-Type', 'application/rss+xml');
echo $output;
-
- } catch (NotFoundException $notFoundException) {
+ } catch (NotFoundException) {
$this->getState()->httpStatus = 404;
}
+ return $response;
}
/**
@@ -718,12 +721,14 @@ public function feed(Request $request, Response $response, $psk)
* @return string
* @throws \Xibo\Support\Exception\NotFoundException
*/
- private function generateFeed($feed, $dataSetEditDate, $dataSet)
+ private function generateFeed($feed, $dataSetEditDate, $dataSet): string
{
// Create the start of our feed, its description, etc.
$builder = Rss20FeedBuilder::create()
->withTitle($feed->title)
->withAuthor($feed->author)
+ ->withFeedUrl('')
+ ->withSiteUrl('')
->withDate($dataSetEditDate);
$sort = $feed->getSort();
@@ -860,6 +865,7 @@ private function generateFeed($feed, $dataSetEditDate, $dataSet)
foreach ($dataSetResults as $row) {
$item = Rss20ItemBuilder::create($builder);
+ $item->withUrl('');
$hasContent = false;
$hasDate = false;
@@ -880,7 +886,7 @@ private function generateFeed($feed, $dataSetEditDate, $dataSet)
} else if ($mappings[$key]['dataSetColumnId'] === $feed->publishedDateColumnId) {
try {
$date = Carbon::createFromTimestamp($value);
- } catch (InvalidDateException $dateException) {
+ } catch (InvalidDateException) {
$date = $dataSetEditDate;
}
@@ -892,11 +898,13 @@ private function generateFeed($feed, $dataSetEditDate, $dataSet)
}
}
- if (!$hasDate)
+ if (!$hasDate) {
$item->withPublishedDate($dataSetEditDate);
+ }
- if ($hasContent)
+ if ($hasContent) {
$builder->withItem($item);
+ }
}
// Found, do things
diff --git a/lib/routes.php b/lib/routes.php
index cf62ad724a..997bbed15e 100644
--- a/lib/routes.php
+++ b/lib/routes.php
@@ -458,6 +458,7 @@
$app->post('/dataset', ['\Xibo\Controller\DataSet','add'])
->addMiddleware(new \Xibo\Middleware\FeatureAuth($app->getContainer(), ['dataset.add']))
->setName('dataSet.add');
+$app->get('/rss/{psk}', ['\Xibo\Controller\DataSetRss','feed'])->setName('dataSet.rss.feed');
$app->group('', function (RouteCollectorProxy $group) {
$group->put('/dataset/{id}', ['\Xibo\Controller\DataSet','edit'])->setName('dataSet.edit');
@@ -478,10 +479,10 @@
// RSS
$group->get('/dataset/{id}/rss', ['\Xibo\Controller\DataSetRss','grid'])->setName('dataSet.rss.search');
$group->post('/dataset/{id}/rss', ['\Xibo\Controller\DataSetRss','add'])->setName('dataSet.rss.add');
- $group->put('/dataset/{id}/rss/{rssId}', ['\Xibo\Controller\DataSetRss','edit'])->setName('dataSet.rss.edit');
- $group->delete('/dataset/{id}/rss/{rssId}', ['\Xibo\Controller\DataSetRss','delete'])->setName('dataSet.rss.delete');
- $group->get('/rss/{psk}', ['\Xibo\Controller\DataSetRss','feed'])->setName('dataSet.rss.feed');
-
+ $group->put('/dataset/{id}/rss/{rssId}', ['\Xibo\Controller\DataSetRss','edit'])
+ ->setName('dataSet.rss.edit');
+ $group->delete('/dataset/{id}/rss/{rssId}', ['\Xibo\Controller\DataSetRss','delete'])
+ ->setName('dataSet.rss.delete');
})->addMiddleware(new \Xibo\Middleware\FeatureAuth($app->getContainer(), ['dataset.modify']));
// Data
From 730062b029928249fe6062238f360c7d7b449364 Mon Sep 17 00:00:00 2001
From: Dan Garner
Date: Fri, 5 Apr 2024 12:38:51 +0100
Subject: [PATCH 17/23] Misc sanitisation improvements v4 (#2452)
* Parsedown safe mode
fixes xibosignage/xibo#3391
* Auth: normalise responses
fixes xibosignage/xibo#3390
* Uploads: add sanitization
fixes xibosignage/xibo#3392
---
lib/Connector/XiboExchangeConnector.php | 2 +-
lib/Controller/Layout.php | 2 +-
lib/Controller/Library.php | 2 +-
lib/Controller/Login.php | 17 +++++++++++------
lib/Controller/Template.php | 9 ++++++---
lib/Entity/Media.php | 5 ++++-
lib/Helper/LayoutUploadHandler.php | 6 +++---
lib/Helper/XiboUploadHandler.php | 6 +++---
lib/Service/HelpService.php | 4 ++--
9 files changed, 32 insertions(+), 21 deletions(-)
diff --git a/lib/Connector/XiboExchangeConnector.php b/lib/Connector/XiboExchangeConnector.php
index 71c77540db..6b576ea285 100644
--- a/lib/Connector/XiboExchangeConnector.php
+++ b/lib/Connector/XiboExchangeConnector.php
@@ -193,7 +193,7 @@ private function createSearchResult($template) : SearchResult
$searchResult->title = $template->title;
$searchResult->description = empty($template->description)
? null
- : Parsedown::instance()->line($template->description);
+ : Parsedown::instance()->setSafeMode(true)->line($template->description);
// Optional data
if (property_exists($template, 'tags') && count($template->tags) > 0) {
diff --git a/lib/Controller/Layout.php b/lib/Controller/Layout.php
index bd74409493..0e59789ba1 100644
--- a/lib/Controller/Layout.php
+++ b/lib/Controller/Layout.php
@@ -1600,7 +1600,7 @@ public function grid(Request $request, Response $response)
// Parse down for description
$layout->setUnmatchedProperty(
'descriptionFormatted',
- Parsedown::instance()->text($layout->description)
+ Parsedown::instance()->setSafeMode(true)->text($layout->description)
);
} else if ($showDescriptionId == 2) {
$layout->setUnmatchedProperty('descriptionFormatted', strtok($layout->description, "\n"));
diff --git a/lib/Controller/Library.php b/lib/Controller/Library.php
index 7c212f37ad..3bc46cc0bc 100644
--- a/lib/Controller/Library.php
+++ b/lib/Controller/Library.php
@@ -2489,7 +2489,7 @@ public function uploadFromUrl(Request $request, Response $response)
}
// if we were provided with optional Media name set it here, otherwise get it from download info
- $name = empty($optionalName) ? $downloadInfo['filename'] : $optionalName;
+ $name = empty($optionalName) ? htmlspecialchars($downloadInfo['filename']) : $optionalName;
// double check that provided Module Type and Extension are valid
if (!Str::contains($module->getSetting('validExtensions'), $ext)) {
diff --git a/lib/Controller/Login.php b/lib/Controller/Login.php
index 3e81ffbe74..234a52afb9 100644
--- a/lib/Controller/Login.php
+++ b/lib/Controller/Login.php
@@ -1,8 +1,8 @@
send()) {
throw new ConfigurationException('Unable to send password reminder to ' . $user->email);
} else {
- $this->getFlash()->addMessage('login_message', __('Reminder email has been sent to your email address'));
+ $this->getFlash()->addMessage(
+ 'login_message',
+ __('A reminder email will been sent to this user if they exist'),
+ );
}
// Audit Log
$this->getLog()->audit('User', $user->userId, 'Password Reset Link Granted', [
'UserAgent' => $request->getHeader('User-Agent')
]);
- } catch (GeneralException $xiboException) {
- $this->getLog()->debug($xiboException->getMessage());
- $this->getFlash()->addMessage('login_message', __('User not found'));
+ } catch (GeneralException) {
+ $this->getFlash()->addMessage(
+ 'login_message',
+ __('A reminder email will been sent to this user if they exist'),
+ );
}
$this->setNoOutput(true);
diff --git a/lib/Controller/Template.php b/lib/Controller/Template.php
index 6ac0357797..b905e1f27c 100644
--- a/lib/Controller/Template.php
+++ b/lib/Controller/Template.php
@@ -1,6 +1,6 @@
setUnmatchedProperty('descriptionWithMarkup', Parsedown::instance()->text($template->description));
+ $template->setUnmatchedProperty(
+ 'descriptionWithMarkup',
+ Parsedown::instance()->setSafeMode(true)->text($template->description),
+ );
if ($this->getUser()->featureEnabled('template.modify')
&& $this->getUser()->checkEditable($template)
@@ -347,7 +350,7 @@ public function search(Request $request, Response $response)
// Handle the description
$searchResult->description = '';
if (!empty($template->description)) {
- $searchResult->description = Parsedown::instance()->line($template->description);
+ $searchResult->description = Parsedown::instance()->setSafeMode(true)->line($template->description);
}
$searchResult->orientation = $template->orientation;
$searchResult->width = $template->width;
diff --git a/lib/Entity/Media.php b/lib/Entity/Media.php
index c5d5a951ff..47c22d3af4 100644
--- a/lib/Entity/Media.php
+++ b/lib/Entity/Media.php
@@ -1,6 +1,6 @@
mediaId = $this->getStore()->insert('
INSERT INTO `media` (`name`, `type`, duration, originalFilename, userID, retired, moduleSystemFile, released, apiRef, valid, `createdDt`, `modifiedDt`, `enableStat`, `folderId`, `permissionsFolderId`, `orientation`, `width`, `height`)
VALUES (:name, :type, :duration, :originalFileName, :userId, :retired, :moduleSystemFile, :released, :apiRef, :valid, :createdDt, :modifiedDt, :enableStat, :folderId, :permissionsFolderId, :orientation, :width, :height)
diff --git a/lib/Helper/LayoutUploadHandler.php b/lib/Helper/LayoutUploadHandler.php
index d4421ed3ca..b86ffc2b33 100644
--- a/lib/Helper/LayoutUploadHandler.php
+++ b/lib/Helper/LayoutUploadHandler.php
@@ -1,6 +1,6 @@
getSanitizer($_REQUEST);
// Parse parameters
- $name = $params->getArray('name')[$index];
+ $name = htmlspecialchars($params->getArray('name')[$index]);
$tags = $controller->getUser()->featureEnabled('tag.tagging')
- ? $params->getArray('tags')[$index]
+ ? htmlspecialchars($params->getArray('tags')[$index])
: '';
$template = $params->getCheckbox('template', ['default' => 0]);
$replaceExisting = $params->getCheckbox('replaceExisting', ['default' => 0]);
diff --git a/lib/Helper/XiboUploadHandler.php b/lib/Helper/XiboUploadHandler.php
index bae67dd2c8..f5e666445d 100644
--- a/lib/Helper/XiboUploadHandler.php
+++ b/lib/Helper/XiboUploadHandler.php
@@ -1,6 +1,6 @@
getUser()->isQuotaFullByUser(true);
// Get some parameters
- $name = $this->getParam($index, 'name', $fileName);
+ $name = htmlspecialchars($this->getParam($index, 'name', $fileName));
$tags = $controller->getUser()->featureEnabled('tag.tagging')
- ? $this->getParam($index, 'tags', '')
+ ? htmlspecialchars($this->getParam($index, 'tags', ''))
: '';
// Guess the type
diff --git a/lib/Service/HelpService.php b/lib/Service/HelpService.php
index e4bdc5a1bb..5c720281d4 100644
--- a/lib/Service/HelpService.php
+++ b/lib/Service/HelpService.php
@@ -1,6 +1,6 @@
url = $this->helpBase . $helpLink->url;
}
if (!empty($helpLink->summary)) {
- $helpLink->summary = \Parsedown::instance()->line($helpLink->summary);
+ $helpLink->summary = \Parsedown::instance()->setSafeMode(true)->line($helpLink->summary);
}
$this->links[$pageName][] = $helpLink;
From 5a8c681d1e4a20d22990cacbc4e13f1dc26418a8 Mon Sep 17 00:00:00 2001
From: Dan Garner
Date: Fri, 5 Apr 2024 13:56:02 +0100
Subject: [PATCH 18/23] DataSet: create using utf8mb4 (#2472)
fixes xibosignage/xibo#3380
---
lib/Entity/DataSet.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/Entity/DataSet.php b/lib/Entity/DataSet.php
index 26239e9bd7..f68086b420 100644
--- a/lib/Entity/DataSet.php
+++ b/lib/Entity/DataSet.php
@@ -1098,7 +1098,7 @@ private function createTable()
CREATE TABLE `dataset_' . $this->dataSetId . '` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1
', []);
}
From d7d7f6567e10148e77fe558edbc6ecf2a7c4ee91 Mon Sep 17 00:00:00 2001
From: Dan Garner
Date: Mon, 8 Apr 2024 09:18:43 +0100
Subject: [PATCH 19/23] Feature/westphal 4.0.10 release prep (#2476)
* Install: fix wording for custom install folder still existing
fixes xibosignage/xibo#3383
* Release Preparation 4.0.10.
---
lib/Helper/Environment.php | 2 +-
lib/Middleware/Actions.php | 6 ++-
locale/af.mo | Bin 2833 -> 2833 bytes
locale/ar.mo | Bin 23838 -> 23838 bytes
locale/bg.mo | Bin 92492 -> 92492 bytes
locale/ca.mo | Bin 372093 -> 372093 bytes
locale/cs.mo | Bin 30798 -> 30798 bytes
locale/da.mo | Bin 30786 -> 30786 bytes
locale/de.mo | Bin 329487 -> 329487 bytes
locale/default.pot | 85 ++++++++++++++++++-------------------
locale/el.mo | Bin 15316 -> 15316 bytes
locale/en_GB.mo | Bin 200840 -> 200840 bytes
locale/es.mo | Bin 420297 -> 420297 bytes
locale/et.mo | Bin 5691 -> 5691 bytes
locale/eu.mo | Bin 98907 -> 98907 bytes
locale/fa.mo | Bin 200544 -> 200544 bytes
locale/fi.mo | Bin 157714 -> 157714 bytes
locale/fr.mo | Bin 320375 -> 320375 bytes
locale/fr_CA.mo | Bin 315734 -> 315734 bytes
locale/he.mo | Bin 21605 -> 21605 bytes
locale/hi.mo | Bin 511 -> 511 bytes
locale/hr.mo | Bin 20011 -> 20011 bytes
locale/hu.mo | Bin 10859 -> 10859 bytes
locale/id.mo | Bin 268139 -> 268139 bytes
locale/it.mo | Bin 159454 -> 159454 bytes
locale/ja.mo | Bin 543884 -> 543884 bytes
locale/ko.mo | Bin 231696 -> 231696 bytes
locale/ku.mo | Bin 547 -> 547 bytes
locale/lb.mo | Bin 2420 -> 2420 bytes
locale/lo.mo | Bin 968 -> 968 bytes
locale/lt.mo | Bin 38085 -> 38085 bytes
locale/nb.mo | Bin 22777 -> 22777 bytes
locale/nl.mo | Bin 277046 -> 277722 bytes
locale/nl_NL.mo | Bin 919 -> 919 bytes
locale/pl.mo | Bin 113450 -> 113450 bytes
locale/pt.mo | Bin 38366 -> 38366 bytes
locale/pt_BR.mo | Bin 463484 -> 463486 bytes
locale/ro.mo | Bin 158717 -> 158717 bytes
locale/ru.mo | Bin 325958 -> 325958 bytes
locale/sk.mo | Bin 923 -> 923 bytes
locale/sl.mo | Bin 9510 -> 9510 bytes
locale/sr@latin.mo | Bin 6132 -> 6132 bytes
locale/sv.mo | Bin 89780 -> 89780 bytes
locale/th.mo | Bin 548624 -> 548624 bytes
locale/tr.mo | Bin 272937 -> 272937 bytes
locale/vi.mo | Bin 22930 -> 22930 bytes
locale/zh_CN.mo | Bin 140890 -> 140890 bytes
locale/zh_TW.mo | Bin 130000 -> 130000 bytes
48 files changed, 46 insertions(+), 47 deletions(-)
diff --git a/lib/Helper/Environment.php b/lib/Helper/Environment.php
index 694419c795..a837fd8fbf 100644
--- a/lib/Helper/Environment.php
+++ b/lib/Helper/Environment.php
@@ -30,7 +30,7 @@
*/
class Environment
{
- public static $WEBSITE_VERSION_NAME = '4.0.9';
+ public static $WEBSITE_VERSION_NAME = '4.0.10';
public static $XMDS_VERSION = '7';
public static $XLF_VERSION = 4;
public static $VERSION_REQUIRED = '8.1.0';
diff --git a/lib/Middleware/Actions.php b/lib/Middleware/Actions.php
index cf321b8cc0..b54dd8d73d 100644
--- a/lib/Middleware/Actions.php
+++ b/lib/Middleware/Actions.php
@@ -1,6 +1,6 @@
userTypeId == 1 && file_exists(PROJECT_ROOT . '/web/install/index.php')) {
$container->get('logger')->notice('Install.php exists and shouldn\'t');
- $notifications[] = $factory->create(__('There is a problem with this installation. "install.php" should be deleted.'));
+ $notifications[] = $factory->create(
+ __('There is a problem with this installation, the web/install folder should be deleted.')
+ );
$extraNotifications++;
// Test for web in the URL.
diff --git a/locale/af.mo b/locale/af.mo
index f8ab033bdeb71a497639a56960e24899c0daeae0..745d6ce5712fc6cb32a15d5dec4117e4dc6952d9 100755
GIT binary patch
delta 68
zcmbOzHc@QDXErVqT?11ELsKhLv&nziR5TJ(lZ{LgQ`5{7Ee%YJk}WM$(~MJ%j4e_u
Yk_?g)4GdG#EK>~=Ez>r8vY%iE0Ksb%h5!Hn
delta 68
zcmbOzHc@QDXErWlT>}dR14}C-i^+f4R5XlIO)O1KQ;kzhP0dox3{#C#lT1w#lhe!-
YEsV@l49!z5Q%%e)jEpvWvY%iE0H^H}d;kCd
diff --git a/locale/ar.mo b/locale/ar.mo
index 745659b9f60d36225ccbc0eceb374df9bd24fa0f..a4affb63ec955474f86df205af04759f209123b5 100755
GIT binary patch
delta 70
zcmbQYi*epA#tnCjxlD8oOce}GtxU}(KQmU*NK8#OGD%ELGf%WMFfmHDv`kGiPBk*N
aNU=yVNKP~`Oi8m$HB7Wj+iYa=MgssVMHY1c
delta 70
zcmbQYi*epA#tnCjxr}uUEEEhZt&A)tKQmU*FiJJCG&M~%PBAq#OEoi0HA+n~HAzfP
aGf%WIGEXryPqj=nF|#l-+H7R@_
diff --git a/locale/ca.mo b/locale/ca.mo
index b9f66bf81e17493917dcfd050105bc64e6ad53d7..eaee9ddda96d567d71a56ce9bffa50e1d8e4d350 100755
GIT binary patch
delta 86
zcmex+OYHA0v4$4L7N#xC-o{)ex(22ShNf1gX46BBnN>6rQwO66D85QcWyPO;e3iOij&F%?wkG
oQj<(g5|h)+6D^F)Qw+^hEmKX*ER2lW7aB7IG0XOa#;kWL0gb5|e*gdg
diff --git a/locale/cs.mo b/locale/cs.mo
index e1a155d7b160c300fa61c1da5c7f5342151f238b..bf1eaa4d8267fddc838ee0866a9931f004178965 100755
GIT binary patch
delta 70
zcmX^2f$`i2#tqv3Tqe2(rV56pR;Ff?P5o6g5>u0nOcGPm%o8mQOpKB(EmPBsQ;m!*
aQY?}Tk`oOKQ_?I`4HGTXHaGg8)c^n?Ru*Ca
delta 70
zcmX^2f$`i2#tqv3T*kTv777NIRz?<+P5o6gj8aW3O-)mcQ%p_GQq2rgjZ%|LO%jvS
a%o8n)%u@`_Q!P_X%q)zIHaGg8)c^no*cDg+
diff --git a/locale/da.mo b/locale/da.mo
index 7e95abd90ef66bf526d2567213e0023f29d0aaab..d477599f9b8713173bdfd30f7472d18ae565e3d1 100755
GIT binary patch
delta 70
zcmX@~f$`7>#to}|xlD8oOce}GtxU}(Z}nBtNK8#OGD%ELGf%WMFfmHDv`kGiPBk*N
aNU=yVNKP~`Oi8m$HB7Wj+sx?as09E{^%gq-
delta 70
zcmX@~f$`7>#to}|xr}uUEEEhZt&A)tZ}nBtFiJJCG&M~%PBAq#OEoi0HA+n~HAzfP
aGf%WIGEXryPqj=nF|#l-+RW(Zs09EucNH-J
diff --git a/locale/de.mo b/locale/de.mo
index fd633e76f948a6e1589e06aeb12ff437707e798e..fedc7501d39f7dc95d3e266a96677140bf8f9cc6 100755
GIT binary patch
delta 84
zcmeD06Y1|0X=q{G!W43w%S6|}RKd{H%G7Ln+-)Wmjl|SsBa_6`H1kAD0~4cUOUu+W
m<5VMKixi6_gXBa5!<013RKrBewDwiEnShvi`>NY4soDT;xEwYB
delta 84
zcmeD06Y1|0X=q{G!W43w%UIXILcze&%E)4R+-)Wm4Wm>OOHNY4soDTb\n"
"Language-Team: LANGUAGE \n"
@@ -11454,7 +11454,7 @@ msgstr ""
#: cache/9f/9f9a142004ca4a1c914a4395fe586017.php:125
#: cache/a4/a4b5f52b1992bb349e8a30b19ff24645.php:80
-#: lib/Controller/Playlist.php:1702 lib/Controller/Library.php:2114
+#: lib/Controller/Playlist.php:1703 lib/Controller/Library.php:2114
#: lib/Controller/Layout.php:1656
msgid "Design"
msgstr ""
@@ -12461,7 +12461,7 @@ msgid "Report an application fault"
msgstr ""
#: cache/04/0499f0242d314e52ef2aed46b4a0b1e9.php:113
-#: lib/Middleware/Actions.php:102
+#: lib/Middleware/Actions.php:104
msgid ""
"CMS configuration warning, it is very unlikely that /web/ should be in the "
"URL. This usually means that the DocumentRoot of the web server is wrong and "
@@ -17918,7 +17918,7 @@ msgstr ""
#: cache/71/71725d40a3089432630feea639ab8751.php:112
#: cache/71/71725d40a3089432630feea639ab8751.php:116
-#: lib/Controller/Sessions.php:114
+#: lib/Controller/Sessions.php:119
msgid "Logout"
msgstr ""
@@ -18167,8 +18167,8 @@ msgstr ""
#: cache/2c/2c268905994cc74a86fb2ebd71265416.php:137
msgid ""
-"Assign all Media items based on their Library duration, and make it sticky "
-"so that changes in the library are not pulled into Layouts."
+"Assign all Media items to Playlists based on their Library duration, and "
+"make it sticky so that changes in the library are not pulled into Layouts."
msgstr ""
#: cache/2c/2c268905994cc74a86fb2ebd71265416.php:147
@@ -20809,7 +20809,7 @@ msgstr ""
#: lib/Controller/Widget.php:988 lib/Controller/Widget.php:1077
#: lib/Controller/Widget.php:1444 lib/Controller/Widget.php:1553
#: lib/Controller/Widget.php:1635 lib/Controller/Playlist.php:1311
-#: lib/Controller/Playlist.php:1475 lib/Controller/Layout.php:740
+#: lib/Controller/Playlist.php:1476 lib/Controller/Layout.php:740
#: lib/Controller/Layout.php:843 lib/Controller/Region.php:229
#: lib/Controller/Region.php:376 lib/Controller/Region.php:462
#: lib/Controller/Region.php:527 lib/Controller/Region.php:748
@@ -21488,7 +21488,7 @@ msgstr ""
msgid "Please provide an assetId"
msgstr ""
-#: lib/Controller/Fault.php:109 lib/Entity/Layout.php:1936
+#: lib/Controller/Fault.php:109 lib/Entity/Layout.php:1910
msgid "Can't create ZIP. Error Code: "
msgstr ""
@@ -21623,42 +21623,42 @@ msgstr ""
msgid "Please provide Media to Assign"
msgstr ""
-#: lib/Controller/Playlist.php:1335
+#: lib/Controller/Playlist.php:1336
msgid "You do not have permissions to use this media"
msgstr ""
-#: lib/Controller/Playlist.php:1340
+#: lib/Controller/Playlist.php:1341
#, php-format
msgid "You cannot assign file type %s to a playlist"
msgstr ""
-#: lib/Controller/Playlist.php:1400
+#: lib/Controller/Playlist.php:1401
msgid "Media Assigned"
msgstr ""
-#: lib/Controller/Playlist.php:1485
+#: lib/Controller/Playlist.php:1486
msgid "Cannot Save empty region playlist. Please add widgets"
msgstr ""
-#: lib/Controller/Playlist.php:1504
+#: lib/Controller/Playlist.php:1505
msgid "Order Changed"
msgstr ""
-#: lib/Controller/Playlist.php:1642 lib/Controller/Playlist.php:1719
+#: lib/Controller/Playlist.php:1643 lib/Controller/Playlist.php:1720
msgid "Specified Playlist item is not in use."
msgstr ""
-#: lib/Controller/Playlist.php:1712 lib/Controller/Library.php:2124
+#: lib/Controller/Playlist.php:1713 lib/Controller/Library.php:2124
#: lib/Controller/Layout.php:1702
msgid "Preview Layout"
msgstr ""
-#: lib/Controller/Playlist.php:1787
+#: lib/Controller/Playlist.php:1788
#, php-format
msgid "For Playlist %s Enable Stats Collection is set to %s"
msgstr ""
-#: lib/Controller/Playlist.php:1920
+#: lib/Controller/Playlist.php:1921
#, php-format
msgid "Playlist %s moved to Folder %s"
msgstr ""
@@ -22001,7 +22001,7 @@ msgid ""
"This function is available only to User who originally locked this Layout."
msgstr ""
-#: lib/Controller/Layout.php:3111 lib/Entity/Layout.php:2275
+#: lib/Controller/Layout.php:3111 lib/Entity/Layout.php:2249
msgid "Empty Region"
msgstr ""
@@ -22587,7 +22587,7 @@ msgstr ""
msgid "File available only for SSSP displays"
msgstr ""
-#: lib/Controller/Sessions.php:183
+#: lib/Controller/Sessions.php:177
msgid "User Logged Out."
msgstr ""
@@ -22745,9 +22745,10 @@ msgstr ""
msgid "Layout ID %d is locked by another User! Lock expires on: %s"
msgstr ""
-#: lib/Middleware/Actions.php:93
+#: lib/Middleware/Actions.php:94
msgid ""
-"There is a problem with this installation. \"install.php\" should be deleted."
+"There is a problem with this installation, the web/install folder should be "
+"deleted."
msgstr ""
#: lib/Middleware/SAMLAuthentication.php:102
@@ -23190,40 +23191,36 @@ msgid ""
"edge. Please check the allowed Resize Limit in Administration -> Settings"
msgstr ""
-#: lib/Entity/Layout.php:1837
-msgid "Missing one or more required elements"
-msgstr ""
-
-#: lib/Entity/Layout.php:1853
+#: lib/Entity/Layout.php:1827
#, php-format
msgid "%s is pending conversion"
msgstr ""
-#: lib/Entity/Layout.php:1858
+#: lib/Entity/Layout.php:1832
#, php-format
msgid ""
"%s is too large. Please ensure that none of the images in your layout are "
"larger than your Resize Limit on their longest edge."
msgstr ""
-#: lib/Entity/Layout.php:1870
+#: lib/Entity/Layout.php:1844
msgid "Misconfigured Playlist"
msgstr ""
-#: lib/Entity/Layout.php:2264
+#: lib/Entity/Layout.php:2238
#, php-format
msgid "There is an error with this Layout: %s"
msgstr ""
-#: lib/Entity/Layout.php:2343 lib/Entity/Layout.php:2472
+#: lib/Entity/Layout.php:2317 lib/Entity/Layout.php:2446
msgid "Not a Draft"
msgstr ""
-#: lib/Entity/Layout.php:2558
+#: lib/Entity/Layout.php:2532
msgid "Draft Layouts must have a parent"
msgstr ""
-#: lib/Entity/Layout.php:2693 lib/Listener/WidgetListener.php:199
+#: lib/Entity/Layout.php:2667 lib/Listener/WidgetListener.php:199
msgid "Cannot add the same SubPlaylist twice."
msgstr ""
@@ -25116,33 +25113,33 @@ msgstr ""
msgid "There was a problem processing your request, please try again"
msgstr ""
-#: lib/Connector/AlphaVantageConnector.php:120
+#: lib/Connector/AlphaVantageConnector.php:123
msgid "Unable to contact the AlphaVantage API"
msgstr ""
-#: lib/Connector/AlphaVantageConnector.php:234
-msgid "Missing Items for Stocks Module"
+#: lib/Connector/AlphaVantageConnector.php:238
+msgid "Add some stock symbols"
msgstr ""
-#: lib/Connector/AlphaVantageConnector.php:282
+#: lib/Connector/AlphaVantageConnector.php:286
msgid "Invalid symbol "
msgstr ""
-#: lib/Connector/AlphaVantageConnector.php:319
+#: lib/Connector/AlphaVantageConnector.php:323
msgid "Stocks data invalid"
msgstr ""
-#: lib/Connector/AlphaVantageConnector.php:395
+#: lib/Connector/AlphaVantageConnector.php:399
msgid ""
"Missing Items for Currencies Module. Please provide items in order to "
"proceed."
msgstr ""
-#: lib/Connector/AlphaVantageConnector.php:537
-#: lib/Connector/AlphaVantageConnector.php:544
-#: lib/Connector/AlphaVantageConnector.php:549
-#: lib/Connector/AlphaVantageConnector.php:614
-#: lib/Connector/AlphaVantageConnector.php:619
+#: lib/Connector/AlphaVantageConnector.php:541
+#: lib/Connector/AlphaVantageConnector.php:548
+#: lib/Connector/AlphaVantageConnector.php:553
+#: lib/Connector/AlphaVantageConnector.php:618
+#: lib/Connector/AlphaVantageConnector.php:623
msgid "Currency data invalid"
msgstr ""
@@ -25473,7 +25470,7 @@ msgid ""
"please consult your administrator"
msgstr ""
-#: lib/Storage/PdoStorageService.php:412
+#: lib/Storage/PdoStorageService.php:417
#, php-format
msgid "Failed to write to database after %d retries. Please try again later."
msgstr ""
diff --git a/locale/el.mo b/locale/el.mo
index 83b35dffa76f241bdd3424b896f3fa97856f2ea1..b479ac6842ae835097c7b7c236fd8bf78c3fdf71 100755
GIT binary patch
delta 68
zcmcaoex-avxg3{?u7Rn7p{bRr+2lq!6^+EyWFwQr)HL%%O9K<5WJ}A`G~-kwV~Z4v
XB!lEc1H+Uw%T&We%e2jB<=ABb>wXma
delta 68
zcmcaoex-avxg3|Vu7QPufu)s^#pFgg6%C_Q6H8OmRO1v=Q?pbv!&IZxBvX^bwO66D}dR14}C-%jxcq8CA55QcWyPO;e3iOij&F%?wkGQj<(g
o5|h)+6D^F)Qw+^hEmKX*ER2jaxi)P*&fXsLnsIx~YbG6406~ZvEdT%j
diff --git a/locale/es.mo b/locale/es.mo
index a936b68cf7f616e92f616d94d2e23da6009ff1f4..09b7c76df730e0111c4a508aebae957106874711 100755
GIT binary patch
delta 86
zcmX?kS@Ps%$%Yoj7N#xCoBOy-bPY@u3{9;}&8P3}V^+~fOiea2NlZ;MPqZ{JF-o?y
pOieRRH8QqHu}CsVPBbt~NwZ8fOtegE=j>+&VwUZk{j3LW0RZS*95Da@
delta 86
zcmX?kS@Ps%$%Yoj7N#xCoBOzobqy>O3@ojTET`}7V^+~HN;R=GHBB{6F*P+yH8V^#
pN=-5~NlZ>NPqZ*HPcbx4wM;cJvoJDh=j>+&VwUZk{j3LW0RY8^8z%q&
diff --git a/locale/et.mo b/locale/et.mo
index 97843592a98b450ed69d34ab123b74ef426d2f74..a9dc090379303369c3c9cdd1fa2cd8aa44d9fd43 100755
GIT binary patch
delta 68
zcmdn3vs-6FFh7@xu7Rn7p{bRr+2mM$6^+EyWFwQr)HL%%O9K<5WJ}A`G~-kwV~Z4v
YB!lEc1H+Uw%T&We%e2ia`6saf0HMqj4FCWD
delta 68
zcmdn3vs-6FFh7^Eu7QPufu)s^#pGCi6%C_Q6H8OmRO1v=Q?pbv!&IZxBvX^b4BnTBfEMry3bs
aq*x>wBqtgerleV>8YWt%ZNBrkejWf^S{S1M
delta 70
zcmccJ!gjlbZA05*E@NE-3k3s9DrO3@ojTET+G!VpP#EN;R=GHBB{6F*P+yH8V^#N=-5~
iNlZ>NPqZ*HPcbx4wM;cJvoJDhx2k5`ZdJ{sHU$9oJQyti
diff --git a/locale/fi.mo b/locale/fi.mo
index 8d6dbeb80f456a42a711f95e883a08db49b39f48..1d64cd6cb0ff37bf380217e2d9068894aa5a6c93 100755
GIT binary patch
delta 74
zcmbPqfpgLY&W0_F_PJapx(22ShNf1gX45@$8C5hAQwO66DD+jAGQa5(?~jFTGW
delta 84
zcmexD+jAGQa5(?~X}=lU
diff --git a/locale/fr_CA.mo b/locale/fr_CA.mo
index d6435c8f2a0108270c2e78932d40b76b15d6750d..fd449c61f7a141c3cc05c352bc1e1b9276e72f25 100644
GIT binary patch
delta 84
zcmcb%Nch?!;f5B*Elhi6aGB^Dm?{{WTA7+pKQ@C&MI$ja*~la@HO)NH(!j(h+0rsK
n%{bM_*doOu$sjq=z%V7vGSx8AGOb-`CKC`dZx@=$;$i^+rT`j~
delta 84
zcmcb%Nch?!;f5B*Elhi6a2e|wSST1+S{YeRKQ@C&MZ+l7#M0C>)i}k})GXD^Fx4nE
n$hWo9>FIWRObV>vlxW;10n
uGdN^8VlZQ2Ffn9iIb|_nIc6ye0N|vB;H0SFrGen2xZtIN;G~-1rGNnMY9WgN
delta 88
zcmV-e0H^=|1OEfCkO2xaEigDBFgZFhIFp(IBtbG|G&wajWiwu0nOcGPm%o8mQOpKB(EmPBsQ;m!*
aQY?}Tk`oOKQ_?I`4HGTXHfLBK76AawK@`dW
delta 70
zcmZ2IhjH~B#tlN2T*kTv777NIRz{YSWh_-Rj8aW3O-)mcQ%p_GQq2rgjZ%|LO%jvS
a%o8n)%u@`_Q!P_X%q)zIHfLBK76AaW!xO*&
diff --git a/locale/hu.mo b/locale/hu.mo
index 033560f0dd6f03b69b77cfb4acdb9046e80e7e07..996e2f0131ae1dbd89284491b35ef56483ecd685 100755
GIT binary patch
delta 68
zcmaDI@;YQghYXjAu7Rn7p{bRr+2lzwDjJEY$wnrLscGhkmIfw9$(EL>X~wBW#uh0S
YNe0P@28JnVmZ^q`mT8;s$@KC90PRW@g#Z8m
delta 68
zcmaDI@;YQghYXjou7QPufu)s^#pFpcDjG(qCYGkAsm3X$re>*ThN(uWNv0-=$!X?^
Y7DnbNhUTf3sU~I?Mn;?O$@KC90MpDAdjJ3c
diff --git a/locale/id.mo b/locale/id.mo
index 81a4f17854dcec8d28b607bca5e9ff0c465e2cc3..338cc8e169caffc27426cc840e2ceffa7a03e215 100755
GIT binary patch
delta 80
zcmaF8PT=)Afrb{wElh^FTqe2(rV56pR;Fgtt#g@FG!j#jjZ6|#)65es4NQ!ZEiF^i
kj8lz_EmAC!43ZNK3{%o9Qw)7sl}nYOp*GCx@f0R4{{&j0`b
delta 80
zcmaF8PT=)Afrb{wElh^FT*kTv777NIRz?=nt#g@FG>lSBEKN;QjZ;ib%~H(_Q;kxS
kOidD#)65esjLcIE%~LH?P0TEejN03CnYOp*GCx@f0Nm#Q*>R
diff --git a/locale/it.mo b/locale/it.mo
index 34b120d01df505ac66929c6bf149b21193288127..f6e1e1d559c6ae4fe470477a049eb31d9fc0d48d 100755
GIT binary patch
delta 78
zcmcb2m-F6T&W0_F1vy+Mx(22ShNf1gX49*37*#Y9QwO66Drg{g&k3k$m)mx-={se+-Ym8scuK|2-|jl|SsBa_6`H1kAD0~4cU
vOUu+W<5VMKixi6_gXBa5!<013RKrBewDwp#79eH?Vm2UV-yUnnq0a{ZAb%R=
delta 96
zcmeB~sn|19v7v>rg{g&k3k$m)m$9yag@S>lm664CK|2-|4Wm>OOHl#=n7+6{vSxi6mhfzhtDAmN$)HKyN#njX+)yy!}C^gB{
iBr!S7Jki3)JjKvF)iTw@%)-d1UF~=Ez>l)7*vZD3J$MQsK_iX$;<=sazMP)q|B1T>+%=?T5KM4
delta 96
zcmZ3?vY2JV8b&T-T>}dR14}C-i^+%=?Bi0>i
diff --git a/locale/lb.mo b/locale/lb.mo
index 16c03dbe5e944e0abae14abe180bbae09afbc650..20a84cf7645ab33f09d8db8b1b9b9cbd46c94c7c 100755
GIT binary patch
delta 68
zcmew&^hIa`3oDn2u7Rn7p{bRr*u0nOcGPm%o8mQOpKB(EmPBsQ;m!*
aQY?}Tk`oOKQ_?I`4HGTXHh09@ngam;(-ndM
delta 70
zcmX@QlIiG5rVU21T*kTv777NIRz?<+ZDLh4j8aW3O-)mcQ%p_GQq2rgjZ%|LO%jvS
a%o8n)%u@`_Q!P_X%q)zIHh09@ngamlRTOvt
diff --git a/locale/nb.mo b/locale/nb.mo
index 84f3eafd549be357d1d3876f89855070c6738fca..45ecb749411590e36fa42e4c9d14e05137a261da 100755
GIT binary patch
delta 70
zcmeylk@4q7#tnNdxlD8oOce}GtxU}(AGcJ|NK8#OGD%ELGf%WMFfmHDv`kGiPBk*N
aNU=yVNKP~`Oi8m$HB7Wj+bnGLOb!4`y%xRz
delta 70
zcmeylk@4q7#tnNdxr}uUEEEhZt&A)tAGcJ|FiJJCG&M~%PBAq#OEoi0HA+n~HAzfP
aGf%WIGEXryPqj=nF|#l-+AM7KOb!4tKNYk9
diff --git a/locale/nl.mo b/locale/nl.mo
index 979cfe8ba078f137b2f15f91ce334768be8be8fd..ad08dc6a14700f77d0f37a32f1aa5b62ab219544 100755
GIT binary patch
delta 60311
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