diff --git a/etemplate/js/et2_widget_link.js b/etemplate/js/et2_widget_link.js index 134e1a85b3..ca35e7c01a 100644 --- a/etemplate/js/et2_widget_link.js +++ b/etemplate/js/et2_widget_link.js @@ -545,6 +545,7 @@ var et2_link_entry = et2_inputWidget.extend( this._super.apply(this, arguments); this.search = null; + this.clear = null; this.app_select = null; this._oldValue = { id: null, @@ -570,6 +571,7 @@ var et2_link_entry = et2_inputWidget.extend( this.search.autocomplete("destroy"); } this.search = null; + this.clear = null; this.app_select = null; this.request = null; }, @@ -691,6 +693,7 @@ var et2_link_entry = et2_inputWidget.extend( this.clear = $j(document.createElement("span")) .addClass("ui-icon ui-icon-close") .click(function(e){ + if (!self.search) return; // only gives an error, we should never get into that situation // No way to tell if the results is open, so if they click the button while open, it clears if(self.last_search && self.last_search != self.search.val()) { @@ -705,7 +708,11 @@ var et2_link_entry = et2_inputWidget.extend( self.search.autocomplete("close"); self.set_value(null); self.search.val(""); - self.search.trigger("change"); + // call trigger, after finishing this handler, not in the middle of it + window.setTimeout(function() + { + self.search.trigger("change"); + }, 0); } self.search.focus(); }) diff --git a/etemplate/js/et2_widget_textbox.js b/etemplate/js/et2_widget_textbox.js index 5d2cbd27a1..2cb0509f26 100644 --- a/etemplate/js/et2_widget_textbox.js +++ b/etemplate/js/et2_widget_textbox.js @@ -217,8 +217,10 @@ var et2_textbox = et2_inputWidget.extend( }); } } else { + if (!this.getValue()) this.input.val(''); this.input.removeAttr("placeholder"); } + this.options.blur = _value; } }); et2_register_widget(et2_textbox, ["textbox", "passwd"]); diff --git a/timesheet/inc/class.timesheet_bo.inc.php b/timesheet/inc/class.timesheet_bo.inc.php index 6b19a58bea..85d1787de1 100644 --- a/timesheet/inc/class.timesheet_bo.inc.php +++ b/timesheet/inc/class.timesheet_bo.inc.php @@ -152,6 +152,13 @@ class timesheet_bo extends so_sql_cf */ var $columns_to_search = array('egw_timesheet.ts_id', 'ts_project', 'ts_title', 'ts_description', 'ts_duration', 'ts_quantity', 'ts_unitprice'); + /** + * all cols in data which are not (direct)in the db, for data_merge + * + * @var array + */ + var $non_db_cols = array('pm_id'); + function __construct() { parent::__construct(TIMESHEET_APP,'egw_timesheet',self::EXTRA_TABLE,'','ts_extra_name','ts_extra_value','ts_id'); @@ -627,19 +634,21 @@ class timesheet_bo extends so_sql_cf $this->user = $this->data['ts_modifier']; } - // check if we have a real modification - // read the old record - $new =& $this->data; - unset($this->data); - $this->read($new['ts_id']); - $old =& $this->data; - $this->data =& $new; - $changed[] = array(); - if (isset($old)) foreach($old as $name => $value) + // check if we have a real modification of an existing record + if ($this->data['ts_id']) { - if (isset($new[$name]) && $new[$name] != $value) $changed[] = $name; + $new =& $this->data; + unset($this->data); + $this->read($new['ts_id']); + $old =& $this->data; + $this->data =& $new; + $changed = array(); + if (isset($old)) foreach($old as $name => $value) + { + if (isset($new[$name]) && $new[$name] != $value) $changed[] = $name; + } } - if (!$changed) + if (isset($old) && !$changed) { return false; } @@ -666,7 +675,6 @@ class timesheet_bo extends so_sql_cf egw_link::notify_update(TIMESHEET_APP,$this->data['ts_id'],$this->data); } - return $err; } @@ -970,4 +978,68 @@ class timesheet_bo extends so_sql_cf } if ($backup) $this->data = $backup; } + + + /** + * changes the data from the db-format to your work-format + * + * Reimplemented to store just ts_project in db, but have pm_id and ts_project in memory, + * with ts_project only set, if it contains a custom project name. + * + * @param array $data =null if given works on that array and returns result, else works on internal data-array + * @return array + */ + function db2data($data=null) + { + if (($intern = !is_array($data))) + { + $data =& $this->data; + } + // get pm_id from links and ts_project: either project matching ts_project or first found project + if (!isset($data['pm_id']) && $data['ts_id']) + { + $first_pm_id = null; + foreach(egw_link::get_links('timesheet', $data['ts_id'], 'projectmanager') as $pm_id) + { + if (!isset($first_pm_id)) $first_pm_id = $pm_id; + if ($data['ts_project'] == egw_link::title('projectmanager', $pm_id)) + { + $data['pm_id'] = $pm_id; + $data['ts_project_blur'] = $data['ts_project']; + $data['ts_project'] = ''; + break; + } + } + if (!isset($data['pm_id']) && isset($first_pm_id)) $data['pm_id'] = $first_pm_id; + } + elseif ($data['ts_id'] && $data['pm_id'] && egw_link::title('projectmanager', $data['pm_id']) == $data['ts_project']) + { + $data['ts_project_blur'] = $data['ts_project']; + $data['ts_project'] = ''; + } + return parent::db2data($intern ? null : $data); // important to use null, if $intern! + } + + /** + * changes the data from your work-format to the db-format + * + * Reimplemented to store just ts_project in db, but have pm_id and ts_project in memory, + * with ts_project only set, if it contains a custom project name. + * + * @param array $data =null if given works on that array and returns result, else works on internal data-array + * @return array + */ + function data2db($data=null) + { + if (($intern = !is_array($data))) + { + $data =& $this->data; + } + // allways store ts_project to be able to search for it, even if no custom project is set + if (empty($data['ts_project'])) + { + $data['ts_project'] = $data['pm_id'] ? egw_link::title('projectmanager', $data['pm_id']) : ''; + } + return parent::data2db($intern ? null : $data); // important to use null, if $intern! + } } diff --git a/timesheet/inc/class.timesheet_ui.inc.php b/timesheet/inc/class.timesheet_ui.inc.php index 5117c7a4b6..0b97a0be04 100644 --- a/timesheet/inc/class.timesheet_ui.inc.php +++ b/timesheet/inc/class.timesheet_ui.inc.php @@ -91,6 +91,7 @@ class timesheet_ui extends timesheet_bo $only_admin_edit = true; $msg = lang('only Admin can edit this status'); } + $this->data['ts_project_blur'] = $this->data['pm_id'] ? egw_link::title('projectmanager', $this->data['pm_id']) : ''; } else { @@ -144,19 +145,12 @@ class timesheet_ui extends timesheet_bo list($button) = @each($content['button']); $view = $content['view']; $referer = $content['referer']; + $content['ts_project_blur'] = $content['pm_id'] ? egw_link::title('projectmanager', $content['pm_id']) : ''; $this->data = $content; foreach(array('button','view','referer','tabs','start_time') as $key) { unset($this->data[$key]); } - // user switched project to none --> remove project and blur - if ($this->data['ts_project_blur'] && !$this->data['pm_id'] && $this->data['old_pm_id']) - { - unset($this->data['ts_project_blur']); - unset($content['ts_project_blur']); - unset($this->data['ts_project']); - unset($content['ts_project']); - } switch($button) { case 'edit': @@ -186,8 +180,6 @@ class timesheet_ui extends timesheet_bo { $etpl->set_validation_error('start_time',lang('Starttime has to be before endtime !!!')); } - // only store project-blur, if a project is selected - if (!$this->data['ts_project'] && $this->data['pm_id']) $this->data['ts_project'] = $this->data['ts_project_blur']; // set ts_title to ts_project if short viewtype (title is not editable) if($this->ts_viewtype == 'short') { @@ -213,6 +205,20 @@ class timesheet_ui extends timesheet_bo } if ($etpl->validation_errors()) break; // the user need to fix the error, before we can save the entry + // account for changed project --> remove old one from links and add new one + if ((int) $this->data['pm_id'] != (int) $this->data['old_pm_id']) + { + // update links accordingly + if ($this->data['pm_id']) + { + egw_link::link(TIMESHEET_APP,$content['link_to']['to_id'],'projectmanager',$this->data['pm_id']); + } + if ($this->data['old_pm_id']) + { + egw_link::unlink2(0,TIMESHEET_APP,$content['link_to']['to_id'],0,'projectmanager',$this->data['old_pm_id']); + unset($this->data['old_pm_id']); + } + } // check if we are linked to a project, but that is NOT set as project if (!$this->data['pm_id'] && is_array($content['link_to']['to_id'])) { @@ -221,6 +227,7 @@ class timesheet_ui extends timesheet_bo if ($data['app'] == 'projectmanager') { $this->data['pm_id'] = $data['id']; + $this->data['ts_project_blur'] = egw_link::title('projectmanager', $data['id']); break; } } @@ -234,19 +241,6 @@ class timesheet_ui extends timesheet_bo else { $msg = lang('Entry saved'); - if ((int) $this->data['pm_id'] != (int) $this->data['old_pm_id']) - { - // update links accordingly - if ($this->data['pm_id']) - { - egw_link::link(TIMESHEET_APP,$content['link_to']['to_id'],'projectmanager',$this->data['pm_id']); - } - if ($this->data['old_pm_id']) - { - egw_link::unlink2(0,TIMESHEET_APP,$content['link_to']['to_id'],0,'projectmanager',$this->data['old_pm_id']); - unset($this->data['old_pm_id']); - } - } if (is_array($content['link_to']['to_id']) && count($content['link_to']['to_id'])) { egw_link::link(TIMESHEET_APP,$this->data['ts_id'],$content['link_to']['to_id']); @@ -371,10 +365,6 @@ class timesheet_ui extends timesheet_bo { $content['pm_id'] = $preserv['old_pm_id']; } - if ($content['pm_id']) - { - $preserv['ts_project_blur'] = $content['ts_project_blur'] = egw_link::title('projectmanager',$content['pm_id']); - } if ($this->pm_integration == 'full') { $preserv['ts_project'] = $preserv['ts_project_blur']; @@ -392,7 +382,7 @@ class timesheet_ui extends timesheet_bo // the actual title-blur is either the preserved title blur (if we are called from infolog entry), // or the preserved project-blur comming from the current selected project - $content['ts_title_blur'] = $preserv['ts_title_blur'] ? $preserv['ts_title_blur'] : $preserv['ts_project_blur']; + $content['ts_title_blur'] = $preserv['ts_title_blur'] ? $preserv['ts_title_blur'] : $content['ts_project_blur']; $readonlys = array( 'button[delete]' => !$this->data['ts_id'] || !$this->check_acl(EGW_ACL_DELETE) || $this->data['ts_status'] == self::DELETED_STATUS, 'button[undelete]' => $this->data['ts_status'] != self::DELETED_STATUS, diff --git a/timesheet/js/app.js b/timesheet/js/app.js index 5292738419..2e6df6030c 100644 --- a/timesheet/js/app.js +++ b/timesheet/js/app.js @@ -96,4 +96,20 @@ app.classes.timesheet = AppJS.extend( egw.css(".et2_label.ts_description","display:" + (filter2.getValue() == '1' ? "block;" : "none;")); } }, + + /** + * Change handler for project selection to set empty ts_project string, if project get deleted + * + * @param {type} _egw + * @param {et2_widget_link_entry} _widget + * @returns {undefined} + */ + pm_id_changed: function(_egw, _widget) + { + var ts_project = this.et2.getWidgetById('ts_project'); + if (ts_project) + { + ts_project.set_blur(_widget.getValue() ? _widget.search.val() : ''); + } + } }); diff --git a/timesheet/templates/default/edit.xet b/timesheet/templates/default/edit.xet index 73e54fbb20..5d0a4f0b2a 100644 --- a/timesheet/templates/default/edit.xet +++ b/timesheet/templates/default/edit.xet @@ -16,7 +16,7 @@ - +