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 }); 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 /*egw:uses
/vendor/bower-asset/jquery/dist/jquery.js; /vendor/bower-asset/jquery/dist/jquery.js;
/vendor/bower-asset/jquery-ui/jquery-ui.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("%", ""); _this.options.display_format = _this.options.display_format.replace("%", "");
} }
// Clean formats // 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) { if (!_this.options.display_format) {
// @ts-ignore // @ts-ignore
_this.options.display_format = _this.attributes.display_format["default"]; _this.options.display_format = _this.attributes.display_format["default"];
} }
// Get translations // Get translations
_this.time_formats = { _this.time_formats = {
"d": _this.options.short_labels ? _this.egw().lang("d") : _this.egw().lang("Days"), 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"), 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") 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(); _this.createInputWidget();
return _this; return _this;
@ -611,9 +613,40 @@ var et2_date_duration = /** @class */ (function (_super) {
// Create nodes // Create nodes
this.node = jQuery(document.createElement("span")) this.node = jQuery(document.createElement("span"))
.addClass('et2_date_duration'); .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') .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); this.node.append(this.duration);
var self = this; var self = this;
// seems the 'invalid' event doesn't work in all browsers, eg. FF therefore // 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) { et2_date_duration.prototype.set_value = function (_value) {
this.options.value = _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)); var display = this._convert_to_display(parseFloat(_value));
// Set display // Set display
if (this.duration[0].nodeName == "INPUT") { if (this.duration[0].nodeName == "INPUT") {
@ -699,13 +764,18 @@ var et2_date_duration = /** @class */ (function (_super) {
this.format = null; this.format = null;
} }
this.options.display_format = format; 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) { if (this.format) {
this.format.remove(); this.format.remove();
} }
this.format = jQuery(document.createElement('span')).appendTo(this.node); 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')) { if (this.format && !this.format.is('select')) {
this.format.remove(); this.format.remove();
this.format = null; 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} * @return Object {value: Value in display format, unit: unit for display}
*/ */
et2_date_duration.prototype._convert_to_display = function (_value) { 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) { if (_value) {
// Put value into minutes for further processing // Put value into minutes for further processing
switch (this.options.data_format) { switch (this.options.data_format) {
@ -744,6 +828,9 @@ var et2_date_duration = /** @class */ (function (_super) {
case 'h': case 'h':
_value *= 60; _value *= 60;
break; break;
case 's':
_value /= 60.0;
break;
} }
} }
// Figure out best unit for display // 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 * Change displayed value into storage value and return
*/ */
et2_date_duration.prototype.getValue = function () { 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(',', '.'); var value = this.duration.val().replace(',', '.');
if (value === '') { if (value === '') {
return this.options.empty_not_0 ? '' : 0; return this.options.empty_not_0 ? '' : 0;
@ -784,7 +881,9 @@ var et2_date_duration = /** @class */ (function (_super) {
break; break;
} }
// Minutes should be an integer. Floating point math. // 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) { switch (this.options.data_format) {
case 'd': case 'd':
value /= this.options.hours_per_day; value /= this.options.hours_per_day;
@ -792,6 +891,9 @@ var et2_date_duration = /** @class */ (function (_super) {
case 'h': case 'h':
value /= 60.0; value /= 60.0;
break; break;
case 's':
value = Math.round(value * 60.0);
break;
} }
return value; return value;
}; };
@ -800,13 +902,19 @@ var et2_date_duration = /** @class */ (function (_super) {
"name": "Data format", "name": "Data format",
"default": "m", "default": "m",
"type": "string", "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": { "display_format": {
"name": "Display format", "name": "Display format",
"default": "dhm", "default": "dhm",
"type": "string", "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": { "percent_allowed": {
"name": "Percent allowed", "name": "Percent allowed",

View File

@ -662,13 +662,19 @@ export class et2_date_duration extends et2_date
"name": "Data format", "name": "Data format",
"default": "m", "default": "m",
"type": "string", "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": { "display_format": {
"name": "Display format", "name": "Display format",
"default": "dhm", "default": "dhm",
"type": "string", "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": { "percent_allowed": {
"name": "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"]; 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 // @ts-ignore baseWidget defines node as HTMLElement
node: JQuery; node: JQuery;
@ -727,7 +733,7 @@ export class et2_date_duration extends et2_date
} }
// Clean formats // 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) if(!this.options.display_format)
{ {
// @ts-ignore // @ts-ignore
@ -736,9 +742,10 @@ export class et2_date_duration extends et2_date
// Get translations // Get translations
this.time_formats = { this.time_formats = {
"d": this.options.short_labels ? this.egw().lang("d") : this.egw().lang("Days"), 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"), 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") 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(); this.createInputWidget();
} }
@ -748,9 +755,43 @@ export class et2_date_duration extends et2_date
// Create nodes // Create nodes
this.node = jQuery(document.createElement("span")) this.node = jQuery(document.createElement("span"))
.addClass('et2_date_duration'); .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') .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); this.node.append(this.duration);
var self = this; 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) set_value(_value)
{ {
this.options.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)); var display = this._convert_to_display(parseFloat(_value));
// Set display // Set display
@ -865,7 +947,8 @@ export class et2_date_duration extends et2_date
this.format = null; this.format = null;
} }
this.options.display_format = format; 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) if (this.format)
{ {
@ -873,7 +956,12 @@ export class et2_date_duration extends et2_date
} }
this.format = jQuery(document.createElement('span')).appendTo(this.node); 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')) { if(this.format && !this.format.is('select')) {
this.format.remove(); this.format.remove();
@ -910,6 +998,24 @@ export class et2_date_duration extends et2_date
*/ */
_convert_to_display(_value) _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) if (_value)
{ {
// Put value into minutes for further processing // Put value into minutes for further processing
@ -921,6 +1027,9 @@ export class et2_date_duration extends et2_date
case 'h': case 'h':
_value *= 60; _value *= 60;
break; break;
case 's':
_value /= 60.0;
break;
} }
} }
@ -955,6 +1064,19 @@ export class et2_date_duration extends et2_date
*/ */
getValue() 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(',', '.'); var value = this.duration.val().replace(',', '.');
if(value === '') if(value === '')
{ {
@ -971,8 +1093,10 @@ export class et2_date_duration extends et2_date
break; break;
} }
// Minutes should be an integer. Floating point math. // 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) switch(this.options.data_format)
{ {
case 'd': case 'd':
@ -981,6 +1105,9 @@ export class et2_date_duration extends et2_date
case 'h': case 'h':
value /= 60.0; value /= 60.0;
break; break;
case 's':
value = Math.round(value * 60.0);
break;
} }
return value; return value;
} }

View File

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

View File

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