mirror of
https://github.com/EGroupware/egroupware.git
synced 2025-07-01 07:01:12 +02:00
Allow drag and drop between calendars, asking to invite or transfer
This commit is contained in:
@ -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('<br />', $message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* imports a mail as Calendar
|
* imports a mail as Calendar
|
||||||
*
|
*
|
||||||
|
@ -359,7 +359,7 @@ var et2_calendar_daycol = (function(){ "use strict"; return et2_valueWidget.exte
|
|||||||
else if (event)
|
else if (event)
|
||||||
{
|
{
|
||||||
// Got an ID that doesn't belong
|
// Got an ID that doesn't belong
|
||||||
event_ids.splice(i,1);
|
event_ids.splice(i--,1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!this._parent.disabled)
|
if(!this._parent.disabled)
|
||||||
|
@ -866,6 +866,7 @@ var et2_calendar_event = (function(){ "use strict"; return et2_valueWidget.exten
|
|||||||
var action_links = this._get_action_links(actions);
|
var action_links = this._get_action_links(actions);
|
||||||
action_links.push('egw_link_drag');
|
action_links.push('egw_link_drag');
|
||||||
action_links.push('egw_link_drop');
|
action_links.push('egw_link_drop');
|
||||||
|
action_links.push('invite');
|
||||||
this._actionObject.updateActionLinks(action_links);
|
this._actionObject.updateActionLinks(action_links);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -934,12 +935,6 @@ et2_calendar_event.owner_check = function owner_check(event, parent)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!owner_match)
|
|
||||||
{
|
|
||||||
owner_match = (parent.options.owner == event.owner ||
|
|
||||||
parent_owner.indexOf &&
|
|
||||||
parent_owner.indexOf(event.owner) >= 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return owner_match;
|
return owner_match;
|
||||||
};
|
};
|
||||||
|
@ -1006,7 +1006,7 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view.
|
|||||||
|
|
||||||
do
|
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()));
|
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;
|
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)
|
// This binds into the egw action system. Most user interactions (drag to move, resize)
|
||||||
// are handled internally using jQuery directly.
|
// 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 dropEnd = false;
|
||||||
var helper = $j('.calendar_d-n-d_timeCounter',_data.ui.helper)[0];
|
var helper = $j('.calendar_d-n-d_timeCounter',_data.ui.helper)[0];
|
||||||
if(helper && helper.dropEnd && helper.dropEnd.length >= 1)
|
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;
|
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_calEventHeader',_data.ui.helper).css('top','');
|
||||||
$j('.calendar_calEventBody',_data.ui.helper).css('padding-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)
|
if(time.length)
|
||||||
{
|
{
|
||||||
// The out will trigger after the over, so we count
|
// 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) {
|
_init_links_dnd: function(mgr,actionLinks) {
|
||||||
var self = this;
|
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');
|
var drag_action = mgr.getActionById('egw_link_drag');
|
||||||
|
|
||||||
// Check if this app supports linking
|
// Check if this app supports linking
|
||||||
if(!egw.link_get_registry(this.dataStorePrefix || 'calendar', 'query') ||
|
if(!egw.link_get_registry(this.dataStorePrefix || 'calendar', 'query') ||
|
||||||
egw.link_get_registry(this.dataStorePrefix || 'calendar', 'title'))
|
egw.link_get_registry(this.dataStorePrefix || 'calendar', 'title'))
|
||||||
{
|
{
|
||||||
if(drop_action)
|
if(drop_link)
|
||||||
{
|
{
|
||||||
drop_action.remove();
|
drop_link.remove();
|
||||||
if(actionLinks.indexOf(drop_action.id) >= 0)
|
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)
|
if(drag_action)
|
||||||
@ -1185,12 +1228,11 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view.
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't re-add
|
// Don't re-add
|
||||||
if(drop_action == null)
|
if(drop_link == null)
|
||||||
{
|
{
|
||||||
// Create the drop action that links entries
|
// 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
|
// Extract link IDs
|
||||||
var links = [];
|
var links = [];
|
||||||
@ -1256,19 +1298,63 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view.
|
|||||||
}
|
}
|
||||||
|
|
||||||
},true);
|
},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);
|
actionLinks.push(drop_link.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_invite.id);
|
||||||
|
actionLinks.push(drop_change_participant.id);
|
||||||
|
|
||||||
// Don't re-add
|
// Don't re-add
|
||||||
if(drag_action == null)
|
if(drag_action == null)
|
||||||
{
|
{
|
||||||
@ -1287,7 +1373,7 @@ var et2_calendar_timegrid = (function(){ "use strict"; return et2_calendar_view.
|
|||||||
{
|
{
|
||||||
actionLinks.push(drag_action.id);
|
actionLinks.push(drag_action.id);
|
||||||
}
|
}
|
||||||
drag_action.set_dragType('link');
|
drag_action.set_dragType(['link','calendar']);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user