diff --git a/calendar/inc/class.calendar_uiforms.inc.php b/calendar/inc/class.calendar_uiforms.inc.php index 60bd4029a3..1298ed940f 100644 --- a/calendar/inc/class.calendar_uiforms.inc.php +++ b/calendar/inc/class.calendar_uiforms.inc.php @@ -2811,6 +2811,56 @@ class calendar_uiforms extends calendar_ui } } + /** + * + * @param string $_eventId id of the event to be changed. For recurring events + * it may contain the instance date + * @param string[] $invite Resources to invite + * @param string[] $remove Remove resource from participants + */ + public function ajax_invite($_eventId, $invite = array(), $remove = array()) + { + list($eventId, $date) = explode(':', $_eventId,2); + + $old_event=$event=$this->bo->read($eventId); + foreach($remove as $participant) + { + unset($event['participants'][$participant]); + } + foreach($invite as $participant) + { + $event['participants'][$participant] = 'U'; + } + $conflicts=$this->bo->update($event,false, true, false, true, $message); + + $this->update_client($event['id'],$d); + $response = Api\Json\Response::get(); + if(!is_array($conflicts) && $conflicts) + { + if(is_int($conflicts)) + { + $event['id'] = $conflicts; + $response->call('egw.refresh', '','calendar',$event['id'],'edit'); + } + } + else if ($conflicts) + { + $response->call( + 'egw_openWindowCentered2', + $GLOBALS['egw_info']['server']['webserver_url'].'/index.php?menuaction=calendar.calendar_uiforms.edit + &cal_id='.$event['id'] + .'&start='.$event['start'] + .'&end='.$event['end'] + .'&non_interactive=true' + .'&cancel_needs_refresh=true', + '',750,410); + } + else if ($message) + { + $response->call('egw.message', implode('
', $message)); + } + } + /** * imports a mail as Calendar * diff --git a/calendar/js/et2_widget_daycol.js b/calendar/js/et2_widget_daycol.js index 87f600cc87..814fa4b886 100644 --- a/calendar/js/et2_widget_daycol.js +++ b/calendar/js/et2_widget_daycol.js @@ -359,7 +359,7 @@ var et2_calendar_daycol = (function(){ "use strict"; return et2_valueWidget.exte else if (event) { // Got an ID that doesn't belong - event_ids.splice(i,1); + event_ids.splice(i--,1); } } if(!this._parent.disabled) diff --git a/calendar/js/et2_widget_event.js b/calendar/js/et2_widget_event.js index 1210eac1fd..aac9f8e3db 100644 --- a/calendar/js/et2_widget_event.js +++ b/calendar/js/et2_widget_event.js @@ -866,6 +866,7 @@ var et2_calendar_event = (function(){ "use strict"; return et2_valueWidget.exten var action_links = this._get_action_links(actions); action_links.push('egw_link_drag'); action_links.push('egw_link_drop'); + action_links.push('invite'); this._actionObject.updateActionLinks(action_links); }, @@ -934,12 +935,6 @@ et2_calendar_event.owner_check = function owner_check(event, parent) break; } } - if(!owner_match) - { - owner_match = (parent.options.owner == event.owner || - parent_owner.indexOf && - parent_owner.indexOf(event.owner) >= 0); - } } return owner_match; }; diff --git a/calendar/js/et2_widget_timegrid.js b/calendar/js/et2_widget_timegrid.js index d998881b44..ebfff72e9d 100644 --- a/calendar/js/et2_widget_timegrid.js +++ b/calendar/js/et2_widget_timegrid.js @@ -1006,7 +1006,7 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view. do { - if(show_weekend || !show_weekend && [0,6].indexOf(this.date_helper.date.getUTCDay()) === -1 || end_date == start_date) + if(show_weekend || !show_weekend && [0,6].indexOf(this.date_helper.date.getUTCDay()) === -1 || end_date === start_date) { day_list.push(''+this.date_helper.get_year() + sprintf('%02d',this.date_helper.get_month()) + sprintf('%02d',this.date_helper.get_date())); } @@ -1047,6 +1047,29 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view. break; } } + // Determine if we allow a dropped event to use the invite/change actions + var _invite_enabled = function(action, event, target) + { + var event = event.iface.getWidget(); + var timegrid = target.iface.getWidget() || false; + if(event === timegrid || !event || !timegrid || + !event.options.value.owner || !timegrid.options.owner ) return false; + var owner_match = false; + if(event.options.value.participants) + { + for(var id in event.options.value.participants) + { + if(timegrid.options.owner === id || + timegrid.options.owner.indexOf && + timegrid.options.owner.indexOf(id) >= 0) + { + owner_match = true; + } + } + } + return timegrid.options.owner.toString() !== event.options.value.owner.toString() && + !owner_match; + }; // This binds into the egw action system. Most user interactions (drag to move, resize) // are handled internally using jQuery directly. @@ -1068,7 +1091,7 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view. var dropEnd = false; var helper = $j('.calendar_d-n-d_timeCounter',_data.ui.helper)[0]; if(helper && helper.dropEnd && helper.dropEnd.length >= 1) - if (typeof this.dropEnd != 'undefined' && this.dropEnd.length >= 1) + if (typeof this.dropEnd !== 'undefined' && this.dropEnd.length >= 1) { dropEnd = helper.dropEnd[0].dataset || false; } @@ -1093,6 +1116,24 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view. $j('.calendar_calEventHeader',_data.ui.helper).css('top',''); $j('.calendar_calEventBody',_data.ui.helper).css('padding-top',''); + // Disable invite / change actions for same calendar or already participant + var event = _data.ui.draggable.data('selected')[0]; + if(!event || event.id && event.id.indexOf('calendar') !== 0) + { + event = false; + } + var enabled = event ? _invite_enabled( + widget_object.getActionLink('invite').actionObj, + event, + widget_object + ) : false; + + widget_object.getActionLink('invite').enabled = enabled; + widget_object.getActionLink('change_participant').enabled = enabled; + + // If invite or change participant are enabled, drag is not + widget_object.getActionLink('egw_link_drop').enabled = !enabled; + if(time.length) { // The out will trigger after the over, so we count @@ -1160,19 +1201,21 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view. _init_links_dnd: function(mgr,actionLinks) { var self = this; - var drop_action = mgr.getActionById('egw_link_drop'); + var drop_link = mgr.getActionById('egw_link_drop'); + var drop_change_participant = mgr.getActionById('change_participant'); + var drop_invite = mgr.getActionById('invite'); var drag_action = mgr.getActionById('egw_link_drag'); // Check if this app supports linking if(!egw.link_get_registry(this.dataStorePrefix || 'calendar', 'query') || egw.link_get_registry(this.dataStorePrefix || 'calendar', 'title')) { - if(drop_action) + if(drop_link) { - drop_action.remove(); - if(actionLinks.indexOf(drop_action.id) >= 0) + drop_link.remove(); + if(actionLinks.indexOf(drop_link.id) >= 0) { - actionLinks.splice(actionLinks.indexOf(drop_action.id),1); + actionLinks.splice(actionLinks.indexOf(drop_link.id),1); } } if(drag_action) @@ -1185,12 +1228,11 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view. } return; } - // Don't re-add - if(drop_action == null) + if(drop_link == null) { // Create the drop action that links entries - drop_action = mgr.addAction('drop', 'egw_link_drop', egw.lang('Create link'), egw.image('link'), function(action, source, target) { + drop_link = mgr.addAction('drop', 'egw_link_drop', egw.lang('Create link'), egw.image('link'), function(action, source, target) { // Extract link IDs var links = []; @@ -1256,19 +1298,63 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view. } },true); + + drop_link.acceptedTypes = ['default','link']; + drop_link.hideOnDisabled = true; + + // Create the drop action for moving events between calendars + var invite_action = function(action, source, target) { + + // Extract link IDs + var links = []; + var id = ''; + for(var i = 0; i < source.length; i++) + { + // Check for no ID (invalid) or same manager (dragging an event) + if(!source[i].id) continue; + if(source[i].manager === target.manager) + { + + // Find the timegrid, could have dropped on an event + var timegrid = target.iface.getWidget(); + while(target.parent && timegrid.instanceOf && !timegrid.instanceOf(et2_calendar_timegrid)) + { + target = target.parent; + timegrid = target.iface.getWidget(); + } + + // Leave the helper there until the update is done + var loading = action.ui.helper.clone(true).appendTo($j('body')); + var cal_id = source[i].id.split('::'); + egw().json('calendar.calendar_uiforms.ajax_invite', [ + cal_id[1], + timegrid.options.owner, + action.id === 'change_participant' ? self.options.owner : [] + ], + function() { loading.remove();} + ).sendRequest(true); + // Ok, stop. + return false; + } + } + }; + + drop_change_participant = mgr.addAction('drop', 'change_participant', egw.lang('Change to'), egw.image('participant'), invite_action,true); + drop_change_participant.acceptedTypes = ['calendar']; + drop_change_participant.hideOnDisabled = true; + + drop_invite = mgr.addAction('drop', 'invite', egw.lang('Invite'), egw.image('participant'), invite_action,true); + drop_invite.acceptedTypes = ['calendar']; + drop_invite.hideOnDisabled = true; } - if(actionLinks.indexOf(drop_action.id) < 0) + if(actionLinks.indexOf(drop_link.id) < 0) { - actionLinks.push(drop_action.id); - } - // Accept other links, and files dragged from the filemanager - // This does not handle files dragged from the desktop. They are - // handled by et2_nextmatch, since it needs DOM stuff - if(drop_action.acceptedTypes.indexOf('link') == -1) - { - drop_action.acceptedTypes.push('link'); + actionLinks.push(drop_link.id); } + actionLinks.push(drop_invite.id); + actionLinks.push(drop_change_participant.id); + // Don't re-add if(drag_action == null) { @@ -1287,7 +1373,7 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view. { actionLinks.push(drag_action.id); } - drag_action.set_dragType('link'); + drag_action.set_dragType(['link','calendar']); }, /**