implement date-duration select_unit="false" to show durations like "0:01:20"

This commit is contained in:
Ralf Becker 2021-02-05 15:57:38 +02:00
parent 0021080641
commit 04f4a327c2
4 changed files with 269 additions and 29 deletions

View File

@ -23,6 +23,7 @@ var __extends = (this && this.__extends) || (function () {
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.et2_date_range = exports.et2_date_ro = exports.et2_date_duration_ro = exports.et2_date_duration = exports.et2_date = void 0;
/*egw:uses
/vendor/bower-asset/jquery/dist/jquery.js;
/vendor/bower-asset/jquery-ui/jquery-ui.js;
@ -593,16 +594,17 @@ var et2_date_duration = /** @class */ (function (_super) {
_this.options.display_format = _this.options.display_format.replace("%", "");
}
// Clean formats
_this.options.display_format = _this.options.display_format.replace(/[^dhm]/, '');
_this.options.display_format = _this.options.display_format.replace(/[^dhms]/, '');
if (!_this.options.display_format) {
// @ts-ignore
_this.options.display_format = _this.attributes.display_format["default"];
}
// Get translations
_this.time_formats = {
"d": _this.options.short_labels ? _this.egw().lang("d") : _this.egw().lang("Days"),
"h": _this.options.short_labels ? _this.egw().lang("h") : _this.egw().lang("Hours"),
"m": _this.options.short_labels ? _this.egw().lang("m") : _this.egw().lang("Minutes")
d: _this.options.short_labels ? _this.egw().lang("d") : _this.egw().lang("Days"),
h: _this.options.short_labels ? _this.egw().lang("h") : _this.egw().lang("Hours"),
m: _this.options.short_labels ? _this.egw().lang("m") : _this.egw().lang("Minutes"),
s: _this.options.short_labels ? _this.egw().lang("s") : _this.egw().lang("Seconds")
},
_this.createInputWidget();
return _this;
@ -611,9 +613,40 @@ var et2_date_duration = /** @class */ (function (_super) {
// Create nodes
this.node = jQuery(document.createElement("span"))
.addClass('et2_date_duration');
this.duration = jQuery(document.createElement("input"))
var inputs = [];
for (var i = this.options.select_unit ? 1 : this.options.display_format.length; i > 0; --i) {
var input = document.createElement("input");
inputs.push(input);
if (!this.options.select_unit) {
var attr = { min: 0 };
switch (this.options.display_format[this.options.display_format.length - i]) {
case 's':
attr.max = 60;
attr.title = this.egw().lang('Seconds');
break;
case 'm':
attr.max = 60;
attr.title = this.egw().lang('Minutes');
break;
case 'h':
attr.max = 24;
attr.title = this.egw().lang('Hours');
break;
case 'd':
attr.title = this.egw().lang('Days');
break;
}
jQuery(input).attr(attr);
}
}
this.duration = jQuery(inputs)
.addClass('et2_date_duration')
.attr({ type: 'number', size: 3, step: this.options.step, lang: this.egw().preference('number_format')[0] === "," ? "en-150" : "en-001" });
.attr({
type: 'number',
size: 3,
step: this.options.step,
lang: this.egw().preference('number_format')[0] === "," ? "en-150" : "en-001"
});
this.node.append(this.duration);
var self = this;
// seems the 'invalid' event doesn't work in all browsers, eg. FF therefore
@ -672,8 +705,40 @@ var et2_date_duration = /** @class */ (function (_super) {
}
}
};
et2_date_duration.prototype._unit2seconds = function (_unit) {
switch (_unit) {
case 's':
return 1;
case 'm':
return 60;
case 'h':
return 3600;
case 'd':
return 3600 * this.options.hours_per_day;
}
};
et2_date_duration.prototype._unit_from_value = function (_value, _unit) {
_value *= this._unit2seconds(this.data_format);
// get value for given _unit
switch (_unit) {
case 's':
return _value % 60;
case 'm':
return Math.floor(_value / 60) % 60;
case 'h':
return Math.floor(_value / 3600) % this.options.hours_per_day;
case 'd':
return Math.floor(_value / 3600 * this.options.hours_per_day);
}
};
et2_date_duration.prototype.set_value = function (_value) {
this.options.value = _value;
if (!this.options.select_unit && this.options.display_format.length > 1) {
for (var i = this.options.display_format.length; --i >= 0;) {
jQuery(this.duration[i]).val(this._unit_from_value(_value, this.options.display_format[i]));
}
return;
}
var display = this._convert_to_display(parseFloat(_value));
// Set display
if (this.duration[0].nodeName == "INPUT") {
@ -699,13 +764,18 @@ var et2_date_duration = /** @class */ (function (_super) {
this.format = null;
}
this.options.display_format = format;
if ((this.format == null || this.format.is('select')) && (this.options.display_format.length <= 1 || this.options.readonly)) {
if ((this.format == null || this.format.is('select')) &&
(this.options.display_format.length <= 1 || this.options.readonly || !this.options.select_unit)) {
if (this.format) {
this.format.remove();
}
this.format = jQuery(document.createElement('span')).appendTo(this.node);
}
if (this.options.display_format.length > 1 && !this.options.readonly) {
if (!this.options.select_unit && this.options.display_format.length > 1) {
// no unit selection or display
this.format.hide();
}
else if (this.options.display_format.length > 1 && !this.options.readonly) {
if (this.format && !this.format.is('select')) {
this.format.remove();
this.format = null;
@ -735,6 +805,20 @@ var et2_date_duration = /** @class */ (function (_super) {
* @return Object {value: Value in display format, unit: unit for display}
*/
et2_date_duration.prototype._convert_to_display = function (_value) {
if (!this.options.select_unit) {
var vals = [];
for (var i = 0; i < this.options.display_format.length; ++i) {
var unit = this.options.display_format[i];
var val = this._unit_from_value(_value, unit);
if (unit === 's' || unit === 'm' || unit === 'h' && this.options.display_format[0] === 'd') {
vals.push(sprintf('%02d', val));
}
else {
vals.push(val);
}
}
return { value: vals.join(':'), unit: '' };
}
if (_value) {
// Put value into minutes for further processing
switch (this.options.data_format) {
@ -744,6 +828,9 @@ var et2_date_duration = /** @class */ (function (_super) {
case 'h':
_value *= 60;
break;
case 's':
_value /= 60.0;
break;
}
}
// Figure out best unit for display
@ -770,6 +857,16 @@ var et2_date_duration = /** @class */ (function (_super) {
* Change displayed value into storage value and return
*/
et2_date_duration.prototype.getValue = function () {
if (!this.options.select_unit && this.options.display_format.length > 1) {
var value_1 = 0;
for (var i = this.options.display_format.length; --i >= 0;) {
value_1 += parseInt(jQuery(this.duration[i]).val()) * this._unit2seconds(this.options.display_format[i]);
}
if (this.options.data_format !== 's') {
value_1 /= this._unit2seconds(this.options.data_format);
}
return this.options.data_format === 'm' ? Math.round(value_1) : value_1;
}
var value = this.duration.val().replace(',', '.');
if (value === '') {
return this.options.empty_not_0 ? '' : 0;
@ -784,7 +881,9 @@ var et2_date_duration = /** @class */ (function (_super) {
break;
}
// Minutes should be an integer. Floating point math.
value = Math.round(value);
if (this.options.data_format !== 's') {
value = Math.round(value);
}
switch (this.options.data_format) {
case 'd':
value /= this.options.hours_per_day;
@ -792,6 +891,9 @@ var et2_date_duration = /** @class */ (function (_super) {
case 'h':
value /= 60.0;
break;
case 's':
value = Math.round(value * 60.0);
break;
}
return value;
};
@ -800,13 +902,19 @@ var et2_date_duration = /** @class */ (function (_super) {
"name": "Data format",
"default": "m",
"type": "string",
"description": "Units to read/store the data. 'd' = days (float), 'h' = hours (float), 'm' = minutes (int)."
"description": "Units to read/store the data. 'd' = days (float), 'h' = hours (float), 'm' = minutes (int), 's' = seconds (int)."
},
"display_format": {
"name": "Display format",
"default": "dhm",
"type": "string",
"description": "Permitted units for displaying the data. 'd' = days, 'h' = hours, 'm' = minutes. Use combinations to give a choice. Default is 'dh' = days or hours with selectbox."
"description": "Permitted units for displaying the data. 'd' = days, 'h' = hours, 'm' = minutes, 's' = seconds. Use combinations to give a choice. Default is 'dh' = days or hours with selectbox."
},
"select_unit": {
"name": "Select unit or input per unit",
"default": true,
"type": "boolean",
"description": "Display a unit-selection for multiple units, or an input field per unit."
},
"percent_allowed": {
"name": "Percent allowed",

View File

@ -662,13 +662,19 @@ export class et2_date_duration extends et2_date
"name": "Data format",
"default": "m",
"type": "string",
"description": "Units to read/store the data. 'd' = days (float), 'h' = hours (float), 'm' = minutes (int)."
"description": "Units to read/store the data. 'd' = days (float), 'h' = hours (float), 'm' = minutes (int), 's' = seconds (int)."
},
"display_format": {
"name": "Display format",
"default": "dhm",
"type": "string",
"description": "Permitted units for displaying the data. 'd' = days, 'h' = hours, 'm' = minutes. Use combinations to give a choice. Default is 'dh' = days or hours with selectbox."
"description": "Permitted units for displaying the data. 'd' = days, 'h' = hours, 'm' = minutes, 's' = seconds. Use combinations to give a choice. Default is 'dh' = days or hours with selectbox."
},
"select_unit": {
"name": "Select unit or input per unit",
"default": true,
"type": "boolean",
"description": "Display a unit-selection for multiple units, or an input field per unit."
},
"percent_allowed": {
"name": "Percent allowed",
@ -704,7 +710,7 @@ export class et2_date_duration extends et2_date
public static readonly legacyOptions: string[] = ["data_format","display_format", "hours_per_day", "empty_not_0", "short_labels"];
time_formats: {"d":"d","h":"h","m":"m"};
time_formats: {d:"d", h:"h", m:"m", s:"s"};
// @ts-ignore baseWidget defines node as HTMLElement
node: JQuery;
@ -727,7 +733,7 @@ export class et2_date_duration extends et2_date
}
// Clean formats
this.options.display_format = this.options.display_format.replace(/[^dhm]/,'');
this.options.display_format = this.options.display_format.replace(/[^dhms]/,'');
if(!this.options.display_format)
{
// @ts-ignore
@ -736,9 +742,10 @@ export class et2_date_duration extends et2_date
// Get translations
this.time_formats = {
"d": this.options.short_labels ? this.egw().lang("d") : this.egw().lang("Days"),
"h": this.options.short_labels ? this.egw().lang("h") : this.egw().lang("Hours"),
"m": this.options.short_labels ? this.egw().lang("m") : this.egw().lang("Minutes")
d: this.options.short_labels ? this.egw().lang("d") : this.egw().lang("Days"),
h: this.options.short_labels ? this.egw().lang("h") : this.egw().lang("Hours"),
m: this.options.short_labels ? this.egw().lang("m") : this.egw().lang("Minutes"),
s: this.options.short_labels ? this.egw().lang("s") : this.egw().lang("Seconds")
},
this.createInputWidget();
}
@ -748,9 +755,43 @@ export class et2_date_duration extends et2_date
// Create nodes
this.node = jQuery(document.createElement("span"))
.addClass('et2_date_duration');
this.duration = jQuery(document.createElement("input"))
let inputs = [];
for (let i=this.options.select_unit?1:this.options.display_format.length; i > 0; --i)
{
let input = document.createElement("input");
inputs.push(input);
if (!this.options.select_unit)
{
let attr :any = {min : 0};
switch(this.options.display_format[this.options.display_format.length-i])
{
case 's':
attr.max = 60;
attr.title = this.egw().lang('Seconds');
break;
case 'm':
attr.max = 60;
attr.title = this.egw().lang('Minutes');
break;
case 'h':
attr.max = 24;
attr.title = this.egw().lang('Hours');
break;
case 'd':
attr.title = this.egw().lang('Days');
break;
}
jQuery(input).attr(attr);
}
}
this.duration = jQuery(inputs)
.addClass('et2_date_duration')
.attr({type: 'number', size: 3, step:this.options.step, lang: this.egw().preference('number_format')[0] === "," ? "en-150": "en-001"});
.attr({
type: 'number',
size: 3,
step:this.options.step,
lang: this.egw().preference('number_format')[0] === "," ? "en-150": "en-001"
});
this.node.append(this.duration);
var self = this;
@ -827,10 +868,51 @@ export class et2_date_duration extends et2_date
}
}
private _unit2seconds(_unit)
{
switch(_unit)
{
case 's':
return 1;
case 'm':
return 60;
case 'h':
return 3600;
case 'd':
return 3600 * this.options.hours_per_day;
}
}
private _unit_from_value(_value, _unit)
{
_value *= this._unit2seconds(this.data_format);
// get value for given _unit
switch(_unit)
{
case 's':
return _value % 60;
case 'm':
return Math.floor(_value / 60) % 60;
case 'h':
return Math.floor(_value / 3600) % this.options.hours_per_day;
case 'd':
return Math.floor(_value / 3600*this.options.hours_per_day);
}
}
set_value(_value)
{
this.options.value = _value;
if (!this.options.select_unit && this.options.display_format.length > 1)
{
for (let i = this.options.display_format.length; --i >= 0;)
{
jQuery(this.duration[i]).val(this._unit_from_value(_value, this.options.display_format[i]));
}
return;
}
var display = this._convert_to_display(parseFloat(_value));
// Set display
@ -865,7 +947,8 @@ export class et2_date_duration extends et2_date
this.format = null;
}
this.options.display_format = format;
if((this.format == null || this.format.is('select')) && (this.options.display_format.length <= 1 || this.options.readonly))
if((this.format == null || this.format.is('select')) &&
(this.options.display_format.length <= 1 || this.options.readonly || !this.options.select_unit))
{
if (this.format)
{
@ -873,7 +956,12 @@ export class et2_date_duration extends et2_date
}
this.format = jQuery(document.createElement('span')).appendTo(this.node);
}
if(this.options.display_format.length > 1 && !this.options.readonly)
if (!this.options.select_unit && this.options.display_format.length > 1)
{
// no unit selection or display
this.format.hide();
}
else if(this.options.display_format.length > 1 && !this.options.readonly)
{
if(this.format && !this.format.is('select')) {
this.format.remove();
@ -910,6 +998,24 @@ export class et2_date_duration extends et2_date
*/
_convert_to_display(_value)
{
if (!this.options.select_unit)
{
let vals = [];
for (let i=0; i < this.options.display_format.length; ++i)
{
let unit = this.options.display_format[i];
let val = this._unit_from_value(_value, unit);
if (unit === 's' || unit === 'm' || unit === 'h' && this.options.display_format[0] === 'd' )
{
vals.push(sprintf('%02d', val));
}
else
{
vals.push(val);
}
}
return {value: vals.join(':'), unit: ''};
}
if (_value)
{
// Put value into minutes for further processing
@ -921,6 +1027,9 @@ export class et2_date_duration extends et2_date
case 'h':
_value *= 60;
break;
case 's':
_value /= 60.0;
break;
}
}
@ -955,6 +1064,19 @@ export class et2_date_duration extends et2_date
*/
getValue()
{
if (!this.options.select_unit && this.options.display_format.length > 1)
{
let value = 0;
for(let i=this.options.display_format.length; --i >= 0; )
{
value += parseInt(<string>jQuery(this.duration[i]).val()) * this._unit2seconds(this.options.display_format[i]);
}
if (this.options.data_format !== 's')
{
value /= this._unit2seconds(this.options.data_format);
}
return this.options.data_format === 'm' ? Math.round(value) : value;
}
var value = this.duration.val().replace(',', '.');
if(value === '')
{
@ -971,8 +1093,10 @@ export class et2_date_duration extends et2_date
break;
}
// Minutes should be an integer. Floating point math.
value = Math.round(value);
if (this.options.data_format !== 's')
{
value = Math.round(value);
}
switch(this.options.data_format)
{
case 'd':
@ -981,6 +1105,9 @@ export class et2_date_duration extends et2_date
case 'h':
value /= 60.0;
break;
case 's':
value = Math.round(value * 60.0);
break;
}
return value;
}

View File

@ -155,7 +155,7 @@ class Date extends Transformer
$value = self::get_array($content, $form_name);
$valid =& self::get_array($validated, $form_name, true);
if($value)
if ($value && $this->type !== 'date-duration')
{
try
{
@ -233,7 +233,11 @@ class Date extends Transformer
$value = $max;
}
}
if(!$value)
if ($this->type == 'date-duration')
{
$valid = (string)$value === '' ? '' : (int)$value;
}
elseif(!$value)
{
// Not null, blank
$value = '';

View File

@ -521,8 +521,9 @@ span.et2_date span {
text-align: center;
font-size: 9pt;
}
span.et2_date_duration input.et2_date_duration{
width: 25%;
span.et2_date_duration input.et2_date_duration {
width: 3em;
text-align: right;
}
span.et2_date_duration span {
vertical-align: -webkit-baseline-middle;
@ -2722,7 +2723,7 @@ span.et2_url_span input.et2_fullWidth {
float: left;
}
.et2_fullWidth select.et2_date_duration {
width: 70%;
width: 75%;
float: right;
}