Merge pull request #2800 from FinnStutzenstein/Issue2748

Consistent time handling and generic time converter code
This commit is contained in:
Norman Jäckel 2016-12-21 11:52:47 +01:00 committed by GitHub
commit bfa0b4b3fe
5 changed files with 116 additions and 124 deletions

View File

@ -5,16 +5,20 @@
angular.module('OpenSlidesApp.agenda.csv', [])
.factory('AgendaCsvExport', [
function () {
'HumanTimeConverter',
function (HumanTimeConverter) {
return function (element, agenda) {
var csvRows = [
['title', 'text', 'duration', 'comment', 'is_hidden'],
];
_.forEach(agenda, function (item) {
var row = [];
var duration = item.duration ? HumanTimeConverter.secondsToHumanTime(item.duration*60,
{ seconds: 'disabled',
hours: 'enabled' }) : '';
row.push('"' + (item.title || '') + '"');
row.push('"' + (item.text || '') + '"');
row.push('"' + (item.duration || '') + '"');
row.push('"' + duration + '"');
row.push('"' + (item.comment || '') + '"');
row.push('"' + (item.is_hidden ? '1' : '') + '"');
csvRows.push(row);

View File

@ -692,30 +692,6 @@ angular.module('OpenSlidesApp.agenda.site', [
}
])
.factory('AgendaCsvExport', [
function () {
return function (element, agenda) {
var csvRows = [
['title', 'text', 'duration', 'comment', 'is_hidden'],
];
_.forEach(agenda, function (item) {
var row = [];
row.push('"' + (item.title || '') + '"');
row.push('"' + (item.text || '') + '"');
row.push('"' + (item.duration || '') + '"');
row.push('"' + (item.comment || '') + '"');
row.push('"' + (item.is_hidden ? '1' : '') + '"');
csvRows.push(row);
});
var csvString = csvRows.join("%0A");
element.href = 'data:text/csv;charset=utf-8,' + csvString;
element.download = 'agenda-export.csv';
element.target = '_blank';
};
}
])
//mark all agenda config strings for translation with Javascript
.config([
'gettext',

View File

@ -852,48 +852,105 @@ angular.module('OpenSlidesApp.core', [
}
])
/* Two functions to convert between time duration in seconds <-> human readable time span.
* E.g. 90 sec <-> 1:30 (min), 3661 sec <-> 1:01:01 (h)
*
* secondsToHumanTime: Expects seconds and give [h*:]mm[:ss]. The minutes part is always given, the hours
* and minutes could be controlled. The default are forced seconds and hours just if it is not 0.
* - seconds ('enabled', 'auto', 'disabled'): Whether to show seconds (Default 'enabled')
* - hours ('enabled', 'auto', 'disabled'): Whether to show hours (Default 'auto')
*
* humanTimeToSeconds: Expects [h*:]m*[:s*] with each part could have a variable length. The parsed time is
* in seconds. Minutes have to be given and hours and seconds are optional. One have to set 'seconds' or
* 'hours' to true toparse these.
*
* params could be an object with the given settings, e.g. {ignoreHours: true}
*/
.factory('HumanTimeConverter', [
function () {
return {
secondsToHumanTime: function (seconds, params) {
if (!params) {
params = {seconds: 'enabled', hours: 'auto'};
}
if (!params.seconds) {
params.seconds = 'enabled';
}
if (!params.hours) {
params.hours = 'auto';
}
var time;
// floor returns the largest integer of the absolut value of seconds
var total = Math.floor(Math.abs(seconds));
var h = Math.floor(total / 3600);
var m = Math.floor(total % 3600 / 60);
var s = Math.floor(total % 60);
// Add leading "0" for double digit values
time = ('0'+m).slice(-2); //minutes
if ((params.seconds == 'auto' && s > 0) || params.seconds == 'enabled') {
s = ('0'+s).slice(-2);
time = time + ':' + s;
}
if ((params.hours == 'auto' && h > 0) || params.hours == 'enabled') {
time = h + ':' + time;
}
if (seconds < 0) {
time = '-'+time;
}
return time;
},
humanTimeToSeconds: function (data, params) {
if (!params) {
params = {seconds: false, hours: false};
}
var minLength = 1;
if (params.seconds) {
minLength++;
}
if (params.hours){
minLength++;
}
var negative = data.charAt(0) == '-';
var time = data.split(':');
data = 0;
if (time.length >= minLength) {
for (var i = 0; i < minLength; i++) {
data = data*60 + (+time[i]);
}
if (!params.seconds) { // the last field was minutes (e.g. h:mm)
data *= 60;
}
if (negative) {
data = -data;
}
}
return data;
},
};
}
])
/* Converts number of seconds into string "h:mm:ss" or "mm:ss" */
.filter('osSecondsToTime', [
function () {
return function (totalseconds) {
var time;
// floor returns the largest integer of the absolut value of totalseconds
var total = Math.floor(Math.abs(totalseconds));
var h = Math.floor(total / 3600);
var mm = Math.floor(total % 3600 / 60);
var ss = Math.floor(total % 60);
var zero = "0";
// Add leading "0" for double digit values
mm = (zero+mm).slice(-2);
ss = (zero+ss).slice(-2);
if (h == "0")
time = mm + ':' + ss;
else
time = h + ":" + mm + ":" + ss;
if (totalseconds < 0)
time = "-"+time;
return time;
'HumanTimeConverter',
function (HumanTimeConverter) {
return function (seconds) {
return HumanTimeConverter.secondsToHumanTime(seconds);
};
}
])
/* 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;
'HumanTimeConverter',
function (HumanTimeConverter) {
return function (minutes) {
return HumanTimeConverter.secondsToHumanTime(minutes*60,
{ seconds: 'disabled',
hours: 'enabled' }
);
};
}
])

View File

@ -1338,40 +1338,19 @@ angular.module('OpenSlidesApp.core.site', [
// format time string for model ("s") and view format ("h:mm:ss" or "mm:ss")
.directive('minSecFormat', [
function () {
'HumanTimeConverter',
function (HumanTimeConverter) {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModelController) {
ngModelController.$parsers.push(function(data) {
//convert data from view format (mm:ss) to model format (s)
var time = data.split(':');
if (time.length > 1) {
data = (+time[0]) * 60 + (+time[1]);
if (data < 0) {
data = "-"+data;
}
}
return data;
return HumanTimeConverter.humanTimeToSeconds(data, {seconds: true});
});
ngModelController.$formatters.push(function(data) {
//convert data from model format (s) to view format (mm:ss)
var time;
// floor returns the largest integer of the absolut value of totalseconds
var total = Math.floor(Math.abs(data));
var mm = Math.floor(total / 60);
var ss = Math.floor(total % 60);
var zero = "0";
// Add leading "0" for double digit values
if (mm.length < 2) {
mm = (zero+mm).slice(-2);
}
ss = (zero+ss).slice(-2);
time = mm + ':' + ss;
if (data < 0) {
time = "-"+time;
}
return time;
return HumanTimeConverter.secondsToHumanTime(data);
});
}
};
@ -1380,38 +1359,22 @@ angular.module('OpenSlidesApp.core.site', [
// format time string for model ("m") and view format ("h:mm" or "hh:mm")
.directive('hourMinFormat', [
function () {
'HumanTimeConverter',
function (HumanTimeConverter) {
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;
return HumanTimeConverter.humanTimeToSeconds(data, {hours: true})/60;
});
ngModelController.$formatters.push(function(totalminutes) {
ngModelController.$formatters.push(function(data) {
//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;
return HumanTimeConverter.secondsToHumanTime(data*60,
{ seconds: 'disabled',
hours: 'enabled' }
);
});
}
};

View File

@ -271,7 +271,8 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics'])
'gettext',
'Agenda',
'Topic',
function($scope, gettext, Agenda, Topic) {
'HumanTimeConverter',
function($scope, gettext, Agenda, Topic, HumanTimeConverter) {
// Big TODO: Change wording from "item" to "topic".
// import from textarea
$scope.importByLine = function () {
@ -342,22 +343,13 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics'])
}
// duration
if (item.duration) {
var time = item.duration.replace(quotionRe, '$1').split(':'),
len = time.length,
data = '';
if (len > 1 && !isNaN(time[len-2]) && !isNaN(time[len-1])) { // minutes and hours
// e.g.: [sl:1000:]10:34 (the [] will not be parsed)
data = (+time[len-2]) * 60 + (+time[len-1]);
} else if (len == 1) { // just interpret minutes
data = (+time[0]);
} else {
data = null;
}
var time = item.duration.replace(quotionRe, '$1');
time = HumanTimeConverter.humanTimeToSeconds(time, {hours: true})/60;
if (data < 0 || data === '') {
data = null; // no negative duration
if (time <= 0) { // null instead of 0 or negative duration
time = null;
}
item.duration = data;
item.duration = time;
} else {
item.duration = null;
}