diff --git a/README.rst b/README.rst index ed09e1219..98e1ae549 100644 --- a/README.rst +++ b/README.rst @@ -209,6 +209,7 @@ OpenSlides uses the following projects or parts of them: * `angular-ui-tree `_, License: MIT * `api-check `_, License: MIT * `bootstrap `_, License: MIT + * `bootstrap-ui-datetime-picker `_, License: MIT * `chosen `_, License: MIT * `font-awesome-bower `_, License: MIT * `jquery `_, License: MIT diff --git a/bower.json b/bower.json index 50b34df4f..3f9bd1470 100644 --- a/bower.json +++ b/bower.json @@ -22,6 +22,7 @@ "angular-ui-tinymce": "~0.0.17", "angular-ui-tree": "~2.22.0", "bootstrap-css-only": "~3.3.6", + "bootstrap-ui-datetime-picker": "~2.4.0", "docxtemplater": "~2.1.5", "font-awesome-bower": "~4.5.0", "jquery.cookie": "~1.4.1", @@ -54,6 +55,7 @@ }, "resolutions": { "angular": ">=1.5 <1.6", - "jquery": ">=3.1 <3.2" + "jquery": ">=3.1 <3.2", + "angular-bootstrap": "~2.1.3" } } diff --git a/openslides/agenda/config_variables.py b/openslides/agenda/config_variables.py index 9525b4c16..55b6a439d 100644 --- a/openslides/agenda/config_variables.py +++ b/openslides/agenda/config_variables.py @@ -1,18 +1,8 @@ -from datetime import datetime - -from django.core.exceptions import ValidationError as DjangoValidationError from django.core.validators import MaxLengthValidator, MinValueValidator from openslides.core.config import ConfigVariable -def validate_start_time(value): - try: - datetime.strptime(value, '%d.%m.%Y %H:%M') - except ValueError: - raise DjangoValidationError('Invalid input.') - - def get_config_variables(): """ Generator which yields all config variables of this app. @@ -41,16 +31,15 @@ def get_config_variables(): group='Agenda', subgroup='General') - # TODO: Use an input type with generic datetime support. yield ConfigVariable( name='agenda_start_event_date_time', - default_value='', + default_value=None, + input_type='datetimepicker', label='Begin of event', help_text='Input format: DD.MM.YYYY HH:MM', weight=220, group='Agenda', - subgroup='General', - validators=(validate_start_time,)) + subgroup='General') # List of speakers diff --git a/openslides/agenda/static/js/agenda/site.js b/openslides/agenda/static/js/agenda/site.js index 5f1dca7d3..d282d7f6f 100644 --- a/openslides/agenda/static/js/agenda/site.js +++ b/openslides/agenda/static/js/agenda/site.js @@ -136,11 +136,10 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda']) $scope.calculateEndTime = function () { var totalDuration = $scope.sumDurations(); - var startTime = $scope.config('agenda_start_event_date_time'); - // This date-time has a fixed structure: DD.MM.YYYY HH:MM - if (startTime) { - var timestamp = Date.parse(startTime) + totalDuration * 60 * 1000; - var endDate = new Date(timestamp); + var startTimestamp = $scope.config('agenda_start_event_date_time'); + if (startTimestamp) { + var endTimestamp = startTimestamp + totalDuration * 60 * 1000; + var endDate = new Date(endTimestamp); var mm = ("0" + endDate.getMinutes()).slice(-2); var dateStr = endDate.getHours() + ':' + mm; return dateStr; diff --git a/openslides/core/config.py b/openslides/core/config.py index 29f06a93d..84ece613a 100644 --- a/openslides/core/config.py +++ b/openslides/core/config.py @@ -11,7 +11,8 @@ INPUT_TYPE_MAPPING = { 'boolean': bool, 'choice': str, 'comments': list, - 'colorpicker': str} + 'colorpicker': str, + 'datetimepicker': int} class ConfigHandler: diff --git a/openslides/core/static/js/core/base.js b/openslides/core/static/js/core/base.js index 0a66870a1..f4d263298 100644 --- a/openslides/core/static/js/core/base.js +++ b/openslides/core/static/js/core/base.js @@ -9,6 +9,7 @@ angular.module('OpenSlidesApp.core', [ 'ngAnimate', 'ngSanitize', // TODO: only use this in functions that need it. 'ui.bootstrap', + 'ui.bootstrap.datetimepicker', 'ui.tree', 'pdf', 'OpenSlidesApp-templates', diff --git a/openslides/core/static/js/core/site.js b/openslides/core/static/js/core/site.js index c6e94708c..d31c0f028 100644 --- a/openslides/core/static/js/core/site.js +++ b/openslides/core/static/js/core/site.js @@ -23,6 +23,44 @@ angular.module('OpenSlidesApp.core.site', [ // Can be used to find out if the projector or the side is used .constant('REALM', 'site') +.factory('DateTimePickerTranslation', [ + 'gettextCatalog', + function (gettextCatalog) { + return { + getButtons: function () { + return { + show: true, + now: { + show: true, + text: gettextCatalog.getString('now') + }, + today: { + show: true, + text: gettextCatalog.getString('today') + }, + clear: { + show: true, + text: gettextCatalog.getString('clear') + }, + date: { + show: true, + text: gettextCatalog.getString('date') + }, + time: { + show: true, + text: gettextCatalog.getString('time') + }, + close: { + show: true, + text: gettextCatalog.getString('close') + } + }; + } + }; + } + +]) + // Provider to register entries for the main menu. .provider('mainMenu', [ function() { @@ -393,8 +431,9 @@ angular.module('OpenSlidesApp.core.site', [ integer: 'number', boolean: 'checkbox', choice: 'choice', - colorpicker: 'colorpicker', comments: 'comments', + colorpicker: 'colorpicker', + datetimepicker: 'datetimepicker', }[type]; } @@ -549,9 +588,11 @@ angular.module('OpenSlidesApp.core.site', [ 'Config', 'configOptions', 'gettextCatalog', - function($scope, Config, configOptions, gettextCatalog) { + 'DateTimePickerTranslation', + function($scope, Config, configOptions, gettextCatalog, DateTimePickerTranslation) { Config.bindAll({}, $scope, 'configs'); $scope.configGroups = configOptions.data.config_groups; + $scope.dateTimePickerTranslatedButtons = DateTimePickerTranslation.getButtons(); // save changed config value $scope.save = function(key, value) { diff --git a/openslides/core/static/templates/config-form-field.html b/openslides/core/static/templates/config-form-field.html index 8d9a27a62..bb5d6f349 100644 --- a/openslides/core/static/templates/config-form-field.html +++ b/openslides/core/static/templates/config-form-field.html @@ -51,6 +51,18 @@ ng-change="save(configOption.key, $parent.value)" type="text"> + + +