diff --git a/openslides/agenda/migrations/0002_duration.py b/openslides/agenda/migrations/0002_duration.py new file mode 100644 index 000000000..8ea380bed --- /dev/null +++ b/openslides/agenda/migrations/0002_duration.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.1 on 2016-09-22 11:08 +from __future__ import unicode_literals + +from django.db import migrations, models + + +def convert_duration(apps, schema_editor): + Item = apps.get_model('agenda', 'item') + for item in Item.objects.all(): + duration = item.duration + item.duration_tmp = None + if is_int(duration): + # assuming that these are minutes + item.duration_tmp = int(duration) + else: + split = duration.split(':') + # assuming format (h)h:(m)m + if len(split) == 2 and is_int(split[0]) and is_int(split[1]): + # duration = hours * 60 + minutes + item.duration_tmp = int(split[0]) * 60 + int(split[1]) + item.save() + + +def is_int(s): + try: + int(s) + except ValueError: + return False + else: + return True + + +class Migration(migrations.Migration): + + dependencies = [ + ('agenda', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='item', + name='duration_tmp', + field=models.IntegerField(blank=True, null=True), + ), + migrations.RunPython(convert_duration), + migrations.RemoveField( + model_name='item', + name='duration', + ), + migrations.RenameField( + model_name='item', + old_name='duration_tmp', + new_name='duration', + ), + ] diff --git a/openslides/agenda/models.py b/openslides/agenda/models.py index 8e1564187..a97d9701a 100644 --- a/openslides/agenda/models.py +++ b/openslides/agenda/models.py @@ -220,7 +220,7 @@ class Item(RESTModelMixin, models.Model): See Item.ITEM_TYPE for more information. """ - duration = models.CharField(null=True, blank=True, max_length=5) + duration = models.IntegerField(null=True, blank=True) """ The intended duration for the topic. """ diff --git a/openslides/agenda/static/js/agenda/site.js b/openslides/agenda/static/js/agenda/site.js index 31be6db39..0c458db0f 100644 --- a/openslides/agenda/static/js/agenda/site.js +++ b/openslides/agenda/static/js/agenda/site.js @@ -112,6 +112,31 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda']) }); $scope.alert = {}; + $scope.sumDurations = function () { + var totalDuration = 0; + $scope.items.forEach(function (item) { + if (item.duration) { + totalDuration += item.duration; + } + }); + return totalDuration; + }; + + $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 mm = ("0" + endDate.getMinutes()).slice(-2); + var dateStr = endDate.getHours() + ':' + mm; + return dateStr; + } else { + return ''; + } + }; + // pagination $scope.currentPage = 1; $scope.itemsPerPage = 100; diff --git a/openslides/agenda/static/templates/agenda/item-list.html b/openslides/agenda/static/templates/agenda/item-list.html index fb6a0469c..e29581c04 100644 --- a/openslides/agenda/static/templates/agenda/item-list.html +++ b/openslides/agenda/static/templates/agenda/item-list.html @@ -134,6 +134,12 @@ Agenda item Duration + + {{ sumDurations() | osMinutesToTime }}h + + (Estimated end: {{ calculateEndTime() }}) + + Done @@ -196,7 +202,7 @@ - {{ item.duration }} + {{ item.duration | osMinutesToTime }} h @@ -227,7 +233,8 @@
- +
diff --git a/openslides/core/static/js/core/base.js b/openslides/core/static/js/core/base.js index df98b96fb..8b6438704 100644 --- a/openslides/core/static/js/core/base.js +++ b/openslides/core/static/js/core/base.js @@ -429,6 +429,27 @@ angular.module('OpenSlidesApp.core', [ } ]) +/* Converts number of minutes into string "h:mm" or "hh:mm" */ +.filter('osMinutesToTime', [ + function () { + return function (totalminutes) { + var time = ''; + if (totalminutes) { + if (totalminutes < 0) { + time = "-"; + totalminutes = -totalminutes; + } + var hh = Math.floor(totalminutes / 60); + var mm = Math.floor(totalminutes % 60); + // Add leading "0" for double digit values + mm = ("0" + mm).slice(-2); + time += hh + ":" + mm; + } + return time; + }; + } +]) + .filter('osFilter', [ function () { return function (array, string, getFilterString) { diff --git a/openslides/core/static/js/core/site.js b/openslides/core/static/js/core/site.js index 173c457e9..d768045b9 100644 --- a/openslides/core/static/js/core/site.js +++ b/openslides/core/static/js/core/site.js @@ -1502,6 +1502,46 @@ angular.module('OpenSlidesApp.core.site', [ } ]) +// format time string for model ("m") and view format ("h:mm" or "hh:mm") +.directive('hourMinFormat', [ + function () { + return { + require: 'ngModel', + link: function(scope, element, attrs, ngModelController) { + ngModelController.$parsers.push(function(data) { + //convert data from view format (hh:mm) to model format (m) + var time = data.split(':'); + if (time.length > 1 && !isNaN(time[0]) && !isNaN(time[1])) { + data = (+time[0]) * 60 + (+time[1]); + if (data < 0) { + data = "-"+data; + } + } + if (data === '') { + data = 0; + } + return data; + }); + + ngModelController.$formatters.push(function(totalminutes) { + //convert data from model format (m) to view format (hh:mm) + var time = ""; + if (totalminutes < 0) { + time = "-"; + totalminutes = -totalminutes; + } + var hh = Math.floor(totalminutes / 60); + var mm = Math.floor(totalminutes % 60); + // Add leading "0" for double digit values + mm = ("0"+mm).slice(-2); + time += hh + ":" + mm; + return time; + }); + } + }; + } +]) + .directive('osFocusMe', [ '$timeout', function ($timeout) {