Merge pull request #2412 from FinnStutzenstein/Issue2109
Agenda duration and estimated time (closes #2109)
This commit is contained in:
commit
2495d7dd7f
56
openslides/agenda/migrations/0002_duration.py
Normal file
56
openslides/agenda/migrations/0002_duration.py
Normal file
@ -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',
|
||||
),
|
||||
]
|
@ -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.
|
||||
"""
|
||||
|
@ -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;
|
||||
|
@ -134,6 +134,12 @@
|
||||
<translate>Agenda item</translate>
|
||||
<th os-perms="agenda.can_see_hidden_items" class="optional">
|
||||
<translate>Duration</translate>
|
||||
<span ng-if="sumDurations() > 0">
|
||||
{{ sumDurations() | osMinutesToTime }}h
|
||||
<span ng-if="config('agenda_start_event_date_time')">
|
||||
(<translate>Estimated end:</translate> {{ calculateEndTime() }})
|
||||
</span>
|
||||
</span>
|
||||
<th class="minimum optional">
|
||||
<translate>Done</translate>
|
||||
<tbody>
|
||||
@ -196,7 +202,7 @@
|
||||
</span>
|
||||
</div>
|
||||
<td ng-show="!item.quickEdit" os-perms="agenda.can_see_hidden_items" class="optional">
|
||||
{{ item.duration }}
|
||||
{{ item.duration | osMinutesToTime }}
|
||||
<span ng-if="item.duration" translate-comment="'h' means time in hours" translate>h</span>
|
||||
<td ng-if="!item.quickEdit" class="optional">
|
||||
<span os-perms="!agenda.can_manage">
|
||||
@ -227,7 +233,8 @@
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<label for="inputDuration" translate>Duration</label>
|
||||
<input type="text" ng-model="item.duration" class="form-control input-sm" id="inputDuration">
|
||||
<input type="text" ng-model="item.duration" placeholder="hh:mm" hour-min-format
|
||||
class="form-control input-sm" id="inputDuration">
|
||||
</div>
|
||||
</div>
|
||||
<div class="spacer">
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user