diff --git a/calendar/inc/class.calendar_favorite_portlet.inc.php b/calendar/inc/class.calendar_favorite_portlet.inc.php index 87731a90b9..0a40b286de 100644 --- a/calendar/inc/class.calendar_favorite_portlet.inc.php +++ b/calendar/inc/class.calendar_favorite_portlet.inc.php @@ -58,6 +58,9 @@ class calendar_favorite_portlet extends home_favorite_portlet public function exec($id = null, etemplate_new &$etemplate = null) { + // Always load app's javascript, so most actions have a chance of working + egw_framework::validate_file('.','app',$this->context['appname']); + // Always load app's css egw_framework::includeCSS('calendar', 'app-'.$GLOBALS['egw_info']['user']['preferences']['common']['theme']) || egw_framework::includeCSS('calendar','app'); @@ -86,8 +89,6 @@ class calendar_favorite_portlet extends home_favorite_portlet $etemplate->read('home.legacy'); $etemplate->set_dom_id($id); - // Always load app's javascript, so most actions have a chance of working - egw_framework::validate_file('','app',$this->context['appname']); } $content = array('legacy' => ''); @@ -143,7 +144,7 @@ class calendar_favorite_portlet extends home_favorite_portlet $this->favorite['state']['view'] == 'day' ? 1 : 4 ); $this->actions =& $etemplate->getElementAttribute('view', 'actions'); - $ui->week($days, $etemplate); + $ui->week($days, $etemplate); return; } diff --git a/calendar/inc/class.calendar_uiviews.inc.php b/calendar/inc/class.calendar_uiviews.inc.php index 13bf009ae2..70df4078b5 100644 --- a/calendar/inc/class.calendar_uiviews.inc.php +++ b/calendar/inc/class.calendar_uiviews.inc.php @@ -612,12 +612,18 @@ class calendar_uiviews extends calendar_ui $search_params['start'] = $week_start->format('ts'); $search_params['end'] = $week_end->format('ts'); - $content['view'][] = (array)$this->tagWholeDayOnTop($this->bo->search($search_params)); + $content['view'][] = (array)$this->tagWholeDayOnTop($this->bo->search($search_params)) + + array( + 'id' => $week_start->format('Ymd') + ); $home->setElementAttribute("view[$week]",'onchange',false); $home->setElementAttribute("view[$week]",'granularity',$granularity); $home->setElementAttribute("view[$week]",'show_weekend', $this->search_params['weekend']); $week++; } + + // Get the actions + $home->setElementAttribute('view','actions',$this->get_actions()); $home->exec(__METHOD__, $content); } diff --git a/calendar/js/app.js b/calendar/js/app.js index 51f2f8ef3e..eaf57282eb 100644 --- a/calendar/js/app.js +++ b/calendar/js/app.js @@ -75,6 +75,9 @@ app.classes.calendar = AppJS.extend( // up to date as state is changed. sidebox_hooked_templates: [], + // List of queries in progress, to prevent home from requesting the same thing + _queries_in_progress: [], + /** * Constructor * @@ -2724,6 +2727,14 @@ app.classes.calendar = AppJS.extend( // Show ajax loader framework.applications.calendar.sidemenuEntry.showAjaxLoader() + // Already in progress? + var query_string = JSON.stringify(query); + if(this._queries_in_progress.indexOf(query_string) != -1) + { + return; + } + this._queries_in_progress.push(query_string); + this.egw.dataFetch( instance ? instance.etemplate_exec_id : this.sidebox_et2.getInstanceManager().etemplate_exec_id, @@ -2731,7 +2742,13 @@ app.classes.calendar = AppJS.extend( query, this.id, function calendar_handleResponse(data) { - console.log(data); + var idx = this._queries_in_progress.indexOf(query_string); + if(idx >= 0) + { + this._queries_in_progress.splice(idx,1); + } + //console.log(data); + // Look for any updated select options if(data.rows && data.rows.sel_options && this.sidebox_et2) { diff --git a/calendar/js/calendar_favorite_portlet.js b/calendar/js/calendar_favorite_portlet.js index 0c5c952406..5889890f97 100644 --- a/calendar/js/calendar_favorite_portlet.js +++ b/calendar/js/calendar_favorite_portlet.js @@ -27,38 +27,47 @@ observer: function(_msg, _app, _id, _type, _msg_type, _targetapp) // List view, we can just update it this.portlet.getWidgetById('nm').refresh(_id,_type); } + else if (_id) + { + // Calendar app should handle it in its observer() + } + else if (app.classes.calendar && app.calendar) + { + // No ID, probably a refresh of app. Calendar will discard the cache. + // Only make a request if: + // - portlet date range is outside calendar state range + // - portlet owner is not in calendar state owner + // Otherwise, we'll kill the connection with several overlapping requests + + var value = []; + var state = this.portlet.options.settings.favorite.state; + if(state.owner == 0) state.owner = [egw.user('account_id')]; + this.portlet.iterateOver(function(view) { + value.push({ + owner: view.options.owner, + start_date: view.options.start_date, + end_date: view.options.end_date + }) + state.first = !state.first || state.first > view.options.start_date ? view.options.start_date : state.first; + state.last = !state.last || state.last < view.options.end_date ? view.options.end_date : state.last; + },this, et2_calendar_view); + + if(state.first < new Date(app.calendar.state.first) || state.last > new Date(app.calendar.state.last) || + state.owner != app.calendar.state.owner) + { + app.calendar.et2 = this.portlet._children[0] + app.calendar._need_data(value, state); + } + } else { - var event = egw.dataGetUIDdata('calendar::'+_id); - if(event && event.data && event.data.date) + // No intelligence since we don't have access to the state + // (app.calendar.getState() is for the calendar tab, not home) + // just refresh on every calendar or infolog change + if(_app == 'calendar' || _app == 'infolog') { - var new_cache_id = app.classes.calendar._daywise_cache_id( - event.data.date, - // Make sure to use the right owner, not current calendar state - this.portlet.settings.favorite.state.owner || '' - ); - var daywise = egw.dataGetUIDdata(new_cache_id); - daywise = daywise ? daywise.data : []; - if(_type === 'delete') - { - daywise.splice(daywise.indexOf(_id),1); - } - else if (daywise.indexOf(_id) < 0) - { - daywise.push(_id); - } - egw.dataStoreUID(new_cache_id,daywise); - } - else - { - // No intelligence since we don't have access to the state - // (app.calendar.getState() is for the calendar tab, not home) - // just refresh on every calendar or infolog change - if(_app == 'calendar' || _app == 'infolog') - { - app.home.refresh(this.portlet.id); - } - } + app.home.refresh(this.portlet.id); + } } } }); \ No newline at end of file diff --git a/calendar/js/et2_widget_event.js b/calendar/js/et2_widget_event.js index 03547f368b..4e675a8bfa 100644 --- a/calendar/js/et2_widget_event.js +++ b/calendar/js/et2_widget_event.js @@ -235,7 +235,19 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM], } // Copy actions set in parent - this._link_actions(this._parent._parent._parent.options.actions||{}); + var action_parent = this; + while(action_parent != null && !action_parent.options.actions && + !action_parent.instanceOf(et2_container) + ) + { + action_parent = action_parent.getParent(); + } + try { + this._link_actions(action_parent.options.actions||{}); + } catch (e) { + // something went wrong, but keep quiet about it + debugger; + } // Make sure category stuff is there // Fake it to use the cache / call - if already there, these will return @@ -853,7 +865,7 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM], // objects this._actionObject = objectManager.insertObject(false, new egwActionObject( 'calendar::'+this.options.value.row_id, objectManager, new et2_event_action_object_impl(this,this.getDOMNode()), - this._actionManager || objectManager.manager.getActionById(this.options.value.row_id) || objectManager.manager + this._actionManager || objectManager.manager.getActionById('calendar::'+this.options.value.row_id) || objectManager.manager )); } else diff --git a/calendar/js/et2_widget_planner.js b/calendar/js/et2_widget_planner.js index 08d03083d8..03ad5f46bd 100644 --- a/calendar/js/et2_widget_planner.js +++ b/calendar/js/et2_widget_planner.js @@ -732,7 +732,7 @@ var et2_calendar_planner = et2_calendar_view.extend([et2_IDetachedDOM, et2_IResi this.widget.update_timer = null; this.widget.doInvalidate = true; - window.setTimeout(jQuery.proxy(function() {this.loader.hide();},this.widget),100); + window.setTimeout(jQuery.proxy(function() {if(this.loader) this.loader.hide();},this.widget),100); },{widget:this,"trigger":trigger}),ET2_GRID_INVALIDATE_TIMEOUT); }, diff --git a/calendar/js/et2_widget_timegrid.js b/calendar/js/et2_widget_timegrid.js index 4494ec944a..c94efb83f5 100644 --- a/calendar/js/et2_widget_timegrid.js +++ b/calendar/js/et2_widget_timegrid.js @@ -950,6 +950,8 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes */ _scroll: function(event) { + if(!this.day_widgets) return; + // Loop through days, let them deal with it for(var day = 0; day < this.day_widgets.length; day++) { @@ -1013,7 +1015,7 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes for(var i = 0; i < parent.children.length; i++) { - var parent_finder = jQuery(this.div, parent.children[i].iface.doGetDOMNode()); + var parent_finder = jQuery(parent.children[i].iface.doGetDOMNode()).find(this.div); if(parent_finder.length > 0) { parent = parent.children[i]; @@ -1303,7 +1305,7 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes * necessarily an entry from the resource app), or a list containing a * combination of both. */ - set_value: function(events) + set_value: function set_value(events) { if(typeof events !== 'object') return false; @@ -1328,27 +1330,36 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes this.set_start_date(day_list[0]); this.set_end_date(day_list[day_list.length-1]); } - - // Sub widgets actually get their own data from egw.data, so we'll - // stick it there - var consolidated = et2_calendar_view.is_consolidated(this.options.owner, this.day_list.length == 1 ? 'day' : 'week'); - for(var day in events) + + // We need to check if we're attached already, as the datastore can cause + // conflicts across other events (especially home) if we call it too early + if(this.isAttached()) { - var day_list = []; - for(var i = 0; i < events[day].length; i++) + // Sub widgets actually get their own data from egw.data, so we'll + // stick it there + var consolidated = et2_calendar_view.is_consolidated(this.options.owner, this.day_list.length == 1 ? 'day' : 'week'); + for(var day in events) { - day_list.push(events[day][i].row_id); - egw.dataStoreUID('calendar::'+events[day][i].row_id, events[day][i]); - } - // Might be split by user, so we have to check that too - for(var i = 0; i < this.options.owner.length; i++) - { - var owner = consolidated ? this.options.owner : this.options.owner[i]; - var day_id = app.classes.calendar._daywise_cache_id(day,owner); - egw.dataStoreUID(day_id, day_list); - if(consolidated) break; + var day_list = []; + for(var i = 0; i < events[day].length; i++) + { + day_list.push(events[day][i].row_id); + egw.dataStoreUID('calendar::'+events[day][i].row_id, events[day][i]); + } + // Might be split by user, so we have to check that too + for(var i = 0; i < this.options.owner.length; i++) + { + var owner = consolidated ? this.options.owner : this.options.owner[i]; + var day_id = app.classes.calendar._daywise_cache_id(day,owner); + egw.dataStoreUID(day_id, day_list); + if(consolidated) break; + } } } + else + { + this.value = events; + } } // Reset and calculate instead of just use the keys so we can get the weekend preference @@ -1781,9 +1792,10 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes { this.options.height = Math.max(this.options.height, needed); // Set all others to match - if(!_too_small && rowCount > 1) + if(!_too_small && rowCount > 1 && this._parent) { window.setTimeout(jQuery.proxy(function() { + if(!this._parent) return; this._parent.iterateOver(function(widget) { if(!widget.disabled) widget.resize(true); },this, et2_calendar_timegrid); diff --git a/home/inc/class.home_favorite_portlet.inc.php b/home/inc/class.home_favorite_portlet.inc.php index 76d721e2aa..4a5af3f921 100644 --- a/home/inc/class.home_favorite_portlet.inc.php +++ b/home/inc/class.home_favorite_portlet.inc.php @@ -125,7 +125,7 @@ class home_favorite_portlet extends home_portlet egw_framework::includeCSS($this->context['appname'],'app'); // Always load app's javascript, so most actions have a chance of working - egw_framework::validate_file('','app',$this->context['appname']); + egw_framework::validate_file('.','app',$this->context['appname']); // Set this so app's JS gets initialized $old_app = $GLOBALS['egw_info']['flags']['currentapp']; diff --git a/home/js/app.js b/home/js/app.js index 746c00963d..7f12bf0a9e 100644 --- a/home/js/app.js +++ b/home/js/app.js @@ -157,13 +157,15 @@ app.classes.home = AppJS.extend( // Check for existing etemplate, this one loaded over it // NOTE: Moving them around like this can cause problems with event handlers var existing = etemplate2.getById(et2.uniqueId); - if(portlet && existing && existing.etemplate_exec_id != et2.etemplate_exec_id) + if(portlet && existing) { for(var i = 0; i < portlet._children.length; i++) { - if(portlet._children[i]._inst) portlet._children[i]._inst.clear(); + if(typeof portlet._children[i]._init == 'undefined') + { + portlet.removeChild(portlet._children[i]) + } } - portlet._children = []; } // It's in the right place for original load, but move it into portlet var misplaced = $j(etemplate2.getById('home-index').DOMContainer).siblings('#'+et2.DOMContainer.id);