Agenda duration and estimated time (closes #2109)
This commit is contained in:
parent
8770395274
commit
970f42cacb
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)
|
||||||
|
return True
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
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.
|
The intended duration for the topic.
|
||||||
"""
|
"""
|
||||||
|
@ -112,6 +112,31 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda'])
|
|||||||
});
|
});
|
||||||
$scope.alert = {};
|
$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
|
// pagination
|
||||||
$scope.currentPage = 1;
|
$scope.currentPage = 1;
|
||||||
$scope.itemsPerPage = 100;
|
$scope.itemsPerPage = 100;
|
||||||
|
@ -134,6 +134,12 @@
|
|||||||
<translate>Agenda item</translate>
|
<translate>Agenda item</translate>
|
||||||
<th os-perms="agenda.can_see_hidden_items" class="optional">
|
<th os-perms="agenda.can_see_hidden_items" class="optional">
|
||||||
<translate>Duration</translate>
|
<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">
|
<th class="minimum optional">
|
||||||
<translate>Done</translate>
|
<translate>Done</translate>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -196,7 +202,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<td ng-show="!item.quickEdit" os-perms="agenda.can_see_hidden_items" class="optional">
|
<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>
|
<span ng-if="item.duration" translate-comment="'h' means time in hours" translate>h</span>
|
||||||
<td ng-if="!item.quickEdit" class="optional">
|
<td ng-if="!item.quickEdit" class="optional">
|
||||||
<span os-perms="!agenda.can_manage">
|
<span os-perms="!agenda.can_manage">
|
||||||
@ -227,7 +233,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-xs-6">
|
<div class="col-xs-6">
|
||||||
<label for="inputDuration" translate>Duration</label>
|
<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>
|
</div>
|
||||||
<div class="spacer">
|
<div class="spacer">
|
||||||
|
@ -429,6 +429,29 @@ angular.module('OpenSlidesApp.core', [
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
/* Converts number of minutes into string "h:mm" or "hh:mm" */
|
||||||
|
.filter('osMinutesToTime', [
|
||||||
|
function () {
|
||||||
|
return function (totalminutes) {
|
||||||
|
if (!totalminutes) {
|
||||||
|
return '';
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
.filter('osFilter', [
|
.filter('osFilter', [
|
||||||
function () {
|
function () {
|
||||||
return function (array, string, getFilterString) {
|
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', [
|
.directive('osFocusMe', [
|
||||||
'$timeout',
|
'$timeout',
|
||||||
function ($timeout) {
|
function ($timeout) {
|
||||||
|
Loading…
Reference in New Issue
Block a user