diff --git a/apps/workflowengine/appinfo/routes.php b/apps/workflowengine/appinfo/routes.php index b8c9ae1c23..5ae74bcafc 100644 --- a/apps/workflowengine/appinfo/routes.php +++ b/apps/workflowengine/appinfo/routes.php @@ -25,5 +25,6 @@ return [ ['name' => 'flowOperations#addOperation', 'url' => '/operations', 'verb' => 'POST'], ['name' => 'flowOperations#updateOperation', 'url' => '/operations/{id}', 'verb' => 'PUT'], ['name' => 'flowOperations#deleteOperation', 'url' => '/operations/{id}', 'verb' => 'DELETE'], + ['name' => 'requestTime#getTimezones', 'url' => '/timezones', 'verb' => 'GET'], ] ]; diff --git a/apps/workflowengine/js/admin.js b/apps/workflowengine/js/admin.js index ec921f8c22..447237c560 100644 --- a/apps/workflowengine/js/admin.js +++ b/apps/workflowengine/js/admin.js @@ -308,7 +308,6 @@ }, 7000, this.$el.find('.msg.success')); this.message = ''; } - } }); diff --git a/apps/workflowengine/js/requesttimeplugin.js b/apps/workflowengine/js/requesttimeplugin.js index 96cb8a40f7..111b2bb743 100644 --- a/apps/workflowengine/js/requesttimeplugin.js +++ b/apps/workflowengine/js/requesttimeplugin.js @@ -44,10 +44,11 @@ return; } - var startTime = '16:00', + var startTime = '09:00', endTime = '18:00', - timezone = 'Europe/London', + timezone = jstz.determine().name(), $element = $(element); + if (_.isString(check['value']) && check['value'] !== '') { var value = JSON.parse(check['value']), splittedStart = value[0].split(' ', 2), @@ -57,6 +58,7 @@ endTime = splittedEnd[0]; timezone = splittedStart[1]; } + var valueJSON = JSON.stringify([startTime + ' ' + timezone, endTime + ' ' + timezone]); if (check['value'] !== valueJSON) { check['value'] = valueJSON; @@ -68,28 +70,78 @@ $('') .attr('type', 'text') .attr('placeholder', t('workflowengine', 'Start')) + .attr('title', t('workflowengine', 'Example: {placeholder}', {placeholder: '16:00'})) + .addClass('has-tooltip') + .tooltip({ + placement: 'bottom' + }) .addClass('start') .val(startTime) .insertBefore($element); $('') .attr('type', 'text') .attr('placeholder', t('workflowengine', 'End')) + .attr('title', t('workflowengine', 'Example: {placeholder}', {placeholder: '16:00'})) + .addClass('has-tooltip') + .tooltip({ + placement: 'bottom' + }) .addClass('end') .val(endTime) .insertBefore($element); - var timezoneSelect = $('') + .attr('type', 'hidden') + .css('width', '250px') + .insertBefore($element) + .val(timezone); - if (timezoneName === timezone) { - timezoneElement.attr('selected', 'selected'); + timezoneInput.select2({ + allowClear: false, + multiple: false, + placeholder: t('workflowengine', 'Select timezone…'), + ajax: { + url: OC.generateUrl('apps/workflowengine/timezones'), + dataType: 'json', + quietMillis: 100, + data: function (term) { + if (term === '') { + // Default search in the same continent... + term = jstz.determine().name().split('/'); + term = term[0]; + } + return { + search: term + }; + }, + results: function (response) { + var results = []; + $.each(response, function(timezone) { + results.push({ id: timezone }); + }); + + return { + results: results, + more: false + }; + } + }, + initSelection: function (element, callback) { + callback(element.val()); + }, + formatResult: function (element) { + return '' + element.id + ''; + }, + formatSelection: function (element) { + if (!_.isUndefined(element.id)) { + element = element.id; + } + return '' + element + ''; } - - timezoneSelect.append(timezoneElement); }); - timezoneSelect.insertBefore($element); + + // Has to be added after select2 for `event.target.classList` + timezoneInput.addClass('timezone'); $element.parent() .on('change', '.start', _.bind(this.update, this)) @@ -136,6 +188,7 @@ } this._$element.val(JSON.stringify(data)); + this._$element.trigger('change'); } }; })(); diff --git a/apps/workflowengine/lib/AppInfo/Application.php b/apps/workflowengine/lib/AppInfo/Application.php index 7adc4f6864..b5e769d01d 100644 --- a/apps/workflowengine/lib/AppInfo/Application.php +++ b/apps/workflowengine/lib/AppInfo/Application.php @@ -30,6 +30,7 @@ class Application extends \OCP\AppFramework\App { parent::__construct('workflowengine'); $this->getContainer()->registerAlias('FlowOperationsController', 'OCA\WorkflowEngine\Controller\FlowOperations'); + $this->getContainer()->registerAlias('RequestTimeController', 'OCA\WorkflowEngine\Controller\RequestTime'); } /** @@ -51,6 +52,8 @@ class Application extends \OCP\AppFramework\App { 'systemtags/systemtagscollection', ]); + vendor_script('jsTimezoneDetect/jstz'); + script('workflowengine', [ 'admin', diff --git a/apps/workflowengine/lib/Check/RequestTime.php b/apps/workflowengine/lib/Check/RequestTime.php index 4457f9d038..a114819d45 100644 --- a/apps/workflowengine/lib/Check/RequestTime.php +++ b/apps/workflowengine/lib/Check/RequestTime.php @@ -29,7 +29,7 @@ use OCP\WorkflowEngine\ICheck; class RequestTime implements ICheck { const REGEX_TIME = '([0-1][0-9]|2[0-3]):([0-5][0-9])'; - const REGEX_TIMEZONE = '([a-zA-Z]+(?:\\\\\\/[a-zA-Z\-\_]+)+)'; + const REGEX_TIMEZONE = '([a-zA-Z]+(?:\\/[a-zA-Z\-\_]+)+)'; /** @var bool[] */ protected $cachedResults; @@ -110,16 +110,15 @@ class RequestTime implements ICheck { throw new \UnexpectedValueException('Invalid time limits', 2); } - try { - new \DateTimeZone(stripslashes($matches[3])); - } catch(\Exception $e) { - throw new \UnexpectedValueException('Invalid timezone1', 3); + $values = json_decode($value, true); + $time1 = \DateTime::createFromFormat('H:i e', $values[0]); + if ($time1 === false) { + throw new \UnexpectedValueException('Invalid start time given', 3); } - try { - new \DateTimeZone(stripslashes($matches[6])); - } catch(\Exception $e) { - throw new \UnexpectedValueException('Invalid timezone2', 3); + $time2 = \DateTime::createFromFormat('H:i e', $values[1]); + if ($time2 === false) { + throw new \UnexpectedValueException('Invalid end time given', 3); } } } diff --git a/apps/workflowengine/lib/Controller/RequestTime.php b/apps/workflowengine/lib/Controller/RequestTime.php new file mode 100644 index 0000000000..e596ee32a9 --- /dev/null +++ b/apps/workflowengine/lib/Controller/RequestTime.php @@ -0,0 +1,53 @@ + + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\WorkflowEngine\Controller; + +use OCP\AppFramework\Controller; +use OCP\AppFramework\Http\JSONResponse; + +class RequestTime extends Controller { + + /** + * @NoCSRFRequired + * @NoAdminRequired + * + * @param string $search + * @return JSONResponse + */ + public function getTimezones($search = '') { + $timezones = \DateTimeZone::listIdentifiers(); + + if ($search !== '') { + $timezones = array_filter($timezones, function ($timezone) use ($search) { + return strpos(strtolower($timezone), strtolower($search)) !== false; + }); + } + + $timezones = array_slice($timezones, 0, 10); + + $response = []; + foreach ($timezones as $timezone) { + $response[$timezone] = $timezone; + } + return new JSONResponse($response); + } +}