Skip to content

Commit

Permalink
4.0.2 fixes (#2066)
Browse files Browse the repository at this point in the history
* Display : Better handle edit form submit with empty default Layout. xibosignage/xibo#3107
* Tags : Make it so entered Tags are registered on blur. xibosignage/xibo#3091
* Menu Boards : Fix various issues with product options and fix product calories validation
* Menu Boards : Product Option Factory - Fix strange typo in previous commit
* Menu Boards : Add currencyCode property to product_options_value element template.
  • Loading branch information
PeterMis committed Sep 8, 2023
1 parent b99835e commit d94ac16
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 33 deletions.
13 changes: 7 additions & 6 deletions lib/Controller/MenuBoardProduct.php
Expand Up @@ -427,13 +427,14 @@ public function add(Request $request, Response $response, $id): Response
$menuBoardProduct->save();

if (!empty(array_filter($productOptions)) && !empty(array_filter($productValues))) {
$productDetails = array_combine($productOptions, $productValues);
$productDetails = array_filter(array_combine($productOptions, $productValues));
$parsedDetails = $this->getSanitizer($productDetails);

foreach ($productDetails as $option => $value) {
$productOption = $this->menuBoardProductOptionFactory->create(
$menuBoardProduct->menuProductId,
$option,
$value
$parsedDetails->getDouble($option)
);
$productOption->save();
}
Expand Down Expand Up @@ -603,7 +604,7 @@ public function edit(Request $request, Response $response, $id): Response
$menuBoardProduct->description = $sanitizedParams->getString('description');
$menuBoardProduct->price = $sanitizedParams->getDouble('price');
$menuBoardProduct->allergyInfo = $sanitizedParams->getString('allergyInfo');
$menuBoardProduct->calories = $sanitizedParams->getString('calories');
$menuBoardProduct->calories = $sanitizedParams->getInt('calories');
$menuBoardProduct->displayOrder = $sanitizedParams->getInt('displayOrder');
$menuBoardProduct->availability = $sanitizedParams->getCheckbox('availability');
$menuBoardProduct->mediaId = $sanitizedParams->getInt('mediaId');
Expand All @@ -612,8 +613,8 @@ public function edit(Request $request, Response $response, $id): Response
$productValues = $sanitizedParams->getArray('productValues', ['default' => []]);

if (!empty(array_filter($productOptions)) && !empty(array_filter($productValues))) {
$productDetails = array_combine($productOptions, $productValues);

$productDetails = array_filter(array_combine($productOptions, $productValues));
$parsedDetails = $this->getSanitizer($productDetails);
if (count($menuBoardProduct->getOptions()) > count($productDetails)) {
$menuBoardProduct->removeOptions();
}
Expand All @@ -622,7 +623,7 @@ public function edit(Request $request, Response $response, $id): Response
$productOption = $this->menuBoardProductOptionFactory->create(
$menuBoardProduct->menuProductId,
$option,
$value
$parsedDetails->getDouble($option)
);
$productOption->save();
}
Expand Down
80 changes: 64 additions & 16 deletions lib/Entity/Display.php
Expand Up @@ -692,30 +692,49 @@ public function notify()
*/
public function validate()
{
if (!v::stringType()->notEmpty()->validate($this->display))
if (!v::stringType()->notEmpty()->validate($this->display)) {
throw new InvalidArgumentException(__('Can not have a display without a name'), 'name');
}

if (!v::stringType()->notEmpty()->validate($this->license))
if (!v::stringType()->notEmpty()->validate($this->license)) {
throw new InvalidArgumentException(__('Can not have a display without a hardware key'), 'license');
}

if ($this->wakeOnLanEnabled == 1 && $this->wakeOnLanTime == '')
throw new InvalidArgumentException(__('Wake on Lan is enabled, but you have not specified a time to wake the display'), 'wakeonlan');

if ($this->wakeOnLanEnabled == 1 && $this->wakeOnLanTime == '') {
throw new InvalidArgumentException(
__('Wake on Lan is enabled, but you have not specified a time to wake the display'),
'wakeonlan'
);
}
// Broadcast Address
if ($this->broadCastAddress != '' && !v::ip()->validate($this->broadCastAddress))
throw new InvalidArgumentException(__('BroadCast Address is not a valid IP Address'), 'broadCastAddress');
if ($this->broadCastAddress != '' && !v::ip()->validate($this->broadCastAddress)) {
throw new InvalidArgumentException(
__('BroadCast Address is not a valid IP Address'),
'broadCastAddress'
);
}

// CIDR
if (!empty($this->cidr) && !v::numeric()->between(0, 32)->validate($this->cidr))
throw new InvalidArgumentException(__('CIDR subnet mask is not a number within the range of 0 to 32.'), 'cidr');
if (!empty($this->cidr) && !v::numeric()->between(0, 32)->validate($this->cidr)) {
throw new InvalidArgumentException(
__('CIDR subnet mask is not a number within the range of 0 to 32.'),
'cidr'
);
}

// secureOn
if ($this->secureOn != '') {
$this->secureOn = strtoupper($this->secureOn);
$this->secureOn = str_replace(":", "-", $this->secureOn);

if ((!preg_match("/([A-F0-9]{2}[-]){5}([0-9A-F]){2}/", $this->secureOn)) || (strlen($this->secureOn) != 17))
throw new InvalidArgumentException(__('Pattern of secureOn-password is not "xx-xx-xx-xx-xx-xx" (x = digit or CAPITAL letter)'), 'secureOn');
$this->secureOn = str_replace(':', '-', $this->secureOn);

if ((!preg_match('/([A-F0-9]{2}[-]){5}([0-9A-F]){2}/', $this->secureOn))
|| (strlen($this->secureOn) != 17)
) {
throw new InvalidArgumentException(
__('Pattern of secureOn-password is not "xx-xx-xx-xx-xx-xx" (x = digit or CAPITAL letter)'),
'secureOn'
);
}
}

// Mac Address Changes
Expand All @@ -726,14 +745,43 @@ public function validate()
}

// Lat/Long
if (!empty($this->longitude) && !v::longitude()->validate($this->longitude))
if (!empty($this->longitude) && !v::longitude()->validate($this->longitude)) {
throw new InvalidArgumentException(__('The longitude entered is not valid.'), 'longitude');
}

if (!empty($this->latitude) && !v::latitude()->validate($this->latitude))
if (!empty($this->latitude) && !v::latitude()->validate($this->latitude)) {
throw new InvalidArgumentException(__('The latitude entered is not valid.'), 'latitude');
}

if ($this->bandwidthLimit !== null && !v::intType()->min(0)->validate($this->bandwidthLimit)) {
throw new InvalidArgumentException(__('Bandwidth limit must be a whole number greater than 0.'), 'bandwidthLimit');
throw new InvalidArgumentException(
__('Bandwidth limit must be a whole number greater than 0.'),
'bandwidthLimit'
);
}

// do we have default Layout set?
if (empty($this->defaultLayoutId)) {
// do we have global default Layout ?
$globalDefaultLayoutId = $this->config->getSetting('DEFAULT_LAYOUT');
if (!empty($globalDefaultLayoutId)) {
$this->getLog()->debug(
'No default Layout set on Display ID '
. $this->displayId
. ' falling back to global default Layout.'
);
$this->defaultLayoutId = $globalDefaultLayoutId;
$this->notify();
} else {
// we have no Default Layout and no global Default Layout
$this->getLog()->error(
'No global default Layout set and no default Layout set for Display ID ' . $this->displayId
);
throw new InvalidArgumentException(
__('Please set a Default Layout directly on this Display or in CMS Administrator Settings'),
'defaultLayoutId'
);
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions lib/Entity/MenuBoardProduct.php
Expand Up @@ -150,6 +150,13 @@ public function validate(): void
if (!v::stringType()->notEmpty()->validate($this->name)) {
throw new InvalidArgumentException(__('Name cannot be empty'), 'name');
}

if (!empty($this->calories) && !v::intType()->min(0)->max(32767)->validate($this->calories)) {
throw new InvalidArgumentException(
__('Calories must be a whole number between 0 and 32767'),
'calories'
);
}
}

/**
Expand Down
12 changes: 8 additions & 4 deletions lib/Entity/MenuBoardProductOption.php
@@ -1,8 +1,8 @@
<?php
/*
* Copyright (c) 2022 Xibo Signage Ltd
* Copyright (C) 2023 Xibo Signage Ltd
*
* Xibo - Digital Signage - http://www.xibo.org.uk
* Xibo - Digital Signage - https://xibosignage.com
*
* This file is part of Xibo.
*
Expand Down Expand Up @@ -77,11 +77,15 @@ public function __toString()
*/
public function validate()
{
if (!v::stringType()->notEmpty()->validate($this->option) && v::stringType()->notEmpty()->validate($this->value)) {
if (!v::stringType()->notEmpty()->validate($this->option)
&& v::floatType()->notEmpty()->validate($this->value)
) {
throw new InvalidArgumentException(__('Each value needs a corresponding option'), 'option');
}

if (!v::stringType()->notEmpty()->validate($this->value) && v::stringType()->notEmpty()->validate($this->option)) {
if (!v::floatType()->notEmpty()->validate($this->value)
&& v::stringType()->notEmpty()->validate($this->option)
) {
throw new InvalidArgumentException(__('Each option needs a corresponding value'), 'value');
}
}
Expand Down
6 changes: 3 additions & 3 deletions lib/Factory/MenuBoardProductOptionFactory.php
@@ -1,8 +1,8 @@
<?php
/*
* Copyright (c) 2022 Xibo Signage Ltd
* Copyright (C) 2023 Xibo Signage Ltd
*
* Xibo - Digital Signage - http://www.xibo.org.uk
* Xibo - Digital Signage - https://xibosignage.com
*
* This file is part of Xibo.
*
Expand Down Expand Up @@ -78,7 +78,7 @@ public function query($sortOrder = null, $filterBy = [])
foreach ($this->getStore()->select($sql, [
'menuProductId' => $sanitizedFilter->getInt('menuProductId')
]) as $row) {
$entries[] = $this->createEmpty()->hydrate($row);
$entries[] = $this->createEmpty()->hydrate($row, ['doubleProperties' => ['value']]);
}

return $entries;
Expand Down
13 changes: 13 additions & 0 deletions modules/templates/product-elements.xml
Expand Up @@ -255,6 +255,11 @@ if (
<title>Font Color</title>
<default>%THEME_COLOR%</default>
</property>
<property id="currencyCode" type="text">
<title>Currency Code</title>
<helpText>The 3 digit currency code to apply to the price, e.g. USD/GBP/EUR</helpText>
<default></default>
</property>
<property id="prefix" type="text">
<title>Prefix</title>
<default></default>
Expand Down Expand Up @@ -321,6 +326,14 @@ if (
var option = properties.data.productOptions[optionSlot];
var value = option.value;
var options = {};
if (properties.currencyCode && properties.currencyCode !== '') {
options.style = 'currency';
options.currency = properties.currencyCode;
}
value = new Intl.NumberFormat(undefined, options).format(value);
if (properties.prefix && properties.prefix !== '') {
value = properties.prefix + '' + value;
}
Expand Down
9 changes: 9 additions & 0 deletions ui/src/core/xibo-cms.js
Expand Up @@ -406,6 +406,15 @@ function XiboInitialise(scope, options) {
// Normal tags input
$(self).tagsinput();
}

// When tagsinput loses focus, add the tag,
// do not rely solely on comma or selection from suggestions
$('.bootstrap-tagsinput input').blur(function() {
if ($(this).val() !== '') {
$(self).tagsinput('add', $(this).val());
$(this).val('');
}
});
});

// Initialize tags input for properties panel with connectorProperties field
Expand Down
2 changes: 1 addition & 1 deletion ui/src/templates/form-helpers-menuboard-product.hbs
Expand Up @@ -4,7 +4,7 @@
</div>

<div class="form-group col-xl-5">
<input class="form-control" name="productValues[]" type="text" value="{{ optionValue }}" placeholder="Option Value">
<input class="form-control" name="productValues[]" type="number" step="0.01" value="{{ optionValue }}" placeholder="Option Value">
</div>

<div class="form-group col-xl-2 px-2 px-xl-0">
Expand Down
2 changes: 1 addition & 1 deletion views/display-form-edit.twig
Expand Up @@ -120,7 +120,7 @@
{{ forms.dropdown("licensed", "single", title, display.licensed, options, "licensedid", "licensed", helpText) }}

{% set title %}{% trans "Default Layout" %}{% endset %}
{% set helpText %}{% trans "The Default Layout to display where there is no other content scheduled. If left empty with no other content scheduled the splash screen will be displayed" %}{% endset %}
{% set helpText %}{% trans "Set the Default Layout to use when no other content is scheduled to this Display. This will override the global Default Layout as set in CMS Administrator Settings. If left blank a global Default Layout will be automatically set for this Display." %}{% endset %}
{% set attributes = [
{ name: "data-search-url", value: url_for("layout.search") },
{ name: "data-search-term", value: "layout" },
Expand Down
2 changes: 1 addition & 1 deletion views/menuboard-product-form-add.twig
Expand Up @@ -65,7 +65,7 @@

{% set title %}{% trans "Calories" %}{% endset %}
{% set helpText %}{% trans "How many calories are in this product?" %}{% endset %}
{{ forms.input("calories", title, "", helpText) }}
{{ forms.number("calories", title, "", helpText) }}

{% set title %}{% trans "Display Order" %}{% endset %}
{% set helpText %}{% trans "Set a display order for this item to appear, leave empty to add to the end." %}{% endset %}
Expand Down
2 changes: 1 addition & 1 deletion views/menuboard-product-form-edit.twig
Expand Up @@ -65,7 +65,7 @@

{% set title %}{% trans "Calories" %}{% endset %}
{% set helpText %}{% trans "How many calories are in this product?" %}{% endset %}
{{ forms.input("calories", title, menuBoardProduct.calories, helpText) }}
{{ forms.number("calories", title, menuBoardProduct.calories, helpText) }}

{% set title %}{% trans "Display Order" %}{% endset %}
{% set helpText %}{% trans "Set a display order for this item to appear" %}{% endset %}
Expand Down

0 comments on commit d94ac16

Please sign in to comment.