From ef3e6bc4f4726e96890755f94076cbafcde8565f Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Thu, 2 Jun 2005 22:43:44 +0000 Subject: [PATCH] New widget for durations: floating point input with an optional selectbox to specify a unit (hours or days). The storage format is configurabe and can be either minutes (integer) or hours or days as float --- etemplate/doc/reference.html | 19 +++- etemplate/inc/class.date_widget.inc.php | 138 +++++++++++++++++++++++- etemplate/setup/phpgw_de.lang | 3 + etemplate/setup/phpgw_en.lang | 3 + 4 files changed, 155 insertions(+), 8 deletions(-) diff --git a/etemplate/doc/reference.html b/etemplate/doc/reference.html index ac07a85bd7..93a77a2617 100644 --- a/etemplate/doc/reference.html +++ b/etemplate/doc/reference.html @@ -204,7 +204,7 @@ implement only a subset of XUL. Here are the main differences:

(or as tooltip for buttons or general in gtk). If the user has JavaScript switched off, the help-texts get NOT submitted, as this is detected. If the helptext starts with a '@' it is replaced by the value of the content-array at this - index (with the '@'-removed). + index (with the '@'-removed and after expanding the variables). @@ -216,7 +216,7 @@ implement only a subset of XUL. Here are the main differences:

This attribute controls certain aspects of the different widgets. It's meaning and xml / xul-values are document with the widgets. If the options-string starts with a '@' it is replaced by the value of the content-array at this - index (with the '@'-removed). + index (with the '@'-removed and after expanding the variables). @@ -288,6 +288,8 @@ implement only a subset of XUL. Here are the main differences:

of 'all' can be used to indicate it should span all remaining cells of a row. This is not supported by xul-grid's at the moment, but is planned to be.

class: the CSS class for the widget. + If the class-string starts with a '@' it is replaced by the value of the content-array at this + index (with the '@'-removed and after expanding the variables). @@ -615,8 +617,9 @@ implement only a subset of XUL. Here are the main differences:

<date options="Y-m-d,1"/>

<date type="date-time"/>

- <date type="date-timeonly" options="H:i"/> - <date type="date-houronly"/> + <date type="date-timeonly" options="H:i"/>

+ <date type="date-houronly"/>

+ <date type="date-duration"/> no date @@ -639,7 +642,13 @@ implement only a subset of XUL. Here are the main differences:

Sub-widgets: date-time: a date and a time and date-timeonly or date-houronly: only a time / hour
These widgets allow the input of times too or only, they use 12h am/pm or 24h format as specified in the user prefs.
- If readonly is set, this widget can be used to display a date, without the need to convert it. + If readonly is set, this widget can be used to display a date, without the need to convert it.

+ Duration a floating point input with an optional selectbox for the unit (hours or days)
+ Options: [duration-storage-format] [,[duration-display][,hours_per_day]]
+ duration-storage-format: 'h' = hours (float), 'd' = days (float), default minutes (integer)
+ duration-display: 'd' = days, 'h' = hours, 'dh' = days or hours with selectbox, optional '%' allows to enter a percentage
+ hours_per_day: conversation between hours and (working) day, default 8 + hours_per_day: conversation between hours and (working) day, default 8 diff --git a/etemplate/inc/class.date_widget.inc.php b/etemplate/inc/class.date_widget.inc.php index 5232cb2129..3d1886fae8 100644 --- a/etemplate/inc/class.date_widget.inc.php +++ b/etemplate/inc/class.date_widget.inc.php @@ -51,6 +51,7 @@ 'date-time' => 'Date+Time', // date + time 'date-timeonly' => 'Time', // time 'date-houronly' => 'Hour', // hour + 'date-duration' => 'Duration', // duration ); var $dateformat; // eg. Y-m-d, d-M-Y var $timeformat; // 12 or 24 @@ -90,13 +91,16 @@ function pre_process($name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl) { $type = $cell['type']; - list($data_format,$options) = explode(',',$cell['size']); + if ($type == 'date-duration') + { + return $this->pre_process_duration($name,$value,$cell,$readonlys,$extension_data,$tmpl); + } + list($data_format,$options,$options2) = explode(',',$cell['size']); if ($type == 'date-houronly' && empty($data_format)) $data_format = 'H'; $extension_data = array( - 'data_format' => $data_format, 'type' => $type, + 'data_format' => $data_format, ); - if (!$value) { $value = array( @@ -304,6 +308,100 @@ return True; // extra Label is ok } + /** + * pre-processing of the duration extension + * + * Options contain $data_format,$input_format,$hours_per_day + * - data_format: d = days, h = hours, default minutes + * - input_format: d = days, h = hours, default hours+days (selectbox), optional % = allow to enter a percent value (no conversation) + * - hours_per_day: default 8 (workday) + * + * @param string $name form-name of the control + * @param mixed &$value value / existing content, can be modified + * @param array &$cell array with the widget, can be modified for ui-independent widgets + * @param array &$readonlys names of widgets as key, to be made readonly + * @param mixed &$extension_data data the extension can store persisten between pre- and post-process + * @param object &$tmpl reference to the template we belong too + * @return boolean true if extra label is allowed, false otherwise + */ + function pre_process_duration($name,&$value,&$cell,&$readonlys,&$extension_data,&$tmpl) + { + $readonly = $readonlys || $cell['readonly']; + list($data_format,$input_format,$hours_per_day) = explode(',',$cell['size']); + if (!$hours_per_day) $hours_per_day = 8; // workday is 8 hours + if (($percent_allowed = strstr($input_format,'%') !== false)) + { + $input_format = str_replace('%','',$input_format); + } + if ($input_format != 'h' && $input_format != 'd') $input_format = 'dh'; // hours + days + + $extension_data = array( + 'type' => $cell['type'], + 'data_format' => $data_format, + 'unit' => ($unit = $input_format == 'd' ? 'd' : 'h'), + 'input_format' => $input_format, + 'hours_per_day' => $hours_per_day, + 'percent_allowed'=> $percent_allowed, + ); + switch($data_format) + { + case 'd': + $value *= $hours_per_day; + // fall-through + case 'h': case 'H': + $value *= 60; + break; + } + $cell['type'] = 'text'; + $cell['size'] = '4,,/^-?[0-9]*[,.]?[0-9]*'.($percent_allowed ? '%?' : '').'$/'; + $cell_name = $cell['name']; + $cell['name'] .= '[value]'; + + if ($input_format == 'dh' && $value >= 60*$hours_per_day) + { + $unit = 'd'; + } + $value = !$value ? '' : round($value / 60 / ($unit == 'd' ? $hours_per_day : 1),3); + + if (!$readonly && $input_format == 'dh') // selectbox to switch between hours and days + { + $value = array( + 'value' => $value, + 'unit' => $unit, + ); + $tpl =& new etemplate; + $tpl->init('*** generated fields for duration','','',0,'',0,0); // make an empty template + // keep the editor away from the generated tmpls + $tpl->no_onclick = true; + + $selbox =& $tpl->empty_cell('select',$cell_name.'[unit]'); + $selbox['sel_options'] = array( + 'h' => 'hours', + 'd' => 'days', + ); + + $tpl->data[0] = array(); + $tpl->data[1] =array( + 'A' => $cell, + 'B' => $selbox, + ); + $tpl->set_rows_cols(); + $tpl->size = ',,,,0'; + + unset($cell['size']); + $cell['type'] = 'template'; + $cell['name'] = $tpl->name; + unset($cell['label']); + $cell['obj'] = &$tpl; + } + elseif (!$readonly || $value) + { + $cell['no_lang'] = 2; + $cell['label'] .= ($cell['label'] ? ' ' : '') . '%s '.($input_format == 'h' ? lang('hours') : lang('days')); + } + return True; // extra Label is ok + } + /** * postprocessing method, called after the submission of the form * @@ -328,6 +426,40 @@ { return False; } + if ($extension_data['type'] == 'date-duration') + { + if (is_array($value)) // template with selectbox + { + $unit = $value['unit']; + $value = $value['value']; + } + elseif (!preg_match('/^-?[0-9]*[,.]?[0-9]*'.($extension_data['percent_allowed'] ? '%?' : '').'$/',$value_in)) + { + $GLOBALS['phpgw_info']['etemplate']['validation_errors'][$name] = lang("'%1' is not a valid floatingpoint number !!!",$value_in); + return false; + } + else + { + $value = $value_in; + $unit = $extension_data['unit']; + } + if ($extension_data['percent_allowed'] && substr($value,-1) == '%') + { + return $value; + } + $value = (int) round(str_replace(',','.',$value) * 60 * ($unit == 'd' ? $extension_data['hours_per_day'] : 1)); + + switch($extension_data['data_format']) + { + case 'd': + $value /= (float) $extension_data['hours_per_day']; + // fall-through + case 'h': case 'H': + $value /= 60.0; + break; + } + return true; + } $no_date = substr($extension_data['type'],-4) == 'only'; if ($value['today']) diff --git a/etemplate/setup/phpgw_de.lang b/etemplate/setup/phpgw_de.lang index cd8e13ec77..29e94a4990 100644 --- a/etemplate/setup/phpgw_de.lang +++ b/etemplate/setup/phpgw_de.lang @@ -79,6 +79,7 @@ cut etemplate de Ausschneiden date+time etemplate de Datum+Uhrzeit datum etemplate de Datum day etemplate de Tag +days etemplate de Tage db ensures that every row has a unique value in that column etemplate de die Datenbank stelt sicher das alle Zeilen einen einmaligen Wert in dieser Spalte haben db-specific index options (comma-sep.), eg. mysql(fulltext) or mysql(100) for the indexed length of a col etemplate de DB-spezifische Index-Optionen (Komma-getrennt), zB. mysql(FULLTEXT) oder mysql(100) für die indizierte Länge der Spalte db-tools etemplate de DB-Tools @@ -107,6 +108,7 @@ documentation etemplate de Dokumentation drop a table - this can not be undone etemplate de Tabelle löschen (drop) - NICHT rückgänig zu machen drop table etemplate de Tabelle löschen dump4setup etemplate de Dump4Setup +duration etemplate de Dauer edit etemplate de Bearbeiten edit embeded css styles or of the applications app.css file etemplate de bearbeitet die eingebetteten CSS Stile oder die app.css Datei der Anwendung edit the etemplate spez. above etemplate de das oben spezifizierte eTemplate bearbeiten @@ -165,6 +167,7 @@ height, disabled etemplate de H help etemplate de Hilfe horizontal rule etemplate de Waagrechte Linie hour etemplate de Stunde +hours etemplate de Stunden html etemplate de HTML if field is disabled an empty table-cell is displayed, for (temporal) removement of a field/cell etemplate de wenn das Feld deaktiviert ist, wird eine leere Tabellenzelle angezeigt, zum (zeitweisen) Entfernen eines Feldes image etemplate de Grafik diff --git a/etemplate/setup/phpgw_en.lang b/etemplate/setup/phpgw_en.lang index aa2a3867bf..c36cbcac23 100644 --- a/etemplate/setup/phpgw_en.lang +++ b/etemplate/setup/phpgw_en.lang @@ -79,6 +79,7 @@ cut etemplate en Cut date+time etemplate en Date+Time datum etemplate en Datum day etemplate en Day +days etemplate en days db ensures that every row has a unique value in that column etemplate en DB ensures that every row has a unique value in that column db-specific index options (comma-sep.), eg. mysql(fulltext) or mysql(100) for the indexed length of a col etemplate en db-specific index options (comma-sep.), eg. mysql(FULLTEXT) or mysql(100) for the indexed length of a col db-tools etemplate en DB-Tools @@ -107,6 +108,7 @@ documentation etemplate en Documentation drop a table - this can not be undone etemplate en Drop a table - this can NOT be undone drop table etemplate en Drop Table dump4setup etemplate en Dump4Setup +duration etemplate en Duration edit etemplate en Edit edit embeded css styles or of the applications app.css file etemplate en edit embeded CSS styles or of the applications app.css file edit the etemplate spez. above etemplate en edit the eTemplate spez. above @@ -165,6 +167,7 @@ height, disabled etemplate en Height, Disabled help etemplate en Help horizontal rule etemplate en Horizontal Rule hour etemplate en Hour +hours etemplate en hours html etemplate en Html if field is disabled an empty table-cell is displayed, for (temporal) removement of a field/cell etemplate en if field is disabled an empty table-cell is displayed, for (temporal) removement of a field/cell image etemplate en Image