forked from extern/egroupware
244 lines
5.2 KiB
TypeScript
244 lines
5.2 KiB
TypeScript
/**
|
|
* EGroupware eTemplate2 - Duration date widget (WebComponent)
|
|
*
|
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
|
* @package etemplate
|
|
* @subpackage api
|
|
* @link https://www.egroupware.org
|
|
* @author Nathan Gray
|
|
*/
|
|
|
|
|
|
import {css, LitElement} from "@lion/core";
|
|
import {Unparseable} from "@lion/form-core";
|
|
import {Et2InputWidget} from "../Et2InputWidget/Et2InputWidget";
|
|
|
|
export interface formatOptions
|
|
{
|
|
select_unit : string;
|
|
display_format : string;
|
|
data_format : string;
|
|
hours_per_day : number;
|
|
empty_not_0 : boolean;
|
|
number_format? : string;
|
|
};
|
|
|
|
/**
|
|
* Format a number as a time duration
|
|
*
|
|
* @param {number} value
|
|
* @param {object} options
|
|
* set 'timeFormat': "12" to specify a particular format
|
|
* @returns {value: string, unit: string}
|
|
*/
|
|
export function formatDuration(value : number | string, options : formatOptions) : { value : string, unit : string }
|
|
{
|
|
// Handle empty / 0 / no value
|
|
if(value === "" || value == "0" || !value)
|
|
{
|
|
return {value: options.empty_not_0 ? "0" : "", unit: ""};
|
|
}
|
|
// Make sure it's a number now
|
|
value = typeof value == "string" ? parseInt(value) : value;
|
|
|
|
if(!options.select_unit)
|
|
{
|
|
let vals = [];
|
|
for(let i = 0; i < options.display_format.length; ++i)
|
|
{
|
|
let unit = options.display_format[i];
|
|
let val = this._unit_from_value(value, unit, i === 0);
|
|
if(unit === 's' || unit === 'm' || unit === 'h' && options.display_format[0] === 'd')
|
|
{
|
|
vals.push(sprintf('%02d', val));
|
|
}
|
|
else
|
|
{
|
|
vals.push(val);
|
|
}
|
|
}
|
|
return {value: vals.join(':'), unit: ''};
|
|
}
|
|
|
|
// Put value into minutes for further processing
|
|
switch(options.data_format)
|
|
{
|
|
case 'd':
|
|
value *= options.hours_per_day;
|
|
// fall-through
|
|
case 'h':
|
|
value *= 60;
|
|
break;
|
|
case 's':
|
|
value /= 60.0;
|
|
break;
|
|
}
|
|
|
|
// Figure out the best unit for display
|
|
let _unit = options.display_format == "d" ? "d" : "h";
|
|
if(options.display_format.indexOf('m') > -1 && value < 60)
|
|
{
|
|
_unit = 'm';
|
|
}
|
|
else if(options.display_format.indexOf('d') > -1 && value >= (60 * options.hours_per_day))
|
|
{
|
|
_unit = 'd';
|
|
}
|
|
let out_value = "" + (_unit == 'm' ? value : (Math.round((value / 60.0 / (_unit == 'd' ? options.hours_per_day : 1)) * 100) / 100));
|
|
|
|
if(out_value === '')
|
|
{
|
|
_unit = '';
|
|
}
|
|
|
|
// use decimal separator from user prefs
|
|
var format = options.number_format || this.egw().preference('number_format');
|
|
var sep = format ? format[0] : '.';
|
|
if(format && sep && sep != '.')
|
|
{
|
|
out_value = out_value.replace('.', sep);
|
|
}
|
|
|
|
return {value: out_value, unit: _unit};
|
|
}
|
|
|
|
/**
|
|
* Display a time duration (eg: 3 days, 6 hours)
|
|
*
|
|
* If not specified, the time is in assumed to be minutes and will be displayed with a calculated unit
|
|
* but this can be specified with the properties.
|
|
*/
|
|
export class Et2DateDuration extends Et2InputWidget(LitElement)
|
|
{
|
|
static get styles()
|
|
{
|
|
return [
|
|
...super.styles,
|
|
css`
|
|
:host([focused]) ::slotted(button), :host(:hover) ::slotted(button) {
|
|
display: inline-block;
|
|
}
|
|
`,
|
|
];
|
|
}
|
|
|
|
static get properties()
|
|
{
|
|
return {
|
|
...super.properties,
|
|
|
|
/**
|
|
* Data format
|
|
*
|
|
* Units to read/store the data. 'd' = days (float), 'h' = hours (float), 'm' = minutes (int), 's' = seconds (int).
|
|
*/
|
|
data_format: {
|
|
type: String
|
|
},
|
|
/**
|
|
* Display format
|
|
*
|
|
* 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.
|
|
*/
|
|
display_format: {
|
|
type: String
|
|
},
|
|
|
|
/**
|
|
* Select unit or input per unit
|
|
*
|
|
* Display a unit-selection for multiple units, or an input field per unit.
|
|
* Default is true
|
|
*/
|
|
select_unit: {
|
|
type: Boolean
|
|
},
|
|
|
|
/**
|
|
* Percent allowed
|
|
*
|
|
* Allows to enter a percentage instead of numbers
|
|
*/
|
|
percent_allowed: {
|
|
type: Boolean
|
|
},
|
|
|
|
/**
|
|
* Hours per day
|
|
*
|
|
* Number of hours in a day, used for converting between hours and (working) days.
|
|
* Default 8
|
|
*/
|
|
hours_per_day: {type: Number},
|
|
|
|
/**
|
|
* 0 or empty
|
|
*
|
|
* Should the widget differ between 0 and empty, which get then returned as NULL
|
|
* Default false, empty is considered as 0
|
|
*/
|
|
empty_not_0: {type: Boolean},
|
|
|
|
/**
|
|
* Short labels
|
|
*
|
|
* use d/h/m instead of day/hour/minute
|
|
*/
|
|
short_labels: {
|
|
type: Boolean
|
|
},
|
|
|
|
/**
|
|
* Step limit
|
|
*
|
|
* Works with the min and max attributes to limit the increments at which a numeric or date-time value can be set.
|
|
*/
|
|
step: {
|
|
type: String
|
|
}
|
|
}
|
|
}
|
|
|
|
constructor()
|
|
{
|
|
super();
|
|
|
|
// Property defaults
|
|
this.data_format = "m";
|
|
this.display_format = "dhm";
|
|
this.select_unit = true;
|
|
this.percent_allowed = false;
|
|
this.hours_per_day = 8;
|
|
this.empty_not_0 = false;
|
|
this.short_labels = false;
|
|
|
|
this.formatter = formatDuration;
|
|
}
|
|
|
|
getValue()
|
|
{
|
|
if(this.readOnly)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// The supplied value was not understandable, return null
|
|
if(this.modelValue instanceof Unparseable || !this.modelValue)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return this.modelValue.toJSON();
|
|
}
|
|
|
|
render()
|
|
{
|
|
// TODO
|
|
}
|
|
}
|
|
|
|
// @ts-ignore TypeScript is not recognizing that this is a LitElement
|
|
customElements.define("et2-date-duration", Et2DateDuration);
|