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}}
{{trans.editPermissions}} From 51c9dc1a32076c5f4003e11cbe0e7d9803f3cf37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mauro=20Ferr=C3=A3o?= Date: Tue, 26 Mar 2024 13:28:45 +0000 Subject: [PATCH 05/23] Layout Preview: Elements Displayed Incorrectly After Toggling Full Screen (#2446) relates to xibosignage/xibo#3382 --- ui/src/editor-core/bottombar.js | 22 ++------ ui/src/editor-core/history-manager.js | 7 ++- ui/src/layout-editor/main.js | 2 +- ui/src/layout-editor/viewer.js | 73 ++++++++++++++++++++------- ui/src/playlist-editor/main.js | 2 +- 5 files changed, 64 insertions(+), 42 deletions(-) diff --git a/ui/src/editor-core/bottombar.js b/ui/src/editor-core/bottombar.js index c3ff239edc..8f393827e4 100644 --- a/ui/src/editor-core/bottombar.js +++ b/ui/src/editor-core/bottombar.js @@ -71,30 +71,14 @@ Bottombar.prototype.render = function(object) { }, )); - // Preview request path - let requestPath = urlsForApi.layout.preview.url; - requestPath = requestPath.replace(':id', lD.layout.layoutId); - // Handle play button ( play or pause ) this.DOMObject.find('#play-btn').click(function() { if (lD.viewer.previewPlaying) { - this.DOMObject.find('#play-btn i') - .removeClass('fa-stop-circle') - .addClass('fa-play-circle') - .attr('title', bottombarTrans.playPreviewLayout); - app.viewer.render(true); + app.viewer.stopPreview(); } else { - lD.viewer.playPreview( - requestPath, - lD.viewer.containerObjectDimensions, - ); - this.DOMObject.find('#play-btn i') - .removeClass('fa-play-circle') - .addClass('fa-stop-circle') - .attr('title', bottombarTrans.stopPreviewLayout); - lD.viewer.previewPlaying = true; + app.viewer.playPreview(); } - }.bind(this)); + }); } else if (object.type == 'region') { // Render region toolbar this.DOMObject.html(bottomBarViewerTemplate( diff --git a/ui/src/editor-core/history-manager.js b/ui/src/editor-core/history-manager.js index 35c4e39615..30a4a7b7b2 100644 --- a/ui/src/editor-core/history-manager.js +++ b/ui/src/editor-core/history-manager.js @@ -464,10 +464,13 @@ HistoryManager.prototype.removeLastChange = function() { /** * Render Manager + * @param {boolean} reloadToolbar - force render toolbar? */ -HistoryManager.prototype.render = function() { +HistoryManager.prototype.render = function( + reloadToolbar = true, +) { // Upload bottom bar if exists - if (this.parent.bottombar) { + if (this.parent.bottombar && reloadToolbar) { this.parent.bottombar.render(); } diff --git a/ui/src/layout-editor/main.js b/ui/src/layout-editor/main.js index db76f64980..9de479db69 100644 --- a/ui/src/layout-editor/main.js +++ b/ui/src/layout-editor/main.js @@ -674,7 +674,7 @@ lD.refreshEditor = function( this.bottombar.render(this.selectedObject); // Manager ( hidden ) - this.historyManager.render(); + this.historyManager.render(false); // Properties panel and viewer (reloadPropertiesPanel) && this.propertiesPanel.render(this.selectedObject); diff --git a/ui/src/layout-editor/viewer.js b/ui/src/layout-editor/viewer.js index 6717e56829..d64877b0e3 100644 --- a/ui/src/layout-editor/viewer.js +++ b/ui/src/layout-editor/viewer.js @@ -288,18 +288,13 @@ Viewer.prototype.render = function(forceReload = false, target = {}) { // Render full layout const $viewerContainer = this.DOMObject; - // If preview is playing, refresh the bottombar - if (this.previewPlaying && this.parent.selectedObject.type == 'layout') { - this.parent.bottombar.render(this.parent.selectedObject); - } - // Clear temp data lD.common.clearContainer($viewerContainer); // Show loading template $viewerContainer.html(loadingTemplate()); - // Set preview play as false + // When rendering, preview is always set to false this.previewPlaying = false; // Reset container properties @@ -1235,12 +1230,6 @@ Viewer.prototype.renderRegion = function( }, }); - // Update bottom bar - lD.bottombar.render( - (widgetToLoad) ? widgetToLoad : lD.selectedObject, - res, - ); - // If inline editor is on, show the controls for it // ( fixing asyc load problem ) if (lD.propertiesPanel.inlineEditor) { @@ -2128,38 +2117,79 @@ Viewer.prototype.validateElementData = function( /** * Play preview - * @param {string} url - Preview url - * @param {object} dimensions - Preview dimensions + * @param {object=} dimensions - Preview dimensions */ -Viewer.prototype.playPreview = function(url, dimensions) { +Viewer.prototype.playPreview = function(dimensions) { + const app = this.parent; + + // Preview request path + const requestPath = urlsForApi.layout.preview.url + .replace(':id', app.layout.layoutId); + + // If dimensions aren't set, use main container + if (!dimensions) { + dimensions = this.containerObjectDimensions; + } + // Compile layout template with data const html = viewerLayoutPreview({ - url: url, + url: requestPath, width: dimensions.width, height: dimensions.height, }); // Clear temp data - lD.common.clearContainer(this.DOMObject.find('.layout-player')); + app.common.clearContainer(this.DOMObject.find('.layout-player')); // Append layout html to the main div this.DOMObject.find('.layout-player').html(html); + + // Update playing button on bottombar + app.bottombar.DOMObject.find('#play-btn i') + .removeClass('fa-play-circle') + .addClass('fa-stop-circle') + .attr('title', bottombarTrans.stopPreviewLayout); + + // Mark as playing + this.previewPlaying = true; +}; + +/** + * Stop preview + */ +Viewer.prototype.stopPreview = function() { + const app = this.parent; + + // Reload bottombar to original state + app.bottombar.render(app.selectedObject); + + // Reload viewer ( which stops preview ) + this.render(true); }; /** * Toggle fullscreen */ Viewer.prototype.toggleFullscreen = function() { + const app = this.parent; + // If inline editor is opened, needs to be saved/closed if (this.inlineEditorState == 2) { // Close editor content this.closeInlineEditorContent(); } + // Was preview playing? + const previewWasPlaying = this.previewPlaying; + + // Is preview playing? Stop preview + if (previewWasPlaying) { + this.stopPreview(); + } this.DOMObject.parents('#layout-viewer-container').toggleClass('fullscreen'); - this.parent.editorContainer.toggleClass('fullscreen-mode'); + app.editorContainer.toggleClass('fullscreen-mode'); - this.fullscreenMode = this.parent.editorContainer.hasClass('fullscreen-mode'); + this.fullscreenMode = app.editorContainer.hasClass('fullscreen-mode'); // Add attribute to body for editor fullscreen to be used by the moveable if (this.fullscreenMode) { @@ -2169,6 +2199,11 @@ Viewer.prototype.toggleFullscreen = function() { } this.update(); + + // Is preview playing? Restart + if (previewWasPlaying) { + this.playPreview(); + } }; /** diff --git a/ui/src/playlist-editor/main.js b/ui/src/playlist-editor/main.js index 9ad43e42bc..da5ae8aee5 100644 --- a/ui/src/playlist-editor/main.js +++ b/ui/src/playlist-editor/main.js @@ -587,7 +587,7 @@ pE.refreshEditor = function( // Render containers (reloadToolbar) && this.toolbar.render(); - this.historyManager.render(); + this.historyManager.render(false); // Render timeline this.timeline.render(); From e9965d5f5c00b75a7301d71a087f40c67280a527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mauro=20Ferr=C3=A3o?= Date: Tue, 26 Mar 2024 14:33:55 +0000 Subject: [PATCH 06/23] Elements: default value for the URL of the image element is the Xibo website (#2444) relates to xibosignage/xibo#3349 --- modules/templates/global-elements.xml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/modules/templates/global-elements.xml b/modules/templates/global-elements.xml index 11c9d8792c..a7b690aa94 100644 --- a/modules/templates/global-elements.xml +++ b/modules/templates/global-elements.xml @@ -375,7 +375,6 @@ $(target).find('.date').each(function(_idx, dateEl){ Image URL Enter the URL of the image you want to use. - https://xibosignage.com/dist/img/header-logo.svg Opacity @@ -447,15 +446,13 @@ $(target).find('.date').each(function(_idx, dateEl){ - {{#if url}} - - {{/if}} +
]]> 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 @@ {{title}} {{#if provider}} - - {{provider.message}} - + {{#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@f0N&#m#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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

%yFJ)w4y+EbW+jCQ`SP^mZzCW{3zBYvdN#S zE%~G6=WiOQ;8k514tYMYqzE3z7mLeU0|wt7Hu|#@zNctfI2^GA6fCLvsqyczo`%9D zDCn--i_8m=E5VE;g|4Ub5BS_pufjKPZp+Ep4V_2JJEt~)5C00wDihx%J zv5o(U8Bfs&pqU4pz&bRb8*AbG#>t8HZV6y-S?ABd8%x}{{-+Vx3R&zlgw7Q04-O?^ z6Up%z+nFbZQwQ89Tqobmvi_+BPizehOaX^cAO>tFL2N3yt~OCNBKKbt5}ft`5qAoU zogg8I9aSI}LcvGGSJPZY@IGtbSrePd2ISL`3CwHYFGBAjeraOgK<(AIrw#U3oDMp| z=%NvV1*9A7D8jSI=&D)e!8fc`;>fBZ+>IoD%bF2QBUAP0N8@LK(~10qjNz?o0n zX~Wge0!Gr*Gx+)C`QHPgeC+15j1+20Y=8#5@yp2dq_N$^PBQO`NOOu;K_r;*n+^0~ zZll?n_}Spq)8_gzF9W9)Lo5!>y+tb$&C&Aue;<=>2!19o2eR04$jykwSCRB|{DFC6 z#uL`M5U)yX4ms1|uP5FKoyPe2X>cz^#40iJ!5eALtbfKcUjV-seDnGbLF^`haL||J zzKqTY^K%HsOE}9BJBMF@_&k!uHo*46Rb_rCIm7tW{@-)%#1)?;sd}W6c`5Y8;Rv9(uA1U1V$D{Giii) zan^g{UV-12T)s2^uO+7GUCe94+XUZBUjNs``HApd7S5@t2gwy7xg)@DRWm$kW&!J6 z@taUUKGkf)+Ae&t4~)%-2g8{TS6(c>1JW{&kADsBCj5b{l_A~;{YmIQj>YxAL!#5l zL-;8ISd5DE@vkwFsfNy+hxErjq2tj5Af1SinYWr(X(D4exx+VFPr4iJwG zrbe|4{Qlqt8oEIK9Z+lw>wJ!FEXHq${&CjCdcr>m`UUV4i`~YDn>mXeW`MQ+Pn|J%oISZ4)L|#{%OhNr_2V z!rCNa-%09=UmJn3tkouW55=Mxvzd!6!WSFBJdeg?J`tVdG<}uabmY}HH_HCwAv%s= zASl)pzXwHXfKH2}{z?LU;FV)UBRGOxI&D5V)tO&lRD?eT&Qngx2JaDmZr0PWmKA@v zCKYx-NXLR$S(k3_u!}#e4Ul!l7_(cR;}I^5fYSzRV;hNeXIHV{g)+7=+H1~J$U9ie zq0J7U9^XzhQqq{C6Qr41cp8Kss@#D1UJCmooC2cQ6_>*M5UItuLVTSTGD-ZCAKpUn ztmjAj2e%=Iq=*$>h@@EQrpSnP|?0p?jd7Y3BF9yYlxJyz~f5D*2%nXegQ37mjWhqZGn}DPUtg z0rR%X-$ZOMg6^s_S5HlHJ!wQNE*l(4eq2U7jY)i>Lnqa=s06no^nwCkAWx^rP)2{^ z`6*Ho@khjWQgjxaG|cttft4cwUIfefSRk z6y}>XZy){;ie&}ggB8h}scUyg=|{r{zB5Y?jZ6SWrZd*Zo zM`L~zc?2i5>=^YqDtk-9B#+Q`m2zJ3~M8O_#cfb?-OuQT#V!hDc3+^H|2;MP% z{=gVR$6^^Ma-AWT3*vFaeDEtlE+!S!wrC?VT>-ByLOsdb$~+&uS2V?s2N~Cyr$W0k z_?2~j^w&5+Q`_+6XAZ;`$>+b72>NQ_ZzS7U*oZ(dU0>49Z-YH_N0L|oep?1V*lhem zk=2YKmv!NMV#FeE6*bM^Z!S&bq=D)1YOwwijdAeL5zC`Rh3`hZoaS^V9<8UGS(~0J@BfxTD8j;S2=a6s z&Ef^g#%i!uoOve32gXo4+@HRAi1F)^(vC?kQ9#s`w>e@Gh$&RE z$=P{F-GwCWWiFP1g6UZQiC;|D{}QWCk(4x8TX$H5^%eNjDD;`N#=1e#Nb1teKWO}r z`=9@1VPqkpofgU@Ol&ywZIH@ov9So=fOnH|i}8};u|O}1e5H9;8^Pp^#(L>)bD(!m z8^}g(2pq>uM8#UWba|G=D3UTlZV#5Bz->5J;H0KtS>=ABz$-*k!56!0fsvDVIhUO# zCtvI`8);9z*l#$Y^8Rls14*%G-RkPC-F9fU&LPM&iu)qJDMdB@bxP27Z}Wb7NVEab4YYli@^i?D3VyOWacnIXNq6dK1kILHskhS9I61-iBBQ<$J=}t*4tto)_B^C`ZCI-AOwZvuU9X zbUpx%tBpda8=TMJJVs%f8>qQ=T^dYB><>qN1Du7%H?TByLi995)3Jg{E<_qL>O*Ko zFwkY^=P8s}MW<^c*%0jpKdr_$E&8DfZy5kwd#!>hZxdq@PkT2j*5j+f`2mWMsbO6E~{CB#0=_Qm{B@)E0AsC6k zQetTk%!@B}lewRsKo>T1fc!AkXbEr(HLt z@J7}yu;vYBWPKohOV$T6-;eNV#s6tEjAXupW>F^}C^Xf5AQTS=$;30_7#7o#8JymmNAu^GbsXkdr#^tXz{X1ya# z*3}af*{^UC5UU4&67lb<5y4tpMjK*T8P|x%j>q+XKv&tA+$ZS)!!Fkb;#?Z>V|P6$ zmWK7I2*1XUh46jm@pR|Y!KLtfkUJT4hjWD36UHKKcnMln@uz?-7;~x710D8n*(f@? zrDTa5!B339QHX8uuY*pzOJX8P#_~|~I0e&NQ{$lW)}l8De>!WyaR2C~JqAB9dauzw z3CD4Z#G#P#Xz||!v(sT#hzk(dO7bU7-V1L&@uP5~@DGxEl9O0QYz?si@FU6fWVB?6 zC4{$Bn@t2av&OAe_J5Ruu678rCq%Kq;COH~oCAmtBl!US1d5Gftqr>nOGqpkYnN!` zI{6{^_u+{3BvwFcyrG$PjArE3fU{DrzgRqWSP;^DME5|jlkCQPDSib6E)tImCk8(a ziGzrjL}VLH9bs&eQ_><4%ijxdL&$lg4ZVe%iS-sTm-;_-7t0VGNudbHVnZM` z(xYESlGrR_GvEv-xd)>FvGs7?k{iHU8FJe)# z$>&LQS|x&F8;NJa->YkrHQtsJ7*8x6MQmCi0B&B^{k2KSA5QEb+y`)T=>`|Otj8tZ zS-$>XA+aXi1|!&pq?vTrmRLP7lvp8R6+kh6e6jloH3faaBidL_{P~PQXqBL`Y51jS zpfM;`Qa4f;jX~-+mh0b>gtQb(rd`egheB9{NJqpkl6+0q{^Iu&HS8QYdBMiyJMFvr zt+dg(%-r*d0je*>yw4JPL_r*RG#}8+BLf^kiiH z6fqwPzDKJQqa(bo;Usi+bec$j!+5 zOGXt6UnHlCHu9C2SQ4~@RsXXd{d%-gv7Sio|5K1oLC9>I!7D-`n-)#LdM)%SgDEt>2zjQ-{lA)EdUiUSM6rS_4pl!s zLSq?8NIu3|G=(bbDSgBjd!x>40ot6M`7`onYutSP2}JNQ!FUM#pqWgN zGg0&dI0jsb=y~Gb;q52!C-Hp5va`eMc6X^?LLB~#;Pb|JRP*_D@>k$g4HS61%&jf2A-W#1IjFzlbCDxd6 zU-K`pKH2s9x21uWdW4f)M59Q)Kohk{E`XRnoL2Z^FTsH{vI)N&<12n;PNNmPUFcQO zCL7|1t@aV18ce@1(0lOx(d4kaL0s zNbHG#(=M<+gPn=xauMnVcbvu#>rPiP_o9JM!cU10~$ zSlmNkj*=2;aXZ8}6wFML*f87X=}+fQ$Q0BrDx`gJ}vPWo0AUrHGCT|b7 z;+~#0!^5IFMz`(jmM2MMluu*3J=CZXgxAy_6cIC~uiL%~wxF;M_LwUB-8y^6@`*4f zt1r3T%N;MQUB`&Kt7*wJlG~wFd69lEkq`(s28r-q9O_-MwQ5 z2fNqxiWiXAub_`#U@^ad=sS__r(|Bpr$C`%g$hS+igM5D8)R?i9}r{@E)o>z7vSG6 zFwh=c(C%NbX#1jV{n`cj6=)wEXfF^H7##B_%Kg~V?EjvLopX{yvHy2W|Ar!C4yW-* z6DvWZ@Q9EOb{Y)|Yae~b$D>>djr5cgGku>4USXJ-Y481>eD{@+;WeUF`Qp*?>Lo1NTr2DLntbLMMbHk zNPAGEXm~!K>zwC#y`I2bAH!-lmBPuuiSd}%H*-Dvn)yQfA3wMNEE`E z-4lshuSg_*-ssgt;*oC?2|h|Zin;L#yc)M*HvAu6hljB+p2Y%q^>>LxCRW7a*a6Gp zILwF3@y0|VnRtnU4QBm5k+=#AqBm5;Mc5MSrzH}fU}Ngn{Fq35h27AGYyFf+w8P#w z3fJRjnCEByA5Y_@cp{hXMUdXbdLM4}7@XIM3UP(RuNonePq?}?XDAAk;cc)UIZ zy>C|hd|~{2DcbJS@%l^A*U|g;Sf~HQf%w5E(J!Olp))*%B{27|Au@GvE%naW3ID(b z*z!~&F%@Ux2uwenNZf(9VNX1Xb+N&3iNrv>6O*h#;xh^*vEuKE#7)=*UDFq_93I3b z_&3^7gENUlBb=!3v?hK zV{ZHh4f&PlLMZd$CDe;!PArSru{K_V&CuNG86As-sn5kcxB*Sh9atVeJxBbV;U#~D zkyXKp)Ne$SW;zzc`_SZEi@ES6wBbGI0KZ1>{|PhjcWi;@(EIEE6$X3*=Ahmi&5fZ+ z3eI30nw8UH{l4g8yqfEeqXXE4&h#xbi9SUm@ip4uZ}Iv+=>3VOzWcd&duk;|A(u@mef!Av{nO9cW#&!KSg^5q-WV+QCq~9>=5iJ%_dMRdhnX zBLhq(F8MnoOEr0H38~{ePigC=>sNNL-HjsTRNjSOcHMj%bJfq7k_IzcAB+XmXWC+i8Gy+zK7& z=;$P1JR*Vm#0J%V=l zD;CC#^t4n2ilP&&66>|`cIqwD(~_xo_#a??SVB z7MffSqcdKM=Ezf66TgVpb7u(y$d67m6H8&8EXlM)Lkj)4Pz6__4IID#iV>!G#dsvcGg9>i40(1vnf5hBqLozXaSd%ldG7oVZI@*|q%XVEpz$Q8UC3sS!dU80KU zeb=MUx547>|6UZ_k5kdLU4$MukKuIOgmzs0%CKhL(fg*N+i*6z_79*lTZ-<6189zX z9zXvX9q{k*^M6vGC)tBng%Rb)eB4kL9cfc^MxA55Cz{nmO|UXzx{g2m9#mqyQt+L&~tZQ_NlXvl`3`}j_DyUarydIIg}h3G42 zgKr^gnK*<+t1siCHhO{jjnI33^ z1F<~bj-GU@&<3}n9qd3m+>Z|E<5>R^ZTAOkgnyt1T+MtT$Hpfqc=FwYHn0P2@EzQZ zAEP0DG=De=pF#)rEE>{n=$fBG2cEM)Sh50WGFL+f+72C97qtDpv7Q`3!8IR`hGZt1 z#T(E8y^0la50=C;=sA(UU|OOKcEoZx5i8(YH2Dr+zah!A(q0I(4;zwzK$=VGcQm$F!6j@ncvG zkE1zsO(yNR|I1P6iPg|GyB}@f3A_b2VL!}QG%e8tCt?qL1r6oZ#lnD!qBAXr&agf@ zp^mXW2!~R?124g2m^3?2Qt-jk=zdQx9tKbV{k#mCy*1GLZbxTyFB-Z1SO&ZP0;rMmxR*y?Dl@MkDbq+TkH|jgO)s{|W85YMC&D zhUfs=;z;a*Ms6p%efOYAcmRFw%lP@vXpSU*qhKhqlnoKM5*=YNbRbpG2I`@aX&0~e zMI$y8?PwBuRL{U$aT!j)OUtDtCgBwP2G60naI}1C_aqZ1DA+)Y3Sp)l(UIL8>toSK zOh?yrcD%k2J5gVWhVm4ejF(gl_ZLSeP#%p?Ep%dyV!eGz_Fs1j-q;VF(FpX$DQM{D zqPg&BtZzm;+>J)&NWA_%nq+^XGt6Eo4EQRvy?kiS~l^LL`3plkar`rO~>%&)2$+AD@8V`cQYW@t{` zh|YWjI>F@K6kMCd=mRU!^I#MD;0`pj@1Z&IIr@@H)C$`zKN`8(=zzMQ4G%+~y9>R4 zHadXSXg}ML`;&?HLLqSioxz{+hOD(iP8321SOWdLGTLxsbf6uu2=+!Bz6)J~1=s~Q zp^?0_PG~1TzE8abX7~MnhC)>?TtvUQRIMA8kza%0G6X`x&a;N z^EeV;LAPn?>qA7UqPfrvUGf_+_5SZg!43wXNi{Cs@VPfo{~jCQX`G6c>V^9^qHFm& z8j(Zj5}ZH>_$PWIURpooNC|X+*P{_?fl0sF45#3T=0zXHYSh=G4S$Li@H;dauW1lM zUIJa)=I8`&!kRb=9l#T4yPGi+ccLfhaWohHZovL`gt;4rZ#GrYY#tw-gU;}AH1u1s zK7ND^@ybS_;f`o%$Dj>Q!rJ%%*2QO|QI2lg3C0y`iI*Oi5$FVnl zhc?`_NtkIn^vmU7w4)>%(xqrFtU)939QxcFXnXHqCccm6#3^)u=WW0nt2PZ;dOaHQ z_Gm|a&^5gydOvzHu0kWV7wzCE`rHY00H>pA%|c|aMwg^3+TS4bx#UO+&U{?-PAp1& z3fj<0bXz@-&hSliO%I?mIU4KVM$beO&BKIpq7lkO&xP{nKpG(JB@;Kq8+xJ*4hkP6 zZbKiKgwE`KwBtw78LUSm^E|o~Z^i3J(RRK;pF4#n?Z42HJkDxPKk3RPzZoxOv^I&4ja6O5>tR6r^z737!4$R^Ee;)-y z{0aKtPw32kM`wCjtI*+<=ytmfondXX!6xVcTcHE#ibiAz+Rikz{l(}>`DDEQHYWYx zCs!bk84Y>5rpr6rc*Ol*!tZ%9il!y)K>Y3;*|mtigH8?h>Wjh>u& zIs^-&NmmkG>KbTdn|EOUTWB9IbdNXmLmL>4mGMp-icezUG$Pb7{2)@XQ(A&zVjh;{ z^P`=^TQdE|uwZ36eA4SjZ zSI}HJhN)~vx9cf12NK=F&xlu}IWhwMJ;NAu2{xk7C-+b=0{hWyK8!x_7243ZXvqFT zb0cf_@EgoL=>5IWWE&ivf+eUwgidHX+Wwd5QT#pHUa=l&i5c$yY7`vNRy5=X&<8$= z^{>#5zK@M$?-a7;C}Q( zJcthHFglMrSx5tKm|tg8O3qZ*+TB>KlGZ-M=sU-?d!A z1rL@rSO>SEA^HuCz!f)znde25tqPi)t;5DK zXYd8C#BZ=H&g>Vm_c=7__Mm6^p;-R`&5^&*0cP(Xyb7Ih-dHb+E=_54Nvop+Xcj+D zwx!@tqn*$Yc8T^xBXJWt(gEn2j*FkKL(lxD(HZVTBX9&w=5Nr6Wgiea%pEO&e&s8Q zOemRXM8S@`V(LJ_!PE!G>+hm#{ysX8Z=-)=YH0?>9Knu!o)^7uC>pVe=&qTM_Ol*` z;4`T@`|s*OVT5_nP+x~OToKD)b-V@p;$+;7CTYXL;m>yN#Am7RLL)T#mbBELe6GRa z)W5*e*lI|42aJwBfSK<9%@oYWLtenNp&^9Durc-4=$g(!U(<`xCEJ8X>?Jg$JJI`& zp%eKYoyec){r_SsObiR>L~BewNqruLVOV2$nCS|9n0m&Dw8VT|hW)V2t>LHN+4uqV zV>kw17@3xM9*f=<-t!;e-P9Y6q66H8J+R5>wA5eGcoch4&pL+vZzuXZn&!XR&Gj0z{dL0^}l4veeL6fuvX5x*v zC&T_7&xI9Sn1k-;(i1|%4X_>c4(Nfj3~lh`=x%g-y@zJ|r|7mkj_!)H=s?r&2-mYl z3q~s?DY#}$(3!MDPqw~jN2Ab#V-lJ~_h2V{8cX5dSQU%i8Foom^e3H>=)h*z(gm*7q`dtX2s_!@7*i)ch{niOU@9^FQh(HTxhlWjqCMf`kYtiOmJ zI6Kh@y^T)j0Mbq}afCuiE_{LcG2^b#L1FX&DuzX|6fVZr=t*`Ijo8m<2mhjx%rZHi z2k27dMF(6C9dKnd2O6a6q-R?ShPo%(z#w#lx1k}tBVNBJ*5{!Ecmz$h4d?;$Ci>h_ zbf({6dHe;$0yJU9EpArKR=PAU`OAhNpTKsC}VoaiGt{WN}=1QKH6bF zG~`3k+?j-ib|#twi_i!@injj(8j&5?7!RO1aAorDkmY&NH7ZKbk8?&>8%M4k$4*{3^CGdQ?wD&yOW&$B&{*{5Tr9jhM^V)2pchf0GeiyU(!% zp2T{XZC03B3v}&oKy#ui8tM`8`e-x)cSfh7GoKafOVEy&qwPF{<=p?9DHxJt=)ON4 z>pAWXGrbN?%BpC`ZP1zYL-+Ma^tpSZYtVha1AXo&8mY7BbJ^|-$$2d%YjB|=1!q1G z4e_n$2=7E^lte>#Z@fMaZTKN{h8xl6UPG7W9dyY)M^DC6=m4_L4ihMhE_Lqbt?eHly$zDP`K89`aH?*Dlb3({(Kqu4(?Pn008^haI2Oh@GxDp-6X*5!Qp!ffW>3I3vwA2@hoalrqp-a#b&85NU`7sBp z;YM_VUnVJJQn-LVQ1JfnL0v3Oy(_v6r(knjiRQ}J*a!bWbD;CQ5P@6K&!?dSUli*n z&?PyG4lwKdF!5w21+%gWdSEm{XW9l0RR?q%c8&H!?;C-3bbGAdi>~P+G%_pEcArKg zx*c2KUUaE)EJ)>6GEszrH5ujDJAeNn02qb~V;?|5u=3G7Ll;8iKCUc}VCf|HCqA#G^at9_2)h84T%@62X>jD~qs~!r!rOuCrwllg! z1F#uRi1qDgsNch<@kjLeB}+miR-n1G3LU_DbRt`pu>Wm%Cl?&RK{RQO#~V(g+5Jzv ze(l3yASKZpsEISMAv&YoXh)x;?H!Nx-_c0?g)a5K=tR<%vj1yQ$g?zr=msoKeKeNB z#h8h&pa;$8=r+yrNT?S>XVMPKVh?n?-i>y+7VU6DbR*WL{zClx`y>S$_ytX-^U*Ai zh8gBUXOa(H!?I{ZZa|lA2pX}8Xaw#(P=caiO0fry%g;@ceEIKUsarrP0$eUMknwwcEIoA^;*kQ5lbf8Qm~`j zaSTq6_21A2|BdyWD?*3)(T2;QpVvoo;f7f6hIV)h8mT+bNG(FQ=^AvxJFuJk{~Zdh z-E}L&+P20@)Q6xUU4o7AIjoAO@MbLfc=*X_dUQLw_P?XgU9&3WP(|!Yy(>1rr?4h| zhlPCq7hWA6xE|fNUC@JMI(~EDurX|K=hYcYIcH(jB@8Jr3 z{wa1-8oy0{IviLtp9wFqO<0c4KSSHSWMdduiH+=kv#ypexFILHHrJvDL__p})@W$Eq5F0^`p(#jp5?!wNm%mL zux)#zYd!%Tz&dnE-;JMtgT4h5uMq+F{}mLRS$_0`qUeY#qXVgf4`NfSkB6}-Uj2Ib z6-~G3X0)TLb_6S8CiOPx1V*3(TY~PYJ(%=?FDSS+=h4t+eT#v5iYpqXVDNRc7_gXp~=$_4Rssz zT(~>B3f+EhpbdY4cK8b#$-KKlwwFX_JPu3ZTy(%M>`I0XUg3fx+JnC3-i;oJ9*%w< zJ&rc;9XjyeqW?y-?GD%TM2n&ktcVV@CK~Y;NeXVG9%%O7jE49&G-T7TCEka=_1;Gx zJb^C3S@gcNH^cSI(Rv}Qh9%Jsd!qdeL)#yXCVO%^g@zP1pdu24vPj}9Q$-f$x3MeCi> zwd;k>cx-eU8v6Uu87@WNdQYMQ-xWXq5FPL_^qbKI^!}^f_S-i5uP6oAat0dW`RI+S zV|`n!??)f}8hr!9s)jMsZd2cQEVhK+F|`nunaNe`0!6gqX;=V3Wqho0dF(bwu(^!{rPgs)tc(1u5$OLqs_@GNwo527!z z$Iu*Dg|`13`rO+|3O;ZEo#9b5RHxBo$$l_2R32@hMyxkQBiAloAAv?{B07+1=!E8@ z5m<>1=&AVmCbYfeE((U^K=e5J;2Cs3XZauuFh7o>UJAW`37S+-qTB9eG#NiY*Y*fH z!(XH4(1`wr-dFa+)WDL7Dij<^J*`y|6&!8hdfPNFYfF-fW zk+jrnwFO!qf*!T=(EHxN(s&YG!W^H50arlJhk>{rkK-cu|Lo7gUy;uLd0OHg>Wgt9 zUVAizem%N|o6%73Kxcjg?cfyp6)x8o@xZ~_)SIHa=`Qqun~yHZQnbCtG4=QVpN=1F z#WH-b15K9i&<0MUq0cy$mbe#l<72oCJ%Vd}83x`I=ThH;My}IW;Rl+@coX#vI1w*B z9&#vooc(`07arh(H(Yum{QaK6IGOrIG&d%H9U?IY`%!-whvGSOMmL`ff8}xrI`EG$ z6OW?F`Y)Q)xxNXzBNOXTulx=B-v)+p!4Qo>JG=|sr?asEu106{CAteP|2DkkCZXrU z8#oxhM&AvszYF)zz&_NU!Gx0q%xo`X}EzuW0M4zwxd-yf|R^*+N zOkAW;l@Ds12@x2AcDx!Z;YrMbxzC2R&4(^QQS>NYgs$-hG%~NCOL#6`&+?o24U*&{|%#1f(sMyQe1{6<7zaUpFtbkg67C;Xh(lyJ1qWJ$oA3L zh591wgD3G;YiD#k{dOW%w-T%*`IkN*@ijV(c|NG!K@y0V~{Q~+r&iZc%RUvc$ z-OvYzVyZ)|NPQ-{O*h5QtNs@v))*Z~YjmI;(FpWLC)__t!T0}2G{lplccUSlgPsqI z(T=}D8$5+Ja1NbW`o$3P+-N&3(04?8bjE|x`=_AK&&CW)E~Mbd7Gr5#iOy^2`-*G>ISKwOQj89>YwDiOpOiNEsti~tM`&wqCry}|jntT_LcKG`rS<+J> zX@G{f8M=nu(CiqQ`x-Ox_jo<`CFzM>)bn9` z_y1=UQb~AedZIBORLAysJ1)oFxET9gmYzz=GdPNR?yTvlKU}^CGt&5d0H)z9*}`+L zU7nsO%6+}EhZ#@ChSay95j%sK^q*LoBR#do+t7pMlAP(OUoezFPr^QEa;-$)^M$Vn zUXMni2ll|(I2^x153shm(o^Tkbo6_}I&@pUfe!39O#S?y`^xmxHme+Mk1oNj=!5r0 zSE1YT6|{lR(C>QxpviXiRbgOdu@d!`*bygS1>A$>@%Q-obyue+Q`@Kg)!~83cn3E; zjV4La+~I-VXmZ|*9>LF{9qhvdAwQ3<^@VFfE@aCSW||kvalH*T!Q0UYZpC5vQJ!Q7 zVf|~v3~obbG!s4Bmtig3jAQXf^g!yHH$C+e(_MHY_2;oUrsqpfZMRlvhyBoRP^+;u zZi)VjBdE7b<_{x%5le94Yjh2>76>yPhl8mvKnHRL%V4>J>8Ufm3p$hM(GxLWp|JMt z&G=F$4{^&wkw>TdY2?0q~MyqhtBL5G zW>ys&QNIgI;w#t~zrxf~W~Qg!9lg;coQAxll8F~6G~+^!q9K%>&?9v%IAj`HTK^AcQ%{r$GoFKn_Cqwua+S3~{_`3%SqGyLore?fX*5EaK9K8^Z?q0=ECo266UEI z_Iqn|yG=m*c@X_Q!-wc|msMl``<<*#wGirI=z;Mpnq>cCb*x!EG&~%;Q(um** z4QhlA``~cuv#~e+j_#KBHA7_YKnL(9n#_OIOooQ5*9tQnf}Qx_DKvB!a5A>69q!wW zF4-Sw!xQSHC+@fIj7obbfqCuF+8@QbMS!6pU9%vZOgI~}{b#D~jn$KcZ>Mx_aZ705h$t;b- z+wBc>#9f-Cr@kO8M%R8B`gVK^{i1RJv*FQr{adu7->@~dZW``?Ai5k)-Y3xkJR9AL zS=|3`#2em1JJ=WNpI}bvU*Ki*KZ-W=Bxc90Xal=37rukcAaMlk=nHgU-$wsL2cETg@JcK} zJs+0D2Dsd08We9xvGze zkPofbLYJ~VdVUN+?_Y*aWF6+lZEcd_q}$I0M|Kun^Ypf%+}IGEK`(Sh!RS}1tvHkqUhWWbp-9KD zwr!&w(HV5bOzej)&2%*T=b<^V0uA+(vHl8rRKJBI@B~(J|F`cHLOun(;eIr9PoXE^ zCN$(9pf9CQkOvbN(U(o7&grS&>kUBb@8ER&8;#hM8^gdBp-Z?Loxlc6{rTT!3Wj)l zyy0N<6ZGsphVJ7!T|!beMjN;h?cgRfXU3v4o{qM+7#;Z2=!9NCpWBYD@Ga}^{~TRI zi1VV^UI-0gS@gl`=8bx*Z!%t_ zeofEN&NaQ*|JAurs8@RGm(88f?Q;t{qw#2mbJ2)A7+sDYIP1|FKZB)lQ@s8e_NM+N zw!-Ushuv`x8p+4-dfd^Q{cqts7wTY*KH)8R8=6edVgvjtUcaty*c~^cxv>}5VCGHf zsb4z3iQ}o4y*WMgi;NZM64&h)eni`j4)m)2>8anI)lE{kl?xBz2K)~l$dd!YjbEW7 z&N?t;eR;frdT(?;KZ*VE6LkOA85APY89lgqqPZ{(U8393gJ%|c-XzyhFvL61j`yNj zdl9|ylEER%i=p?`LK|*~cGv;Ee<-?ix1sNV$>`FqLr=y}(cN+$-6c71N$r|sB9nq^ zT^YM#OI(4Ep(Cz4BsAO>O}3usn%{!HFPG`@#YkKN$IQ2m9TaV_} z5%j*?BhwR&u^IZho{1GrjvW-d;b$y?g>DNsHbF;x58i}zM}@3jiiZAotc}@6hi%sk zmr|dNEw@~PUiLqf@bw$^@7n%bD(1U1N{QSP?Jal(F z5I;YFF4+pzay#21=qF?dgix4lW8!f<2ZBx6VUsn zp-1WcXhRR9=fNtp<8|mjUPiP09V~+<(TU|8AKK3|p8fCkD9!~(S{c2eA)3`Khr(#K5g$`(Ml0qhhQ|Os~g#=B|3oT@kx9en=p{kcZMu~abkMn0@p8~YyZcja84AtD?RlmEFz9?42AY zm^@0s4o;vUK7%gFKj=&{riA(x(L89x3ZeIxK_gWaZKpQ+d~5W+j`8z8@$&&_yW_(3 zWMXQ(VFtREb7FmQ^wH?!(RJtypNSsE;?ytVdMrLQJ@scq`_PwAxoPRCzdbV)$5Fq4 zbMZEozK8q&FADxp*lBwBS#K7Ork-|pNXD^feGyi{#64mESH-qehhhiZge@>_M%eeQ zu%fqP0ek`7P5;CG_&wHi|F@YLk|Bu|sBb_Ih{L!RbIl4lvKh_hLuhDEqoMo<&Hl^o z4cBv^yC)yI)}^BL(E;3uCf{gGnvIW8D1|%Fqw^cAhb8U{KREP92Q&{|>%H;%essJ2 zg?^8?e0KN>R|L(02GQo|(ze5a*bO}ow#{b$d-m_=f(?C*Zo@y&?9VbMm={g1a_Efe z#d>G-`GIJNC&kYnLZ5#cZTEG|g$K}G^d;KPpL1Ay8^}2~bWj2fT}^aG&CrH=#_PA@ zF6xu8G}gO6G&~3$_;~dGd(as!L67RE&;Rr2_j_4M2jVEJaT#A+P zCGbA=7)xxqD#{UoyZb&H*7?c^&mFKv<2a3$Cl{*{n1=YE~8*Fyp4wDG}=(s zg<&Q|(1BIMOl*xsaX22p`!PTESrj5S0eyZ3x+Kfc$h?I1^A;M3UyukV6aP_gjdDK_ zlBOh@-4$ZJ4w^iT&``EP2RaZR$GgyjsKA5a`QliMdO37=3_#l-iK%x7I-&bhpR@l~ zQ*iri#K!m{F2~=|kS|;uX7D_k6FbnQ`3S4xZ&(|PKNLdV2OCqLhb8bmw8P)grOCP^ ztbGN%l>QU-DHxJwxD>mhN%S+i9WSD<*@h2?2Bu&-^;PK0YAqU}XV9d237zSlc>P0k zJ0FeaTN<`;S4V{Un-%XV4}34>K|A6XAR)o1}0h7aE{h z+5tV1`=i_FUUWCCK)2ab_!z#4-q&wknDHz$7dA$>phxv<*cf-C?PRPE{p3Oink-7e zWGRQu8_h3!jkG7ZoWN7CK^#0=Lz^ft= zOD1|yaOOkMjwhnqW*#oW7txnf(+y!84M&qMi5^5pu?+r)-LUjiVHZqA2QVMq#*bnq zZbt|58K!>z|DJ*~{WY5Lba*fyI8^e-RMnhg72jaMR{c!XI zI-pZ%lBPc!lJP1`?f-%l?5G5m!}91rx}yW@8y$vb^X=$Clf?445DVd}Xc8VlBl8tH zkzb>KqPrmRT=4Se*#GsZU&94YxXx$}EJRPNweiL;(OvQbev22-4vs$`exf;r&g={} z!t@tHZZt*j8;s__xOn|RbYNRvVESa2~J6?3+VFEzy_F zUFgBI3CrSl*bJ}Q5<2dNz6Bpbzd!sBGx2Y9LWN!mNt|p(!L{p)z5^zqBYXtihOeSC z{|YPMpXiBMVr%$?L^pIzXGRy`FzSz>IhFQuFe|zgxzLFg#t!cPsuY~j^!ULx^uhgj z6Mlpatm?M#U?=QFeK2;$9k>av+#dcY=1nwm4POb#+6nEj54wFvqY<8kso(!EqtK5F zn=k{fel=wGwdez-&}~;A&5<7HOom`nygk-mMhCP9-9>p{3rXD+9l&%nQV*feuf#0w z|BV#fHZR5xw#WM0==M7huYZnNsQ-W-K)<3(b=m9bslVx14xRY|bo;JCJ6a#FZ;99U zqW$g1q-%SKf;0OG9pQyo&$1(gDmQvx88lfN;gi@0&EkwVLWFXl9hOGViJE8x8>9Di z$L`nVb}U%BARrQpu+Kp8Z<8=|2bk2Y{0nj4GI`n!6XNHy z(Oh{H9pD!9zFl}XevZ@erZ>YM`5sGBIL?K^Z-oK0+!KDA-2t8POX$pYpdIf+8$OCg z;s^A;)9B33V<)_9ZrrmYoNQME;_Nk=!^%WOLQCNr2oWh3WK=tFnZ$!bWPLW z4WZ71K3ELPVtMR{-Qwr#&q6KwsMp(1_fHqwoowg}L7gUql|ok<|ae(m4G6@XM_S&{+RGa) zjb5*Pkp1t^a_zX_J{=xEm=SMW8m~Wzj(8WE#rx0!9LDSMdn}H{KL`h%V7(heJbo(MVQC2izWA z(mrU!Zo#{74BFpM$iR|`vlM(F*T*5N3#0qF0@^`!yc3(D_q~b^_mdFX z6=+1BNAG_tUjGnn?<5-8vzXicf5nk7!eZ!wQ8C&HUE}d+MDE4fxEOsG{12PrQMBPA zpN5cEM!&H1K?iadnj;I*ZMzR0*r!<9{r??>5}50=@OrI*CPyc1jbqU4-j1&2f#{Ez zN&S+~!;kBwqGQqPuc4v-0)6gVY=db>gY7Ws2TLfl#23(x|HLks_lvL;x1u2*hvV=r zbWMLj@Ba%kG2gL}D|OM&yQ63Q05p=fp#z$Zwm0V(`@al@2jYcSurc-BX!2xy8A6*g zS{TjpifCw?qYd{$x8F!~LW|G=JcBOPR`kBN(S83JHpgGTOopVX{#AIO1v=tRXcG2~ z4nlKd1iF9cqucgzG&i=PIj|>wei&Wr@6e9Vp##ZwJPf=5dcAUzf@|9py`d-i;PB`~ zwBh^Eq*)rTuR~|DCDz|TXZ#5op%YjN&!Yp(JP{^V5pAz-G}(qiDuif*Bhi6OM;m$o zo#}>H--R}K1ReM{=yQL^&vShpIx2;>TMZ9k3pAnyPKNu7B1xZ2)TCg@d!r2xK}R?q zZD0nPEDxh=yAn;J?Px@HqhCr7qB-+3`u;x`KmQw@K(=qf0aXlbr*TU5Umpq;xNrx$ zZ`YzT-;I^=Q%tShx8cX^0_f4%3B5iHZEzC0jUPgv-;U+*AWp!)u{4hTE_~m36z`({ z#J?0Az{Kyv%VQmy%?GeGp25{v|A+8Pr(^ge^@=}+KdwKF>!}z2Dg4%JAG#!?e-5wd z8Q75ePBg+7qd9(I|GSOyQ*bRSp&@OKhVn)<)P2#czXe^xJFzNG!*TcmUZ2JQehu&Y zn@{np80!DSvV30jw-AYTXghbH1D^d`{Qh70_i)Dd#U^}k2y5cCXTpOwpuZou6HDPs z=m3tQ+wzLD!K&zhyP`RD6S@?`(T=BMAAAtakzdcU|JzeI!vz~|@<;e8HVnOC6uQRa z(V5RgBXmESq>rKzdQeX=eK7Z*VQq_{ z$+Qo>@f5lwf5m$GUtxyXqj}M_EshSb3Yw%1(dW9OyQx2#tmDzhBp1XF)}inDZFoH% zj@Pd|AHJ;?M+Z_GJ!q<+A+Co;q7`<-9%$sAMI*Ke-M-t==XXW-Ap=Y%KBC~rf5M{p z7rGP$E`(pXHbFx?8couf=uDQO`~F$wb6mhLMJdEv-tjh zgn~D&Ku7ol-iXhlU&|B!gr&I@&4oO%UJ7lnCOYE==m46c9kfIv)EQlpo3I+*8eNIa z-2Wd?XpVXQ4I}T3=E7QZhMUmre;9=tSN_`#Fks z{7bxk{v!L|2D8$<4PK4TBp*6}>i7!QLqm5C&5^Qc8L0-_p}El)?PzSQPe+$@3EJ** zwBt3g{#>kYNlRv=j>?@}u){-W$c|z<9*^~t(I3!A{E8kZzoWY)OM2+25&8~kfevUe zre0=fQqMpm_B1;2%}EN5^mX*>^IPcIeF7cGIW(F6#;$m2MtHCf8mU{*?4OQCVi`K) z=g}FzghO!`x+G<@g!>wy15I|NU`OL|G)_ck_&qwppV0xFL+?wwB+U3yyqS6voQ12f z9+tW^BlTObf%rc4Eog4dxGW>JEnmU$)HAYX_?yvW;!X->x$q2@#KTwu|HjIgnJrxJ z6ukot`EoRrpP-TW3SF|lJ0w-FD`7Op!suWr2Zq5N3jj{?AI^@8tjGxs87g~k$4+F!Nd6Y zwINp~ zmgNsw{{r@;z8hV#f(1gdHHo%I2ht18p~2|OW)#}-EOZGL7sv>I{=bY1X8nt37Vkl` z_p^BY+j#u~`mV@TFsx}IEKR*6w#D{X1|LC_aTl5!|DyNhD-;IM7*|v8P>B6sk-}*% z_~3PgLnK;ZW9q%p6Y(+h?f4N6!PA(DJ+2EgoQRiEzXzS+T=c|y1f9@R=Ae5N&TJ zI)DezZT)blClh-ql;Xnw&=LKPc5nf0Fk7+EaUt}CtbjJy79CiRSRaTSD2dT%Qm#cO z^e(ytpP|p4LQl+pu%P?y+T!7ZYUquP(9m{8XFL%NjZ74YMK4=myL~q=NcDNtSf$z`(URpBbMnTM^-U2ev7?2OaPcY>dY+>6#QN71pK%dP7-s2`Zx_ZHR`x6S_pB(6zqkH9bSQ)QxMzi`YbOOiF0sVoau}b;yHe7|i-glx)oqUUeq1}ge@Cn-S_h|N?LzC&! z3K^-NWO89^>ebMOCZiEbqRDqZnp01sGk-q%GP*0?KqtC4)RT#$6zuS8^nu^70iH*f zq;|!SeC^QsaCGKV(cF13`Wza$eQ2_Nif-dS(X}pEDJ)?#bhnJa)c^kHJPJOz4n5C}W?=O8c>P|?hO&=B7py%*h1_oD+@i{P)bbf>Bz`EJIf9gL;m zOeRH>=-SUhvvdhMfDLE^+p!zIjpjz-YT@%z=ySEv+-QY{z8yNi@mL1$#}c@u8vEaE z^(hzJE{W=)!)EA>-O*4b(a^5Jintpy@icbFt7?SE3`4Vh2HL?H^uWniGYp_A_M+Yf ztKiz2?0-Xghzst^Q)tKv)e6a037t_>G~_p;5$k~-O#PxG&REpL@v%Vpk^*5po4MjtGJDSb&(4}||P3D);?Y0+P!uQaQ zze0D%X|%oM6?MXhi=&aKiuLgZbPeaA4b4Yq{!qNW9NovO(2lpF6L=%~F?t^Sf_9jr zZfLI@nxvKR1Nu)~Pob?hTpvQ;1D(NebZsZ%NIZb&v3|Xf1GVaBr2dR}FglY*(HTC6 z4rE94FuEIlMz?jo24N{XV5aZ?E)-m|+tDPu2W?;t+VFNX3ExL&`Wp_y3+VZ9bHi}o zFlC2Bpab{=J=1eE4r^Ts?XV$w zy)`=Hf#~)ehfZV$uEht?(AR7d2Hpj|zb~4sBQf>pR7H85Ax z5X$E0^)YxoJ{SEVTB2Fp9ax9YN1%~ii|(Q~(f;0P#{M^{_H&^l9zsJ@qIsA}c{CU5 zqT8}Hy6t+SOLGf)z}$r{(Hb;zd(em+MNiUS&;ev?k&*iEfy!cc>SJ3Z!~6OjE*O%` zmNC?5C>x>!xB>0B4?5r>(NSnl+=1Sgj4nWzbOjpn7jOmcL2@~oss$%5gMYo@et8;F*S1@nJMK-oYXGFPamB+l3?jar7KGfyFWH zhH$i(#D4Do4iud6bLg3T3|+Ha?L$P$V9m3oUUQ=I9*WZhO!rD0pK?vWn=-q#Gs}z$pBj z`sgkhsehoLUDpuOeR!PfC($+E+btu}g8K(|4;??%4Jmwt~LU}(rlhxP(-$l1^zQN%f z8H2vG?!f!-YjmQw-V&DfMf51&ouuHAyB{yZuh4DyJ$m5$iJo-nL&C|JH+mg zm6_Na-@ZZNd4K)37km1;jI~o{`fMQ3;9Ndx8e0zl6p@}{rex&D7ZEo(5(Fx z3uD&XLg-4NOHc=mKznq6y`qEA(BFpMHys`D67&du0zI-{L?^flP0}NN&iRwLbX2$@ zH*&Njilh6wbiCdi-Tz(j5}X~cFFhQ6;mp~=!M+BZ5VIwCq2&6$bl^E0B0qAQ|LM_(Sp{`Y~mxM0W* zpxJs1o$2X#<2iJfWQ+}=&x_rt7ezyVCpxpaXs91X+g%?&e=&ak78=QeXnR@4vHzV} zzHy$|YJc@?uTl9eo=*+LWGt|qY5on5@2VKzD?P6?*2XGZ$ zF)`ftJo+-)iS(CDd`!WY#7Q)JGbV-KerKX~@Bfsd(2ftTM^_3!`fq~J{UqS^f++VM$r#QrIn@A-V_ zu4sZa@IEx#U&Bm1iybk~^w9Aw=#q^>mtab~J_nu1gVWjnsgZHP4xT|rb_h+nFVXk@ z87zfY+#SB>*F+oci5|H_(6yb66>)C7z737kduVPPLi;<3_VdTxjM&g6?g^pKhBjOT zy|E%1k%s7iI-xTkj7IEHoPz7nr6@KdJXaHa-L^yrFamvkEIRX9XutE56x=2cqib^* z?eNQZ!*AGw`UNysZk!qX5IrAmoE36s7P{?Lq7nHFr{XER7jL^aBlXX6p2Zo|C*2pm z0VV&XFq{kBXNNzv+KIKOx0@6Gln}Q{A2D)}n zp&h-5HuOF&$FFfCPJb}uLdC@yssA;c#`rwfe?r@N?4j`Wd>2k}P0vu6iDQ<8wfqAY zP`~2gjMQJlTY)c9{|#NcwM)Z{NckB;62PNPRP|!Dbs$Km8`YO;UJ* z3oV}tq526OVe_ZMe!d$$A6`di_zxP|w$FsGW>e9V?H-(f4`N=-x-sNPCN`p83ti$n z(4?J(o-@g16kMB)XvZh9AQpW#BufMIi^mXjNj9J_tN+mF@;(=Sn(c`0``gja7h@)F zL?iJYx_kablk<}2Q|}7Se+rJQKYGJxbVhfgYjhu)gj=GoNB5#9<^k-2pQ3AD@r4kn zL0E$Ni#Py3Mi06=FNWk>gLT~hxi^Io-+=z+;uf^wRhR{zM$dug z1K*+h{y%iBD{l>Nx7N|VXe7s=C*w2!|M|;dVtvs840)OTZ-=*W!3fNVH_Sl?usGJA zKp%Jx4gE{#xv>kc#@yS&=cUlkE20Cgiymlg;^+6F$-Mvz;nUmL|Ay*qE|`3W(19F9 zub)8I_7wX5&c8jp?JA<5cSbw986Ds#d>to5tG|+w*iHR6+=^RX4S%8O*4Hu;JE@mS zz8+@!9Xis#(4?!iBMhV-8uBLSm&l&zl8i%VJ{irG1!(p^f)3<;bgd7^`q${henfNS zG?u~S#rQ#)H!@QHvOy(m=M88m>+cNT`C4O3>I-lK9>y1O+ODwAtLzTnf;(e%uJ6NZ z)5wu%p0_d*Tex0fPxuOV964{2i7b1=*XAZ@gLBbrt^amL>OUmB8C|Ql(Ub5bHpk-c zWTgH_s)u1F^^4KWcVl~aBiHBREc^mJCkE{cUua&&)Sv%-O`#1R{DXGf@_%8ChhY)w z^P(HkCDb}u&m`Qy$R>Y^UD}I9I-TxKd3mx{v^3 zxA`EvnbxLozK!J9-;4vDwGryWwE;`@wNEn+txDk@|PP zn&TAekE0Bwo+0S1du`4AxyiX)xgnH=_v{1xf=4 z!8oA%OY5fc1mz~I2etvbg9E|)U{5gWmG$lS23U!8!q@UB;PF?VNhpq4V1Do-DAzXr z8|#Q7LAk5@f^s)+2aAKBL3ttydFy6=K6oEc@;%>KSPJxJ-A~tZ!91)lgL3pP?|Fif z$G<-lDKG?-M)rdu^c{=@^L?WrZ-Qev6S*7RzgR~b2FeKx0Oc+|0Lmpw`_($?9^fd}2SLe;{N`qU z^m0GYm$k=t>jw{iunX&5U|lfp59>wlNKhJj@Po&{T&s#dt(#>#DEGi^up{^hlz6jW zZpL8nEGRcm)!)|9wg(rn9uLk01O8YIp8{90_W5hQ4SyDF!n)8u>$Tt#pa;gydCXK+?jM&901x_k5Ix`Fahhyx}FD0p(UW~U^6H$T=szSdf*5s54-DN zBJejTg*zs<^Kxw44#s`B^a1tmx+yKhWcMz1FT?1t!w?KI&d*K5BeH zFV^9peD`Yv+T|vh$wXeUELYqE2C}{c%FPxxp|z8gpj>+&P+krDgR-NNiWNa=tQIKu zOe;_t7!At3u@01aM?i1zQbIoeASaX0I3zJ+BAfYb*B_Lp$ogPba5N~q^`M-<4N!LY z9h3seJ#FT<;ZVg+pxjFT z1~6|b>z=u%X#dPa9%k`VTh9YYL3!M!2j%FpfD$jL@d!|!nj=Bs?FQv;KBV!>pj^tk zpxh(xK{*Lq8ta5ogYtZl9pnW0{~wshO_3ig50(UFXA?jvFbkBOF9bzs11Lv-2$XAo z8jKIV2j%(UCn)zuinJC#A1FEzpgb(gDb@r_%J=^$bu0sAC!0WdSRK;!bx`hw7hp74 zE1mTWxf_%xmYbkFD(->B!PlTP>X+U+iQ=I6tATPUrhxL@@Dw;t9{;{xHscL=7?hoD z%3wWwc7gJ+yaS5hCtb(QXzkbwl)~9S$qNFdp~4yu2Yp#r0ObTagU!KSU@7npXqP7( zpG?*hL&9RNxEd@1zE#ZQZ9Od8fWn&zmI0rDlR>}CHlqo+A6yM)&SEoPU7rC* zurB0dGp>P$z@^~qtUUg^GYR*#nXl7h!8WX)fE~ap*=**YWb6ZrvF?@KdJ5hS`muft z<^hxCu$ixvih;RUj|H28v7kJIrpsxaKoBVRKtWJWu5?bjb*-!8$c>{FC{Hj`LAmQU zgYuehm#)8Q{2wUyNXA?iF9?)-rw}MNVI(M*qy;FChK^ufa1dAk+yG_)U)q^SVxrvo z45;W2$}61+uol<|TnKIjrSsZ(tcO!`P#zuKKzS4l0bRjypj^6%pj^tcpggZ6^|P6; zAf8pZ6PpBD5HkZyFCkd7|<1w*>2g@&q&ylzZVQ zC_iX;2H4CWTq3~QtY?5F!S|p%3PJ+SOKLaTGbw>%t>OnTpAdqqg3(|A>jj|f}&}b4qgMtgK6_yIx9fYzX^uOm(Od6<*~tAJHN zdAu(K#~7y#b2QD^MExs&UtX){Z*D(69zC`{C z;`tGje}wD~X3{2}Q9QAB7S6np92*u7{%G>g%k|&Jf}f6!eIyQskRM_LMpFn5^OWPj z-0+7m#5ya+f~_f-h{nn?-qTbHh6`GGv|yw*)ELcn>Pv~Q7C(O&h3Ie@39lJ55#y&V zUXEKu-jFbg`CaR{jQhCf!T*LoKz$iiFqqsya6hBtu(lNW0FSp13{P@K662qfo7Nn@ z+<(ReoShKu4EEIH68}>YDnm-aIKVssu>+jMI4%4NoI*|p#7i@mC#>Vz_-GNp#=`GL z6KVAXX0mR<{HhhU8&g=c(W2`JitX3+5$63EscB#!g-Rp-7XCm+Cw37J?2X@HCus5k z++6C&N_;HwC-@F((+=)*YITv%-^@!;%nQd^a6QER?C36HV=3ZJGgWn03lMbJR`_-C z^RMZR>e|Ez@HxJYXr4nuY%)Bt!{}UvyOME_u@rw-^Y`xr&uDiC2%J)}vYIH#SrHpf zY@YH$X=Jwqu*Z5@tH^82{4B$l26~XwnfN8~|QGi#- zMn{CYlDvU+5B%=LYeGJt0=%PQ6wo>8riGBR7T$jHKj29Xzam%%u2?O!#3rz*8Em2r zyaFEFe|sTrV37sqE=b8pXb)ya&=cQx;+rYfkw(%{pcn%0n2Qa;pN!lHc#FVlU@iC# zeBv8sAXb-;q0zzyQn(P_vA z_gE*w-+v)CMvsU83Y524cz;(5n!Jn99Y%HhO(^Wn;H@CT zhu9Xh#Kvh8K5TL;b@*RBjW9UL(e5hy&&DDRiyDv{Gmq!AgGjA1SR_ICq~g-E01O`@@G6kNgxgd^4k-wxs~_*UV&ZAVxvCxOd4=ViHRyutaO z)gj>}2?g0rH;KcK&yK{>f{}0^;QtKg69x7&c+<<6&X8~M)9_!!R|@U`=FQ=5qha&< zZ&0Co6xj;tD+$S%i&dhar&A;1O8{pj4Fn>P5}~?q2S`)cR z5;NMfZcV(Mby>{%#sS1W<6Ot!Z6D*4im487MscKwi9MvKSQ30=ED_!By`0&nxq5fiW^ZAyQ+nUlGhr} zc5-T{xWsG0J+GV~;@&hi9sCNfx}3VyKczeJK%@%JOOWz0e}_;#y58+1*oMRf2=a+5 z=3}!I@qUa`40%ylmHbIecaWb~3y-1+AAG*}E=W;q2{?xw`&2DnoJBndJxOW_i9J!b~2=3gt|BtnT~%HB1z$10gHgs5ov@!8@LzjOR?wVRHWIQ%p0J=Uu>9` zNqG1>k~a>{N7m-~e=#S#wu8Kx4rge>9xKmi5BawG`1BRidg5Cq>0ltSv}mMebR_=< zMasi-A$AHIW18^F8?4UY!P zuy$crn^|WeclVTqmy+9$;hjJ`)A0Bbkxvp3<40!W8-usj`A`PS*8=DdU(8K;ONq^c z69onn>w(TVja9-oSK4>7IB?qFUq;SA`Q6S=7VSwG1M#$ON%*{rVN}ImPX$T}!p+AP z3XuFm{qCIAEJV}5cUUXdyWzfplaP2q&iDrL;-JI&u+Gmf7L0)u-2&MaqS!r>9d=T8 z;#l7zHkQRtEq0W6I>t^K`a`S&^Ym!l0UzTNyM%r^=H>C%WiCInb)nWmX+|E{=Sbv7 zBZD7#ON8@2YV z#g>ED@y&wwl=&(|`317E)@dUa6An!lhT9qx>kn@@Io@!ukhj`S;2Z&8#swU+goQ0Y z+@JMq*#>rsgi|`VJbceZ><8jv;fyWJ?~^CCg(B0fsgaPp70N5DaSa*vf(RFK>ij0e zX^hJVTwz>g@V{Ie#Z+Jom=&McV45FIlaVUQZ$yn|_)BV|OPm_6O{@iZp73i@FA#hX zm+N0akH%EgFH$QjqVu(=xPKwG5|PC4Ym?jy^h59$Vs*Go`{19!$FEzB zT?)mABj!!vGRy~4GzR`ccr6$S;S9Euc$LB z3UM=Y-u^NQLrxA3XH?cx2!T@xeh*E)fPWF|4~&8E?&%TdVBL_pFB+LOm(O)FLaDn! zey|gp51|Ldmn3=+6f3Qb4aVoNEHu;#UOzZ>m^VUj1S1FQjqv{v6Pw0ptaDkfC*Ip> zEpPnQr=bO|)bCGXO@giU7$xBwqLCEdq{ZhWFq8zb7GPeE@D&Xt!#@}ld#0#hIr(~4 zcfC;qFlnEPizz-yk4v)B5co=w>G)!_=xmx?rismn?@`eNG*|#$aT;-$8##IK z&%yBBhuD$K#G)u;J*h_A;l_DY(jU>VJgVg8BvO0Y6@s=~X+us^^# zm*l=G)Pwb2)=R-~^`&6`2=OAI*f_+~FrR5H&98Zg=V#282FO3i>C|RDh7EQC#X3@W zyKbTr{%Y~K{tF;GY%9s@AlDKRtf9slu&$_yRS+qGzq>Xgybi?5Xp#Jy>n#B+IlRQG z(@;;iA-*Ft!2WqNR-LlULDypKNJylDP03%Cd2P0~7F$V6Bq5_tXsmF!(1!`4IgsX>)L$&ZN=g!!IHZB9f*06)Qa^yZ7zyt zs1ZIGj$(+F zAVKW81?Jb!#3s^c9~$Y2*m1-^u+GJ)B_#i-Hjo+K893MRKVqz9BVskcuH>x*^TPc` zjZ<>{pF%pQg_kjR*ic04;7_l@u@viyPi(dBCQQX!I_3R>pAx@6{CAog&D=)8UyMg+ z%C~*7Q8M`s$(4?;kQA$eCA3gF$mg}WD^di3s}#>j&M^G{m@mSeocuRh>=wnuS`#0E zeqwMa>$c=i27klri@zH=_F*hu;>=FL!eAZ*J0UOxf~Piv+vti&JOpkq`obxx4aTru zPE+$iu|~vxk~aaL*f@%aePoP5w>NpY)mPc^{eK?LffV$DkV_MjQg8yqY{U+m64saN zTKKp6=D?TV9M06dJK#GSI6y-q(GbgyFE{#P)xl=O+n{}2K3Jmw9hcYSOeFN9i610y z=VY3JHMC%DlKwKp_?^5FmzWpB*+LM#s#*?zB$JEy2ci9)JcoUzuH1h{OA4i=$U;s0 z2M$E|G{u_W|HC>TxQNa#BP6z6u@Cbg<}c8wtIf%859c}+5`G6MhAl>Clr=RbVIa^l%(W*0b%Wi^%@Q(&tv2KjE z{0jX!zFYFf&M6!vS?qP{I2hr?_*3COV@mVWFv*u$cTnCrgbU%zg3pzLN0`4S_MLT7 z@FDSz+TcTquY}Vbt)}?o*P73Xe>cyc#UBzHv9rONkcD|6J%!Tjqy(cLzH-FY+)9`8%9~gT7n7S7sa2CbxLA;@bO{QMlI%FC>+YDitY&FVpY&Q$@+%l z`M)K^ONg|Fn3Ev8iy=Q0y}C2k50FZv}b% z7!#Q1p}5!x^FP*MaspBzlBcoDNC;xt5t)HN1%%c!A4$?M3Z>AZ(TF*$h*Q(g;eSA9 zG5nWs=BVCrd}YXQ3-)DP7Qa0HGf+5(lbDFEgVCYcra#f&K6=(P%a+#fZRfZ%N`;h;>K~1xw3F`s0*qC)Kt3|uvhC^&T;%gy^<zGK;En)KYV04HsqobUztX@Y)joh$Muxfn zyChtK@D7Ks5^x#iw4pB~%Ab6iM*I&AHvog-pTxP7Vza>%j6H1V49#R_KGD%AbFrkH zidZ7_#=|=(?}_(vD!30q0s?g*ltuI)qZ&nK>TU|+U#tA3PI<{_C=SiOqREqRj-m01 zLXE%%+W3C_^BMcliicn9l{_cDg)oYMSR5KCqr$_O??bdD;=REH>?RS(VemZQgfd)- zO@eokFG2BROP7#NNGU?5j zfPapYzqZbcqbGKY+_!r9wo&jMb1zQv5BL}E3~kOnmC0ZwO5%7(V#hd@YI=0x#5;3B zzO0La*WkENsQv#nephuKQSct|C1{t0KgNkMQ9X@^T1*OFWITiS5ng-UWPJH! zmobobQEZgA#@hs4c3VebS3`~DCSAdZ(^x5X9~XZ z%n5M5K-(t8u5r-vXS=My!w-B+D&othn$T}e#+kx`|I6@l|&SJ(EnP3^^`+q%aZUkttO5^s!@M)GBA_Q@0(m=VX0D@Kd0;lz z#U7I0IUP|g#8#+aeG<#l+-$}*c#pt?;08qJYOz7!Hu%rM7L3H2n+MI2dUFsX%ISMgf0yXF^8mxw|42gYMPiF^}DR>>x!SMW*Zzl0&5SJ<~v9$0jv(8M; zUo^zt5{sm0Lgp!muVG!7v6}fF8n919T&x`wj=;tVfWS zp1C_*u?fugg1hmrV=fj=Y#Ysp&8CU{K^4k#ktranL!*IE}_98aaf2Eclv+TjD>4W?ANLG&9gl=KOQ8xJ}20K(Xy4 ztzg{O^;wd}k~AM*dc;0xvl%I}fcZL5te`fV4Q?AoQ~Zzc7Y8qsCw79dn0Z4sa*3J? z?Ic~t`3GlmMp*)4jTm_;=&)~)?Zmgy%sIrxrc(T&H8uZy|1JKyaGEpfqnnfb>f{Ze zfmWvMkhYQpWLPJd!ktiPJZGoncInp-Js3`#(nd{hH(_r!U0+|CB6ZQ6K|kvAsCOnn4Q2_ei>iQ&StoKB_^u{Vr! zXh!J<=d<2SeItslb3)#TP+SU5VO|~KKM+$PcAE7t@RK&MMTAvkix$IU%*U4%45!FA zxaH7`W;5RS>+7bH(ew}EVr#){^7{WUf}FY&aZ;T5A}w+rj#vZ@j0ew=o15lJFfRvZn!JvmsDckEc$zVV;cSNyTnsOh zp1^xVZ8Vloiw>dLnVdv@O{xO7DPu6aLGa3=zn$Ey%HKfDVfNGzN<%zP@E2n_LNoDQ zL39%MiuEnnUA4(t;0}Dv!5BCb^=PZW$*PUN1xFJTJ43uR{CN}&!=D5U*GAsOF~9#= z#IFcmqhLXrsSnO0aRy^1{$KF$FN$cDgNE&K@XMkG3bkrX&Z>*KoB$`Bu~}pNlv|FXx$z~U!Qad? z!jY%>V{EK4&HN;`mEw=VSP8^xhs$ZghR6fNKdIPT1QO!^gD(ZXM$DtMiOt{_{N4y3 z1N{-TQ8WqRpo@Hy-_MQ^aUhCh~q z-L=_)6m!^LniA`+Sc(RMDf$=Os2lm=#7~SyVYI5t>;D-94$)0&l1nPN5Dm11v`f1@ z3${W`Y$(EEdIF1-9|vwvVvm(ygSDT@=69cp&osX;+OE`UibgsQu74L5sR3ap!ShP2 z3T8(z2jtRl+Nodk7VB<0Y9qT@|0Fjd%{lCt>fR-`P)}wT8gn5`L$?iF^FO=Z0igjx zjYw#Lh*(0_v05;S>s1MXIp71vYGO^5mxY{%jHHZBy8F!R-eGs)bzo7RF_d^Hyfo;# zp|=&Ey&KM6kaDo7KyVNR#ERn|q4Nj?HxY{_@d)$2+E|e8%1aB@LnjltPl%6(e~x&6 zZK?~K%%waRd_&;c9DnQ_OrcXG%x3I?l$)Sf9(LNFM6sVFl>%=f-V1&g);+WVi6qX3q!0Y3}^$(@MI0%_F_*av?AidF@R;56H{N)(w;YBf? z6aPX36Lp7u!P@wC(?ny&VG68Lt!>0Q)AS~EUg(CFur5n|V=Y9n{v@>o2M`dO$hgD& z2bdJ$zhDzhZl%Jbz}hrZUj6;R9yA?@mRJJaz%OZBTF^%~ zxeA}yPBebF^3Fm%5`S4fqcTph2t`-$9_xEF5nmH8>W)U^D@bEU5RL`KnlgH8F5emU zKASrsc5qLZkT@|1`?+L`{oT)Hcgfhj2VB}Dj}5)zay55sIv3YRfiZ4>eu8$J|YC%N4te^AV}?yjdig8cl$ zy!{Il3=E4I)5A4uj=<>P0wE#MLCr%#@<-975H1>#>TiUoWud=v>$CmJMvsa8g(aG&Ys@PK_+)4$-X5Qu2BrIm#XE)E- uS)bgzT;oJF>()9tCi5KE%(3sjxE1q_DVpA9kG+%LRw;RGa6a3zME?VaeIq6S diff --git a/locale/nl_NL.mo b/locale/nl_NL.mo index 8981af67253668c8873d4773ca5c3b41be171d06..4a04d45af4c4f11a3f8d2e7fab6537459ef4a8e7 100755 GIT binary patch delta 67 zcmbQvKAn9-ArqI0u7Rn7p{bRr`Q&OQ6^+EyWFwQr)HL%%O9K<5WJ}A`G~-kwV~Z4v XB!lEc1H+Uw%T&We%e2YInJxeTZ~YU; delta 67 zcmbQvKAn9-ArqIeu7QPufu)s^<>YE66%C_Q6H8OmRO1v=Q?pbv!&IZxBvX^bo~bgbPY@u3{9;}&8F|*WK_{eOiea2NlZ;MPqZ{JF-o?yOieRR eH8QqHu}CsVPBbt~NwZ8fOtehf&cem0wh;hyGZt9@ delta 74 zcmZ4WjcwI8wuUW?>o~cLbqy>O3@ojTET-?^WK_{GN;R=GHBB{6F*P+yH8V^#N=-5~ eNlZ>NPqZ*HPcbx4wM;cJvoJE+&cem0wh;hXuN6-K diff --git a/locale/pt.mo b/locale/pt.mo index e79087e34ea5ff12125656213473a146f3ae5b11..cceb58932b6e40f3e80859ea81d3e445a4c67810 100755 GIT binary patch delta 70 zcmcb&n(5wZrVSc#Tqe2(rV56pR;Ff?jp9@^5>u0nOcGPm%o8mQOpKB(EmPBsQ;m!* aQY?}Tk`oOKQ_?I`4HGTXHrK@^m;(R`fEB<1 delta 70 zcmcb&n(5wZrVSc#T*kTv777NIRz?<+jp9@^j8aW3O-)mcQ%p_GQq2rgjZ%|LO%jvS a%o8n)%u@`_Q!P_X%q)zIHrK@^m;(Ut^AxrK diff --git a/locale/pt_BR.mo b/locale/pt_BR.mo index 8e4fbb909f5d2b77d6666fe5bb115ef721f5ca7c..b8e886277a877981fa3e63e7d7abb832158a7348 100755 GIT binary patch delta 27397 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 diff --git a/locale/ro.mo b/locale/ro.mo index e0ab67f16081f7406a1252f1c46cb7d2f42ab58d..2252a3f0d7bd8697192e717d7dc3858e5e0c35ce 100755 GIT binary patch delta 78 zcmex+o%8Q?&W0_FE-73lx(22ShNf1g=F|OB7*#Y9QwO66D(=@pl6f`c(pRQQREZW}Z#RSC6+xxs&cB}&cm~9>6 delta 96 zcmX^1N%+_&;f5B*Ele_AT*kTv777NIRz{Z7)x4Ng^o>$YEKN;QjZ;ib%~H(_Q;kxS zOidD#)65esjLcIE%~LH?P0TEej5N6z6f`c(pRQQREZW}Z#RSC6+xxs&cB}&cX(1fg diff --git a/locale/sk.mo b/locale/sk.mo index f43ee18595c471c2e340e3f4208f009d0923c1bc..f57e138da12986bdfde0b9efde131b6464e76a4d 100755 GIT binary patch delta 67 zcmbQuKAU~RCMGTuT?11ELsKhL^T~UdR5TJ(lZ{LgQ`5{7Ee%YJk}WM$(~MJ%j4e_u Xk_?g)4GdG#EK>~=Ez>4*Fi!>mi-QwZ delta 67 zcmbQuKAU~RCMGUpT>}dR14}C-%gK9~R5XlIO)O1KQ;kzhP0dox3{#C#lT1w#lhe!- XEsV@l49!z5Q%%e)jEp98Fi!>ma}N?s diff --git a/locale/sl.mo b/locale/sl.mo index da67dce4451688fedb086400715afa6a5fdff124..8cff7af181198571d5fb6afb2b00fe3be2879772 100755 GIT binary patch delta 68 zcmZ4HwajZnkOY^Bu7Rn7p{bRr`Q#W06^+EyWFwQr)HL%%O9K<5WJ}A`G~-kwV~Z4v XB!lEc1H+Uw%T&We%e2iaBVL%6%C_Q6H8OmRO1v=Q?pbv!&IZxBvX^b8${H>lkPN delta 70 zcmdn8mvzft)(yvRa2e|wSST1+S{YeRzIa1L!zk6n($qB7IK|Y|EY-{~)hIQ|)Fd%E a%{JQ#LU9TXtV6i>8$`@Z5Lhu diff --git a/locale/th.mo b/locale/th.mo index a83c66a7e72f2daca27402708122d8cd92986deb..41ca1dc8ed6af0fef2d2bb1b26ce37a5dc57a326 100755 GIT binary patch delta 106 zcmbQRPjSLN#fBEf7N#xC2D)4(x(22ShNf1g=F_conN_qCQwO66Dfrb{wEllUqxlD8oOce}GtxV0Q-$-Xt(MU{9HZn;}O*2olG%ztrwzN!5 kGfp)!wn(u^GDuD|Fic6aOf^ijOlw!kVA`&d!OVIH04_usFaQ7m delta 80 zcmZ2^MPTI>frb{wEllUqxr}uUEEEhZt&A+E-$-Xt(J)Fiu{1SJHBK=#HA^)!Of^bP kGBrs|PBTxmFfvauG*7imH8Ha=GHO@JVA`&d!OVIH01ucLCIA2c diff --git a/locale/vi.mo b/locale/vi.mo index a9aad1584c924b12dd1bbef6145712add6647904..e94e8b1c58018ca4473607733caaf2bb95e593f3 100755 GIT binary patch delta 76 zcmbQVnQ_u)#tqKKTqe2(rV56pR;K2YeT`ML5>u0nOcGPm%o8mQOpKB(EmPBsQ;m!* gQY?}Tk`oOKQ_?I`4HGTXG`S`xNGNUIYkXA|0A4p1@Bjb+ delta 76 zcmbQVnQ_u)#tqKKT*kTv777NIRz{YSeT`MLj8aW3O-)mcQ%p_GQq2rgjZ%|LO%jvS g%o8n)%u@`_Q!P_X%q)zIG`S`xNGNUIYkXA|06u*c<^TWy diff --git a/locale/zh_CN.mo b/locale/zh_CN.mo index 66590925638593a9e9ae14a9cf9793b92a71e126..8590982549122311ea46627962f268e16c862683 100755 GIT binary patch delta 74 zcmcb0hU3;5j)pCaGg7%sbPY@u3{9;}&8II)WmM5fOiea2NlZ;MPqZ{JF-o?yOieRR eH8QqHu}CsVPBbt~NwZ8fOtehf{w|d<=Kuhn)fkWf delta 74 zcmcb0hU3;5j)pCaGg7&Xbqy>O3@ojTET=C@WmM5HN;R=GHBB{6F*P+yH8V^#N=-5~ eNlZ>NPqZ*HPcbx4wM;cJvoJE+{w|d<=KuhNQ5S{) diff --git a/locale/zh_TW.mo b/locale/zh_TW.mo index cc938ce517b88cfee9a01e74e5d6b02ffc524711..cb5a3cf38b287278e00b0da1706c123eaf161813 100755 GIT binary patch delta 74 zcmccco&Cah_J%Et{ytnLx(22ShNf1g=F=m67*#Y9QwO66D Date: Mon, 8 Apr 2024 13:36:19 +0100 Subject: [PATCH 20/23] Layout: cannot add a layout if you remove the 1920x1080 resolution (#2474) fixes xibosignage/xibo#3332 --- lib/Controller/Layout.php | 11 ++++++----- lib/Factory/ResolutionFactory.php | 23 ++++++++--------------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/lib/Controller/Layout.php b/lib/Controller/Layout.php index 0e59789ba1..91dcae7dd2 100644 --- a/lib/Controller/Layout.php +++ b/lib/Controller/Layout.php @@ -415,11 +415,12 @@ public function add(Request $request, Response $response) // Empty template so we create a blank layout with the provided resolution if (empty($resolutionId)) { - // Pick landscape - $resolution = $this->resolutionFactory->getByDimensions(1920, 1080); - $resolutionId = $resolution->resolutionId; + // Get the nearest landscape resolution we can + $resolution = $this->resolutionFactory->getClosestMatchingResolution(1920, 1080); - $this->getLog()->debug('add: no resolution resolved: ' . $resolutionId); + // Get the ID + $resolutionId = $resolution->resolutionId; + $this->getLog()->debug('add: resolution resolved: ' . $resolutionId); } $layout = $this->layoutFactory->createFromResolution( @@ -3363,7 +3364,7 @@ public function createFullScreenLayout(Request $request, Response $response): Re $media->height )->resolutionId; } else if ($type === 'playlist') { - $resolutionId = $this->resolutionFactory->getByDimensions( + $resolutionId = $this->resolutionFactory->getClosestMatchingResolution( 1920, 1080 )->resolutionId; diff --git a/lib/Factory/ResolutionFactory.php b/lib/Factory/ResolutionFactory.php index d34aa187ff..bf42887d85 100644 --- a/lib/Factory/ResolutionFactory.php +++ b/lib/Factory/ResolutionFactory.php @@ -1,6 +1,6 @@ $height ? '`intended_width` DESC' : '`intended_height` DESC'; + $resolutions = $this->query( - ['intended_width'], + $sort, [ 'disableUserCheck' => 1, - 'widthGe' => $width, - 'heightGe' => $height, + 'enabled' => 1, 'start' => 0, 'length' => 1 ] @@ -203,21 +206,11 @@ public function query($sortOrder = null, $filterBy = []) $params['width'] = $parsedFilter->getDouble('width'); } - if ($parsedFilter->getDouble('widthGe') !== null) { - $body .= ' AND intended_width >= :widthGe '; - $params['widthGe'] = $parsedFilter->getDouble('widthGe'); - } - if ($parsedFilter->getDouble('height') !== null) { $body .= ' AND intended_height = :height '; $params['height'] = $parsedFilter->getDouble('height'); } - if ($parsedFilter->getDouble('heightGe') !== null) { - $body .= ' AND intended_height >= :heightGe '; - $params['heightGe'] = $parsedFilter->getDouble('heightGe'); - } - if ($parsedFilter->getDouble('designerWidth') !== null) { $body .= ' AND width = :designerWidth '; $params['designerWidth'] = $parsedFilter->getDouble('designerWidth'); From d2363a81cade5d5ebce8906ea6da6e48e80a7e9b Mon Sep 17 00:00:00 2001 From: Ruben Pingol <128448242+rubenpingol-xibo@users.noreply.github.com> Date: Thu, 11 Apr 2024 17:12:56 +0800 Subject: [PATCH 21/23] Widget: Fix marquee effect implementation from xiboTextRender (#2479) * Widget: Fix marquee effect implementation from xiboTextRender by correctly setting pauseEffectOnStart --- modules/src/xibo-player.js | 3 ++- modules/src/xibo-text-render.js | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/src/xibo-player.js b/modules/src/xibo-player.js index e14eb77c39..1b31e21da1 100644 --- a/modules/src/xibo-player.js +++ b/modules/src/xibo-player.js @@ -1711,7 +1711,8 @@ XiboPlayer.prototype.renderOptions = function(currentWidget, globalOptions) { globalOptions, { duration: currentWidget.duration, - pauseEffectOnStart: globalOptions.pauseEffectOnStart ?? false, + pauseEffectOnStart: + globalOptions.pauseEffectOnStart ?? true, isPreview: currentWidget.isPreview, isEditor: currentWidget.isEditor, }, diff --git a/modules/src/xibo-text-render.js b/modules/src/xibo-text-render.js index 5990baf6aa..d302348298 100644 --- a/modules/src/xibo-text-render.js +++ b/modules/src/xibo-text-render.js @@ -369,7 +369,6 @@ jQuery.fn.extend({ .css({'white-space': 'normal', float: 'none'}); } - if (!options.pauseEffectOnStart) { // Set some options on the extra DIV and make it a marquee if (isUseNewMarquee) { From 357a7d434b6c72c19485a933b339d2543a4e3bc7 Mon Sep 17 00:00:00 2001 From: Ruben Pingol <128448242+rubenpingol-xibo@users.noreply.github.com> Date: Wed, 24 Apr 2024 15:49:30 +0800 Subject: [PATCH 22/23] Dataset: Fix number row that shows as string (#2494) relates to xibosignage/xibo#3405 --- ui/src/helpers/player-helper.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/ui/src/helpers/player-helper.js b/ui/src/helpers/player-helper.js index 1bb03afac0..0049b8069b 100644 --- a/ui/src/helpers/player-helper.js +++ b/ui/src/helpers/player-helper.js @@ -281,6 +281,27 @@ const PlayerHelper = function() { {group: groupObj}, ); + // Handle special cases where data field name for override + // that's the same as template variable + // E.g. When a dataset column is "text" and the element is using + // text element, extended or not + if (props.isExtended) { + if (props.type === 'dataset' && + props.hasOwnProperty('datasetField') && + dataItem.hasOwnProperty(props.datasetField) + ) { + props[props.dataOverride] = dataItem[props.datasetField]; + } else { + const extendWith = + transformer.getExtendedDataKey(props.dataOverrideWith); + if (props.dataOverride === extendWith && + dataItem.hasOwnProperty(extendWith) + ) { + props[props.dataOverride] = dataItem[extendWith]; + } + } + } + $itemContainer.append( self.renderElement( item.hbs, From a3c93fc1553a2beeffdb6af39f7eb1d573b3636b Mon Sep 17 00:00:00 2001 From: Peter Date: Tue, 30 Apr 2024 13:35:12 +0100 Subject: [PATCH 23/23] SLO : Fix logout link. (#2509) Fixes xibosignage/xibo#3410 --- lib/Middleware/Theme.php | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/lib/Middleware/Theme.php b/lib/Middleware/Theme.php index c3d0546064..b3c3fe99d4 100644 --- a/lib/Middleware/Theme.php +++ b/lib/Middleware/Theme.php @@ -1,6 +1,6 @@ get('configService')->getThemeConfig('view_path') != '') { - $twig->prependPath(Str::replaceFirst('..', PROJECT_ROOT, $container->get('configService')->getThemeConfig('view_path'))); + $twig->prependPath( + Str::replaceFirst( + '..', + PROJECT_ROOT, + $container->get('configService')->getThemeConfig('view_path') + ) + ); } $settings = $container->get('configService')->getSettings(); @@ -99,9 +105,13 @@ public static function setTheme(ContainerInterface $container, Request $request, $settings['TIME_FORMAT_JS'] = DateFormatHelper::convertPhpToMomentFormat($settings['TIME_FORMAT']); $settings['DATE_ONLY_FORMAT'] = DateFormatHelper::extractDateOnlyFormat($settings['DATE_FORMAT']); $settings['DATE_ONLY_FORMAT_JS'] = DateFormatHelper::convertPhpToMomentFormat($settings['DATE_ONLY_FORMAT']); - $settings['DATE_ONLY_FORMAT_JALALI_JS'] = DateFormatHelper::convertMomentToJalaliFormat($settings['DATE_ONLY_FORMAT_JS']); + $settings['DATE_ONLY_FORMAT_JALALI_JS'] = DateFormatHelper::convertMomentToJalaliFormat( + $settings['DATE_ONLY_FORMAT_JS'] + ); $settings['systemDateFormat'] = DateFormatHelper::convertPhpToMomentFormat(DateFormatHelper::getSystemFormat()); - $settings['systemTimeFormat'] = DateFormatHelper::convertPhpToMomentFormat(DateFormatHelper::extractTimeFormat(DateFormatHelper::getSystemFormat())); + $settings['systemTimeFormat'] = DateFormatHelper::convertPhpToMomentFormat( + DateFormatHelper::extractTimeFormat(DateFormatHelper::getSystemFormat()) + ); $routeContext = RouteContext::fromRequest($request); $route = $routeContext->getRoute(); @@ -109,7 +119,14 @@ public static function setTheme(ContainerInterface $container, Request $request, // Resolve the current route name $routeName = ($route == null) ? 'notfound' : $route->getName(); $view['baseUrl'] = $routeParser->urlFor('home'); - $view['logoutUrl'] = $routeParser->urlFor((empty($container->logoutRoute)) ? 'logout' : $container->logoutRoute); + + try { + $logoutRoute = empty($container->get('logoutRoute')) ? 'logout' : $container->get('logoutRoute'); + $view['logoutUrl'] = $routeParser->urlFor($logoutRoute); + } catch (\Exception $e) { + $view['logoutUrl'] = $routeParser->urlFor('logout'); + } + $view['route'] = $routeName; $view['theme'] = $container->get('configService'); $view['settings'] = $settings; @@ -122,7 +139,10 @@ public static function setTheme(ContainerInterface $container, Request $request, $view['translations'] ='{}'; $view['libraryUpload'] = [ 'maxSize' => ByteFormatter::toBytes(Environment::getMaxUploadSize()), - 'maxSizeMessage' => sprintf(__('This form accepts files up to a maximum size of %s'), Environment::getMaxUploadSize()), + 'maxSizeMessage' => sprintf( + __('This form accepts files up to a maximum size of %s'), + Environment::getMaxUploadSize() + ), 'validExt' => implode('|', $container->get('moduleFactory')->getValidExtensions()), 'validImageExt' => implode('|', $container->get('moduleFactory')->getValidExtensions(['type' => 'image'])) ];