Merge pull request #2800 from FinnStutzenstein/Issue2748
Consistent time handling and generic time converter code
This commit is contained in:
commit
bfa0b4b3fe
@ -5,16 +5,20 @@
|
|||||||
angular.module('OpenSlidesApp.agenda.csv', [])
|
angular.module('OpenSlidesApp.agenda.csv', [])
|
||||||
|
|
||||||
.factory('AgendaCsvExport', [
|
.factory('AgendaCsvExport', [
|
||||||
function () {
|
'HumanTimeConverter',
|
||||||
|
function (HumanTimeConverter) {
|
||||||
return function (element, agenda) {
|
return function (element, agenda) {
|
||||||
var csvRows = [
|
var csvRows = [
|
||||||
['title', 'text', 'duration', 'comment', 'is_hidden'],
|
['title', 'text', 'duration', 'comment', 'is_hidden'],
|
||||||
];
|
];
|
||||||
_.forEach(agenda, function (item) {
|
_.forEach(agenda, function (item) {
|
||||||
var row = [];
|
var row = [];
|
||||||
|
var duration = item.duration ? HumanTimeConverter.secondsToHumanTime(item.duration*60,
|
||||||
|
{ seconds: 'disabled',
|
||||||
|
hours: 'enabled' }) : '';
|
||||||
row.push('"' + (item.title || '') + '"');
|
row.push('"' + (item.title || '') + '"');
|
||||||
row.push('"' + (item.text || '') + '"');
|
row.push('"' + (item.text || '') + '"');
|
||||||
row.push('"' + (item.duration || '') + '"');
|
row.push('"' + duration + '"');
|
||||||
row.push('"' + (item.comment || '') + '"');
|
row.push('"' + (item.comment || '') + '"');
|
||||||
row.push('"' + (item.is_hidden ? '1' : '') + '"');
|
row.push('"' + (item.is_hidden ? '1' : '') + '"');
|
||||||
csvRows.push(row);
|
csvRows.push(row);
|
||||||
|
@ -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
|
//mark all agenda config strings for translation with Javascript
|
||||||
.config([
|
.config([
|
||||||
'gettext',
|
'gettext',
|
||||||
|
@ -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" */
|
/* Converts number of seconds into string "h:mm:ss" or "mm:ss" */
|
||||||
.filter('osSecondsToTime', [
|
.filter('osSecondsToTime', [
|
||||||
function () {
|
'HumanTimeConverter',
|
||||||
return function (totalseconds) {
|
function (HumanTimeConverter) {
|
||||||
var time;
|
return function (seconds) {
|
||||||
// floor returns the largest integer of the absolut value of totalseconds
|
return HumanTimeConverter.secondsToHumanTime(seconds);
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
/* Converts number of minutes into string "h:mm" or "hh:mm" */
|
/* Converts number of minutes into string "h:mm" or "hh:mm" */
|
||||||
.filter('osMinutesToTime', [
|
.filter('osMinutesToTime', [
|
||||||
function () {
|
'HumanTimeConverter',
|
||||||
return function (totalminutes) {
|
function (HumanTimeConverter) {
|
||||||
var time = '';
|
return function (minutes) {
|
||||||
if (totalminutes) {
|
return HumanTimeConverter.secondsToHumanTime(minutes*60,
|
||||||
if (totalminutes < 0) {
|
{ seconds: 'disabled',
|
||||||
time = "-";
|
hours: 'enabled' }
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
@ -1338,40 +1338,19 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
|
|
||||||
// format time string for model ("s") and view format ("h:mm:ss" or "mm:ss")
|
// format time string for model ("s") and view format ("h:mm:ss" or "mm:ss")
|
||||||
.directive('minSecFormat', [
|
.directive('minSecFormat', [
|
||||||
function () {
|
'HumanTimeConverter',
|
||||||
|
function (HumanTimeConverter) {
|
||||||
return {
|
return {
|
||||||
require: 'ngModel',
|
require: 'ngModel',
|
||||||
link: function(scope, element, attrs, ngModelController) {
|
link: function(scope, element, attrs, ngModelController) {
|
||||||
ngModelController.$parsers.push(function(data) {
|
ngModelController.$parsers.push(function(data) {
|
||||||
//convert data from view format (mm:ss) to model format (s)
|
//convert data from view format (mm:ss) to model format (s)
|
||||||
var time = data.split(':');
|
return HumanTimeConverter.humanTimeToSeconds(data, {seconds: true});
|
||||||
if (time.length > 1) {
|
|
||||||
data = (+time[0]) * 60 + (+time[1]);
|
|
||||||
if (data < 0) {
|
|
||||||
data = "-"+data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ngModelController.$formatters.push(function(data) {
|
ngModelController.$formatters.push(function(data) {
|
||||||
//convert data from model format (s) to view format (mm:ss)
|
//convert data from model format (s) to view format (mm:ss)
|
||||||
var time;
|
return HumanTimeConverter.secondsToHumanTime(data);
|
||||||
// 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;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1380,38 +1359,22 @@ angular.module('OpenSlidesApp.core.site', [
|
|||||||
|
|
||||||
// format time string for model ("m") and view format ("h:mm" or "hh:mm")
|
// format time string for model ("m") and view format ("h:mm" or "hh:mm")
|
||||||
.directive('hourMinFormat', [
|
.directive('hourMinFormat', [
|
||||||
function () {
|
'HumanTimeConverter',
|
||||||
|
function (HumanTimeConverter) {
|
||||||
return {
|
return {
|
||||||
require: 'ngModel',
|
require: 'ngModel',
|
||||||
link: function(scope, element, attrs, ngModelController) {
|
link: function(scope, element, attrs, ngModelController) {
|
||||||
ngModelController.$parsers.push(function(data) {
|
ngModelController.$parsers.push(function(data) {
|
||||||
//convert data from view format (hh:mm) to model format (m)
|
//convert data from view format (hh:mm) to model format (m)
|
||||||
var time = data.split(':');
|
return HumanTimeConverter.humanTimeToSeconds(data, {hours: true})/60;
|
||||||
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) {
|
ngModelController.$formatters.push(function(data) {
|
||||||
//convert data from model format (m) to view format (hh:mm)
|
//convert data from model format (m) to view format (hh:mm)
|
||||||
var time = "";
|
return HumanTimeConverter.secondsToHumanTime(data*60,
|
||||||
if (totalminutes < 0) {
|
{ seconds: 'disabled',
|
||||||
time = "-";
|
hours: 'enabled' }
|
||||||
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;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -271,7 +271,8 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics'])
|
|||||||
'gettext',
|
'gettext',
|
||||||
'Agenda',
|
'Agenda',
|
||||||
'Topic',
|
'Topic',
|
||||||
function($scope, gettext, Agenda, Topic) {
|
'HumanTimeConverter',
|
||||||
|
function($scope, gettext, Agenda, Topic, HumanTimeConverter) {
|
||||||
// Big TODO: Change wording from "item" to "topic".
|
// Big TODO: Change wording from "item" to "topic".
|
||||||
// import from textarea
|
// import from textarea
|
||||||
$scope.importByLine = function () {
|
$scope.importByLine = function () {
|
||||||
@ -342,22 +343,13 @@ angular.module('OpenSlidesApp.topics.site', ['OpenSlidesApp.topics'])
|
|||||||
}
|
}
|
||||||
// duration
|
// duration
|
||||||
if (item.duration) {
|
if (item.duration) {
|
||||||
var time = item.duration.replace(quotionRe, '$1').split(':'),
|
var time = item.duration.replace(quotionRe, '$1');
|
||||||
len = time.length,
|
time = HumanTimeConverter.humanTimeToSeconds(time, {hours: true})/60;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data < 0 || data === '') {
|
if (time <= 0) { // null instead of 0 or negative duration
|
||||||
data = null; // no negative duration
|
time = null;
|
||||||
}
|
}
|
||||||
item.duration = data;
|
item.duration = time;
|
||||||
} else {
|
} else {
|
||||||
item.duration = null;
|
item.duration = null;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user