Calendar et2 conversion work in progress.

- Drag & drop reschedule across days/weeks (grid views)
This commit is contained in:
Nathan Gray 2015-07-21 23:45:38 +00:00
parent d9723648fd
commit 1ac7324243
6 changed files with 289 additions and 179 deletions

View File

@ -833,6 +833,7 @@ class calendar_ui
$event['app_id'] .= ':'.$event['recur_date']; $event['app_id'] .= ':'.$event['recur_date'];
} }
$event['parts'] = implode(",\n",$this->bo->participants($event,true)); $event['parts'] = implode(",\n",$this->bo->participants($event,true));
$event['date'] = $this->bo->date2string($event['start']);
// Change dates // Change dates
foreach(calendar_egw_record::$types['date-time'] as $field) foreach(calendar_egw_record::$types['date-time'] as $field)

View File

@ -914,6 +914,11 @@ class calendar_uiforms extends calendar_ui
{ {
// Directly update stored data. If event is still visible, it will // Directly update stored data. If event is still visible, it will
// be notified & update itself. // be notified & update itself.
if(!$old_event)
{
// For new events, make sure we have the whole event, not just form data
$event = $this->bo->read($event['id']);
}
$this->to_client($event); $this->to_client($event);
$response->call('egw.dataStoreUID','calendar::'.$event['id'],$event); $response->call('egw.dataStoreUID','calendar::'.$event['id'],$event);
} }
@ -1036,7 +1041,7 @@ class calendar_uiforms extends calendar_ui
} }
else else
{ {
egw_framework::refresh_opener($msg, 'calendar', $content['id'], $button == 'save' ? 'update' : 'delete'); egw_framework::refresh_opener($msg, 'calendar', $event['id'], $button == 'save' ? ($content['id'] ? 'update' : 'add') : 'delete');
} }
egw_framework::window_close(); egw_framework::window_close();
common::egw_exit(); common::egw_exit();
@ -2549,10 +2554,29 @@ class calendar_uiforms extends calendar_ui
function ajax_moveEvent($_eventId,$calendarOwner,$targetDateTime,$targetOwner,$durationT=null) function ajax_moveEvent($_eventId,$calendarOwner,$targetDateTime,$targetOwner,$durationT=null)
{ {
// we do not allow dragging into another users calendar ATM // we do not allow dragging into another users calendar ATM
if(!$calendarOwner == $targetOwner) if($targetOwner < 0)
{
$targetOwner = [$targetOwner];
}
if($calendarOwner !== $targetOwner && !is_array($targetOwner))
{ {
return false; return false;
} }
// But you may be viewing multiple users, or a group calendar and
// dragging your event
if(is_array($targetOwner) && !in_array($calendarOwner, $targetOwner))
{
$return = true;
foreach($targetOwner as $owner)
{
if($owner < 0 && in_array($calendarOwner, $GLOBALS['egw']->accounts->members($owner,true)))
{
$return = false;
break;
}
}
if($return) return;
}
list($eventId, $date) = explode(':', $_eventId); list($eventId, $date) = explode(':', $_eventId);
$old_event=$event=$this->bo->read($eventId); $old_event=$event=$this->bo->read($eventId);
if (!$durationT) if (!$durationT)
@ -2608,17 +2632,23 @@ class calendar_uiforms extends calendar_ui
} }
} }
$conflicts=$this->bo->update($event); $message = false;
$conflicts=$this->bo->update($event,false, true, false, true, $message);
$response = egw_json_response::get(); $response = egw_json_response::get();
if(!is_array($conflicts)) if(!is_array($conflicts) && $conflicts)
{ {
// Directly update stored data. If event is still visible, it will // Directly update stored data. If event is still visible, it will
// be notified & update itself. // be notified & update itself.
$this->to_client($event); $this->to_client($event);
$response->call('egw.dataStoreUID','calendar::'.$event['id'].($date?':'.$date:''),$event); $response->call('egw.dataStoreUID','calendar::'.$event['id'].($date?':'.$date:''),$event);
if(!$sameday )
{
$response->call('egw.refresh', '','calendar',$event['id'],'update');
}
} }
else else if ($conflicts)
{ {
$response->call( $response->call(
'egw_openWindowCentered2', 'egw_openWindowCentered2',
@ -2630,6 +2660,10 @@ class calendar_uiforms extends calendar_ui
.'&cancel_needs_refresh=true', .'&cancel_needs_refresh=true',
'',750,410); '',750,410);
} }
else if ($message)
{
$response->call('egw.message', implode('<br />', $message));
}
if ($status_reset_to_unknown) if ($status_reset_to_unknown)
{ {
foreach((array)$event['participants'] as $uid => $status) foreach((array)$event['participants'] as $uid => $status)

View File

@ -247,19 +247,19 @@ app.classes.calendar = AppJS.extend(
} }
break; break;
case 'calendar': case 'calendar':
debugger;
var event = egw.dataGetUIDdata('calendar::'+_id); var event = egw.dataGetUIDdata('calendar::'+_id);
if(event && event.data && event.data.date) if(event && event.data && event.data.date)
{ {
var new_cache_id = this._daywise_cache_id(event.data.date) var new_cache_id = this._daywise_cache_id(event.data.date)
var daywise = egw.dataGetUIDdata(new_cache_id).data || []; var daywise = egw.dataGetUIDdata(new_cache_id);
daywise = daywise ? daywise.data : [];
if(_type === 'delete') if(_type === 'delete')
{ {
daywise.splice(daywise.indexOf(_id),1); daywise.splice(daywise.indexOf(_id),1);
} }
else else if (daywise.indexOf(_id) < 0)
{ {
daywise.push(event.date); daywise.push(_id);
} }
egw.dataStoreUID(new_cache_id,daywise); egw.dataStoreUID(new_cache_id,daywise);
} }
@ -338,8 +338,9 @@ app.classes.calendar = AppJS.extend(
var $sortItem = jQuery(this); var $sortItem = jQuery(this);
}, },
start: function () start: function (event, ui)
{ {
$j('.calendar_calTimeGrid',ui.helper).css('position', 'absolute');
// Put owners into row IDs // Put owners into row IDs
app.classes.calendar.views[state.view].etemplates[0].widgetContainer.iterateOver(function(widget) { app.classes.calendar.views[state.view].etemplates[0].widgetContainer.iterateOver(function(widget) {
widget.div.parents('tr').attr('data-owner',widget.options.owner); widget.div.parents('tr').attr('data-owner',widget.options.owner);
@ -363,7 +364,7 @@ app.classes.calendar = AppJS.extend(
// Enable or disable // Enable or disable
if((state.view == 'day' || state.view == 'week') && if((state.view == 'day' || state.view == 'week') &&
state.owner.length > 1 && state.owner.length > egw.config('calview_no_consolidate','phpgwapi')) state.owner.length > 1 && state.owner.length < egw.config('calview_no_consolidate','phpgwapi'))
{ {
sortable.sortable('enable') sortable.sortable('enable')
.sortable("refresh") .sortable("refresh")
@ -414,26 +415,7 @@ app.classes.calendar = AppJS.extend(
var view = app.classes.calendar.views[app.calendar.state.view] || false; var view = app.classes.calendar.views[app.calendar.state.view] || false;
if (view) if (view)
{ {
if(direction > 0) start = view.scroll(direction * delta);
{
start = view.end_date({date:start});
}
else
{
start = view.start_date({date:start});
}
start.setUTCDate(start.getUTCDate()+direction);
}
// Calculate the current difference, and move
else if(app.calendar.state.first && app.calendar.state.last)
{
start = new Date(app.calendar.state.first);
end = new Date(app.calendar.state.last);
// Get the number of days
delta = (Math.round(Math.max(1,end - start)/(24*3600*1000)))*24*3600*1000;
// Adjust
start = new Date(start.valueOf() + (delta * direction ));
end = new Date(end.valueOf() + (delta * direction));
} }
app.calendar.update_state({date:app.calendar.date.toString(start)}); app.calendar.update_state({date:app.calendar.date.toString(start)});
@ -516,7 +498,7 @@ app.classes.calendar = AppJS.extend(
{ {
egw().json( egw().json(
'calendar.calendar_uiforms.ajax_moveEvent', 'calendar.calendar_uiforms.ajax_moveEvent',
[widget.id, widget.options.value.owner, widget.options.value.start, widget.options.value.owner, widget.options.value.duration] [widget.options.value.id, widget.options.value.owner, widget.options.value.start, widget.options.value.owner, widget.options.value.duration]
).sendRequest(true); ).sendRequest(true);
}, },
@ -2137,9 +2119,23 @@ app.classes.calendar = AppJS.extend(
d.setUTCMilliseconds(0); d.setUTCMilliseconds(0);
return d; return d;
}, },
/**
* Get the owner for this view
*
* This is always the owner from the given state, we use a function
* to trigger setting the widget value.
*
* @param {number[]|String} state.owner List of owner IDs, or a comma seperated list
* @returns {number[]|String}
*/
owner: function(state) { owner: function(state) {
return state.owner || 0; return state.owner || 0;
}, },
/**
* Should the view show the weekends
*
* @returns {boolean} Current preference to show 5 or 7 days in weekview
*/
show_weekend: function(state) show_weekend: function(state)
{ {
return parseInt(egw.preference('days_in_weekview','calendar')) == 7; return parseInt(egw.preference('days_in_weekview','calendar')) == 7;
@ -2147,6 +2143,19 @@ app.classes.calendar = AppJS.extend(
extend: function(sub) extend: function(sub)
{ {
return jQuery.extend({},this,{_super:this},sub); return jQuery.extend({},this,{_super:this},sub);
},
/**
* Determines the new date after scrolling. The default is 1 week.
*
* @param {number} delta Integer for how many 'ticks' to move, positive for
* forward, negative for backward
* @returns {Date}
*/
scroll: function(delta)
{
var d = new Date(app.calendar.state.date);
d.setUTCDate(d.getUTCDate() + (7 * delta));
return d;
} }
} }
}); });
@ -2177,6 +2186,12 @@ jQuery.extend(app.classes.calendar,{
state.days = '1'; state.days = '1';
return app.calendar.View.show_weekend.call(this,state); return app.calendar.View.show_weekend.call(this,state);
},
scroll: function(delta)
{
var d = new Date(app.calendar.state.date);
d.setUTCDate(d.getUTCDate() + (delta));
return d;
} }
}), }),
day4: app.classes.calendar.prototype.View.extend({ day4: app.classes.calendar.prototype.View.extend({
@ -2251,6 +2266,12 @@ jQuery.extend(app.classes.calendar,{
if(week_start < d) week_start.setUTCHours(24*7); if(week_start < d) week_start.setUTCHours(24*7);
week_start.setUTCHours(week_start.getUTCHours()-1); week_start.setUTCHours(week_start.getUTCHours()-1);
return week_start; return week_start;
},
scroll: function(delta)
{
var d = new Date(app.calendar.state.date);
d.setUTCMonth(d.getUTCMonth() + delta);
return d;
} }
}), }),

View File

@ -181,9 +181,9 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
} }
else if(typeof _date === "string") else if(typeof _date === "string")
{ {
this._parent.date_helper.set_year(_date.substring(0,4)); // Need a new date to avoid invalid month/date combinations when setting
this._parent.date_helper.set_month(_date.substring(4,6)); // month then day
this._parent.date_helper.set_date(_date.substring(6,8)); this._parent.date_helper.set_value(new Date(_date.substring(0,4),_date.substring(4,6)-1,_date.substring(6,8)));
} }
this.date = new Date(this._parent.date_helper.getValue()); this.date = new Date(this._parent.date_helper.getValue());
@ -225,7 +225,11 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
var events = []; var events = [];
for(var i = 0; i < event_ids.length; i++) for(var i = 0; i < event_ids.length; i++)
{ {
events.push(egw.dataGetUIDdata('calendar::'+event_ids[i]).data); var event = egw.dataGetUIDdata('calendar::'+event_ids[i]).data;
if(event && event.date && event.date === this.options.date)
{
events.push(event);
}
} }
this._update_events(events); this._update_events(events);
},this,this.getInstanceManager().execId,this.id); },this,this.getInstanceManager().execId,this.id);
@ -253,7 +257,11 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
var events = []; var events = [];
for(var i = 0; i < event_ids.length; i++) for(var i = 0; i < event_ids.length; i++)
{ {
events.push(egw.dataGetUIDdata('calendar::'+event_ids[i]).data); var event = egw.dataGetUIDdata('calendar::'+event_ids[i]).data;
if(event && event.date && event.date === this.options.date)
{
events.push(event);
}
} }
this._update_events(events); this._update_events(events);
},this,this.getInstanceManager().execId,this.id); },this,this.getInstanceManager().execId,this.id);
@ -322,16 +330,24 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
*/ */
_update_events: function(_events) _update_events: function(_events)
{ {
// Remove all events var events = _events || this.getArrayMgr('content').getEntry(this.options.date) || [];
while(this._children.length)
// Remove extra events
while(this._children.length > events.length)
{ {
var node = this._children[this._children.length-1]; var node = this._children[this._children.length-1];
this.removeChild(node); this.removeChild(node);
node.free(); node.free();
} }
var events = _events || this.getArrayMgr('content').getEntry(this.options.date) || [];
// Make sure children are in cronological order, or columns are backwards
for(var c = 0; c < events.length; c++) events.sort(function(a,b) {
var start = new Date(a.start) - new Date(b.start);
var end = new Date(a.end) - new Date(b.end);
return a.whole_day ? -1 : (start ? start : end);
});
for(var c = this._children.length; c < events.length; c++)
{ {
// Create event // Create event
var event = et2_createWidget('calendar-event',{ var event = et2_createWidget('calendar-event',{
@ -348,7 +364,7 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
} }
// Seperate loop so column sorting finds all children in the right place // Seperate loop so column sorting finds all children in the right place
for(var c = 0; c < events.length; c++) for(var c = 0; c < events.length && c < this._children.length; c++)
{ {
this._children[c].set_value(events[c]); this._children[c].set_value(events[c]);
} }
@ -386,7 +402,14 @@ var et2_calendar_daycol = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResizea
{ {
var event = this._children[i].options.value || false; var event = this._children[i].options.value || false;
if(!event) continue; if(!event) continue;
if(event.date && event.date != this.options.date)
{
// Still have a child event that has changed date (DnD)
this._children[i].destroy();
this.removeChild(this._children[i]);
continue;
}
var c = 0; var c = 0;
event['multiday'] = false; event['multiday'] = false;
if(typeof event.start !== 'object') if(typeof event.start !== 'object')

View File

@ -99,13 +99,33 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
// Register for updates // Register for updates
var app_id = this.options.value.app_id ? this.options.value.app_id : this.options.value.id + (this.options.value.recur_type ? ':'+this.options.value.recur_date : ''); var app_id = this.options.value.app_id ? this.options.value.app_id : this.options.value.id + (this.options.value.recur_type ? ':'+this.options.value.recur_date : '');
egw.dataRegisterUID('calendar::'+app_id, function(event) { egw.dataRegisterUID('calendar::'+app_id, function(event) {
if(this._parent && this.options.value.date && event.date != this.options.value.date)
{
// Date changed, reparent
var new_parent = this._parent._parent.getWidgetById(event.date);
if(new_parent)
{
new_parent.addChild(this);
}
else
{
// Could not find the right date
this._parent.removeChild(this);
this.destroy();
}
return;
}
// Copy to avoid changes, which may cause nm problems // Copy to avoid changes, which may cause nm problems
this.options.value = jQuery.extend({},event); this.options.value = jQuery.extend({},event);
// Let parent position // Let parent position
this._parent.position_event(this); this._parent.position_event(this);
this._update(this.options.value); // Parent may remove this if the date isn't the same
if(this._parent)
{
this._update(this.options.value);
}
},this,this.getInstanceManager().execId,this.id); },this,this.getInstanceManager().execId,this.id);
@ -123,10 +143,10 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
var eventId = event.id.match(/-?\d+\.?\d*/g)[0]; var eventId = event.id.match(/-?\d+\.?\d*/g)[0];
var appName = event.id.replace(/-?\d+\.?\d*/g,''); var appName = event.id.replace(/-?\d+\.?\d*/g,'');
var app_id = event.app_id ? event.app_id : event.id + (event.recur_type ? ':'+event.recur_date : ''); var app_id = event.app_id ? event.app_id : event.id + (event.recur_type ? ':'+event.recur_date : '');
this._parent.date_helper.set_value(event.start); this._parent.date_helper.set_value(event.start.valueOf ? new Date(event.start) : event.start);
var formatted_start = this._parent.date_helper.getValue(); var formatted_start = this._parent.date_helper.getValue();
this.set_id(eventId || event.id); this.set_id('event_' + (eventId || event.id));
this.div this.div
// Empty & re-append to make sure dnd helpers are gone // Empty & re-append to make sure dnd helpers are gone
@ -156,7 +176,8 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
// Remove any resize classes, the handles are gone due to empty() // Remove any resize classes, the handles are gone due to empty()
.removeClass('ui-resizable') .removeClass('ui-resizable')
.addClass(event.class) .addClass(event.class)
.toggleClass('calendar_calEventPrivate', event.private) .toggleClass('calendar_calEventPrivate', event.private);
this.options.class = event.class;
if(event.category) if(event.category)
{ {
this.div.addClass('cat_' + event.category); this.div.addClass('cat_' + event.category);
@ -240,9 +261,9 @@ var et2_calendar_event = et2_valueWidget.extend([et2_IDetachedDOM],
var bg_color = this.div.css('background-color'); var bg_color = this.div.css('background-color');
var header_color = this.title.css('color'); var header_color = this.title.css('color');
this._parent.date_helper.set_value(this.options.value.start); this._parent.date_helper.set_value(this.options.value.start.valueOf ? new Date(this.options.value.start) : this.options.value.start);
var start = this._parent.date_helper.input_date.val(); var start = this._parent.date_helper.input_date.val();
this._parent.date_helper.set_value(this.options.value.end); this._parent.date_helper.set_value(this.options.value.end.valueOf ? new Date(this.options.value.end) : this.options.value.end);
var end = this._parent.date_helper.input_date.val(); var end = this._parent.date_helper.input_date.val();
var times = !this.options.value.multiday ? var times = !this.options.value.multiday ?

View File

@ -160,35 +160,6 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
// - no action system - // - no action system -
var timegrid = this; var timegrid = this;
// Show the current time while dragging
// Used for resizing as well as drag & drop
var drag_helper = function(event, element,height)
{
this.dropEnd = timegrid._get_time_from_position(element.getBoundingClientRect().left,
element.getBoundingClientRect().top+parseInt(height));
if (typeof this.dropEnd != 'undefined' && this.dropEnd.length)
{
this.dropEnd.addClass("drop-hover");
var time = jQuery.datepicker.formatTime(
egw.preference("timeformat") == 12 ? "h:mmtt" : "HH:mm",
{
hour: this.dropEnd.attr('data-hour'),
minute: this.dropEnd.attr('data-minute'),
seconds: 0,
timezone: 0
},
{"ampm": (egw.preference("timeformat") == "12")}
);
this.innerHTML = '<div style="font-size: 1.1em; text-align:center; font-weight: bold; height:100%;"><span class="calendar_timeDemo" >'+time+'</span></div>';
}
else
{
this.innerHTML = '<div class="calendar_d-n-d_forbiden"></div>';
}
return this.dropEnd;
};
/** /**
* If user puts the mouse over an event, then we'll set up resizing so * If user puts the mouse over an event, then we'll set up resizing so
* they can adjust the length. Should be a little better on resources * they can adjust the length. Should be a little better on resources
@ -236,7 +207,7 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
e.originalEvent = event; e.originalEvent = event;
e.data = {duration: 0}; e.data = {duration: 0};
var event_data = timegrid._get_event_info(this); var event_data = timegrid._get_event_info(this);
var event_widget = timegrid.getWidgetById(event_data.id); var event_widget = timegrid.getWidgetById('event_'+event_data.id);
var sT = event_widget.options.value.start_m; var sT = event_widget.options.value.start_m;
if (typeof this.dropEnd != 'undefined' && this.dropEnd.length == 1) if (typeof this.dropEnd != 'undefined' && this.dropEnd.length == 1)
{ {
@ -269,7 +240,7 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
resize:function(event, ui) resize:function(event, ui)
{ {
// Add 5px to make sure it doesn't land right on the edge of a div // Add 5px to make sure it doesn't land right on the edge of a div
drag_helper.call(this,event,ui.element[0],ui.helper.outerHeight()+5); timegrid._drag_helper(this,ui.element[0],ui.helper.outerHeight()+5);
} }
}); });
}); });
@ -278,70 +249,106 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
this.div.on('dragcreate','.calendar_calEvent:not(.rowNoEdit)', function(event,ui) { this.div.on('dragcreate','.calendar_calEvent:not(.rowNoEdit)', function(event,ui) {
$j(this).draggable('option','cursorAt',false); $j(this).draggable('option','cursorAt',false);
}) })
.on('dragstart', '.calendar_calEvent:not(.rowNoEdit)', function(event,ui) { .on('dragstart', '.calendar_calEvent', function(event,ui) {
$j('.calendar_calEvent',ui.helper).width($j(this).width()) $j('.calendar_calEvent',ui.helper).width($j(this).width())
.height($j(this).outerHeight()) .height($j(this).outerHeight())
.css('top', '').css('left','')
.appendTo(ui.helper); .appendTo(ui.helper);
}) ui.helper.width($j(this).width());
.on('dragstop','.calendar_calEvent:not(.rowNoEdit)', function(event,ui) {
var e = new jQuery.Event('change');
e.originalEvent = event;
e.data = {start: 0};
if (typeof this.dropEnd != 'undefined' && this.dropEnd.length >= 1)
{
var drop_date = this.dropEnd.attr('data-date')||false;
var eT = parseInt(this.dropEnd.attr('data-hour') * 60) + parseInt(this.dropEnd.attr('data-minute'));
var event_data = timegrid._get_event_info(this);
var event_widget = timegrid.getWidgetById(event_data.id);
if(event_widget)
{
event_widget._parent.date_helper.set_year(drop_date.substring(0,4));
event_widget._parent.date_helper.set_month(drop_date.substring(4,6));
event_widget._parent.date_helper.set_date(drop_date.substring(6,8));
event_widget._parent.date_helper.set_hours(this.dropEnd.attr('data-hour'));
event_widget._parent.date_helper.set_minutes(this.dropEnd.attr('data-minute'));
event_widget.options.value.start = event_widget._parent.date_helper.getValue();
// Leave the helper there until the update is done
var loading = ui.helper.clone().appendTo(ui.helper.parent());
loading.addClass('loading');
event_widget.recur_prompt(function(button_id) {
//Get infologID if in case if it's an integrated infolog event
if (event_data.app === 'infolog')
{
// If it is an integrated infolog event we need to edit infolog entry
egw().json('stylite_infolog_calendar_integration::ajax_moveInfologEvent',
[event_data.id, event_widget.options.value.start||false],
function() {loading.remove();}
).sendRequest(true);
}
else
{
//Edit calendar event
egw().json('calendar.calendar_uiforms.ajax_moveEvent', [
button_id=='series' ? event_data.id : event_data.app_id,event_data.owner,
event_widget.options.value.start,
timegrid.options.owner||egw.user('account_id')
],
function() { loading.remove();}
).sendRequest(true);
}
});
}
}
})
// As event is dragged, update the time
.on('drag', '.calendar_calEvent:not(.rowNoEdit)', function(event,ui) {
this.dropEnd = drag_helper.call($j('.calendar_calEventHeader',ui.helper)[0],event,ui.helper[0],0);
$j('.calendar_timeDemo',ui.helper).css('bottom','auto');
}); });
return true; return true;
}, },
/**
* Show the current time while dragging
* Used for resizing as well as drag & drop
*/
_drag_helper: function(element, helper,height)
{
element.dropEnd = this._get_time_from_position(helper.getBoundingClientRect().left,
helper.getBoundingClientRect().top+parseInt(height));
if (typeof element.dropEnd != 'undefined' && element.dropEnd.length)
{
element.dropEnd.addClass("drop-hover");
var time = jQuery.datepicker.formatTime(
egw.preference("timeformat") == 12 ? "h:mmtt" : "HH:mm",
{
hour: element.dropEnd.attr('data-hour'),
minute: element.dropEnd.attr('data-minute'),
seconds: 0,
timezone: 0
},
{"ampm": (egw.preference("timeformat") == "12")}
);
element.innerHTML = '<div style="font-size: 1.1em; text-align:center; font-weight: bold; height:100%;"><span class="calendar_timeDemo" >'+time+'</span></div>';
}
else
{
element.innerHTML = '<div class="calendar_d-n-d_forbiden" style="height:100%"></div>';
}
$j(element).width($j(helper).width());
return element.dropEnd;
},
/**
* Handler for dropping an event on the timegrid
*/
_event_drop: function(timegrid, event,ui) {
var e = new jQuery.Event('change');
e.originalEvent = event;
e.data = {start: 0};
if (typeof this.dropEnd != 'undefined' && this.dropEnd.length >= 1)
{
var drop_date = this.dropEnd.attr('data-date')||false;
var event_data = timegrid._get_event_info(ui.draggable);
var event_widget = timegrid.getWidgetById('event_'+event_data.id);
if(!event_widget)
{
// Widget was moved across weeks / owners
event_widget = timegrid.getParent().getWidgetById('event_'+event_data.id);
}
if(event_widget)
{
event_widget._parent.date_helper.set_year(drop_date.substring(0,4));
event_widget._parent.date_helper.set_month(drop_date.substring(4,6));
event_widget._parent.date_helper.set_date(drop_date.substring(6,8));
event_widget._parent.date_helper.set_hours(this.dropEnd.attr('data-hour'));
event_widget._parent.date_helper.set_minutes(this.dropEnd.attr('data-minute'));
event_widget.options.value.start = new Date(event_widget._parent.date_helper.getValue());
// Leave the helper there until the update is done
var loading = ui.helper.clone().appendTo(ui.helper.parent());
loading.addClass('loading');
event_widget.recur_prompt(function(button_id) {
if(button_id === 'cancel' || !button_id) return;
//Get infologID if in case if it's an integrated infolog event
if (event_data.app === 'infolog')
{
// If it is an integrated infolog event we need to edit infolog entry
egw().json('stylite_infolog_calendar_integration::ajax_moveInfologEvent',
[event_data.id, event_widget.options.value.start||false],
function() {loading.remove();}
).sendRequest(true);
}
else
{
//Edit calendar event
egw().json('calendar.calendar_uiforms.ajax_moveEvent', [
button_id==='series' ? event_data.id : event_data.app_id,event_data.owner,
event_widget.options.value.start,
timegrid.options.owner||egw.user('account_id')
],
function() { loading.remove();}
).sendRequest(true);
}
});
}
}
},
/** /**
* Something changed, and the days need to be re-drawn. We wait a bit to * Something changed, and the days need to be re-drawn. We wait a bit to
* avoid re-drawing twice if start and end date both changed, then recreate * avoid re-drawing twice if start and end date both changed, then recreate
@ -381,7 +388,7 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
detachFromDOM: function() { detachFromDOM: function() {
// Remove the binding to the change handler // Remove the binding to the change handler
$j(this.div).off("change.et2_calendar_timegrid"); $j(this.div).off(".et2_calendar_timegrid");
this._super.apply(this, arguments); this._super.apply(this, arguments);
}, },
@ -636,42 +643,55 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
// Determine target node // Determine target node
var event = _data.event || false; var event = _data.event || false;
if(!event) return; if(!event) return;
if(_data.ui.draggable.hasClass('rowNoEdit')) return;
/*
We have to handle the drop in the normal event stream instead of waiting
for the egwAction system so we can get the helper, and destination
*/
if(event.type === 'drop')
{
this.getWidget()._event_drop.call($j('.calendar_d-n-d_timeCounter',_data.ui.helper)[0],this.getWidget(),event, _data.ui);
}
var drag_listener = function(event, ui) {
aoi.getWidget()._drag_helper($j('.calendar_d-n-d_timeCounter',ui.helper)[0],ui.helper[0],0);
};
var time = $j('.calendar_d-n-d_timeCounter',_data.ui.helper);
switch(_event) switch(_event)
{ {
// Triggered once, when something is dragged into the timegrid's div // Triggered once, when something is dragged into the timegrid's div
case EGW_AI_DRAG_OVER: case EGW_AI_DRAG_OVER:
_data.ui.draggable.off('.et2_timegrid') // Listen to the drag and update the helper with the time
// Listen to the drag and update the helper with the time // This part lets us drag between different timegrids
.on('drag.et2_timegrid',function(event,ui) { _data.ui.draggable.on('drag.et2_timegrid'+widget_object.id, drag_listener);
var nodes = aoi.getWidget()._get_time_from_position(event.clientX,event.clientY); _data.ui.draggable.on('dragend.et2_timegrid'+widget_object.id, function() {
_data.ui.draggable.off('drag.et2_timegrid' + widget_object.id);
});
if(time.length)
{
// The out will trigger after the over, so we count
time.data('count',time.data('count')+1);
}
else
{
_data.ui.helper.prepend('<div class="calendar_d-n-d_timeCounter" data-count="1"><span></span></div>');
}
// Highlight the destination time
$j('[data-date]',aoi.doGetDOMNode()).removeClass("ui-state-active");
nodes.addClass('ui-state-active');
// Update the helper with the actual time
var time = jQuery.datepicker.formatTime(
egw.preference("timeformat") == 12 ? "h:mmtt" : "HH:mm",
{
hour: nodes.attr('data-hour'),
minute: nodes.attr('data-minute'),
seconds: 0,
timezone: 0
},
{"ampm": (egw.preference("timeformat") == "12")}
);
$j('.calendar_d-n-d_timeCounter span',ui.helper).empty().html(time);
})
_data.ui.helper.prepend('<div class="calendar_d-n-d_timeCounter"><span></span></div>');
break; break;
// Triggered once, when something is dragged out of the timegrid // Triggered once, when something is dragged out of the timegrid
case EGW_AI_DRAG_OUT: case EGW_AI_DRAG_OUT:
// Reset // Stop listening
_data.ui.draggable.off('drag.et2_timegrid'+widget_object.id);
// Remove any highlighted time squares
$j('[data-date]',this.doGetDOMNode()).removeClass("ui-state-active"); $j('[data-date]',this.doGetDOMNode()).removeClass("ui-state-active");
_data.ui.draggable.off('.et2_timegrid');
$j('.calendar_d-n-d_timeCounter',_data.ui.helper[0]).remove(); // Out triggers after the over, count to not accidentally remove
time.data('count',time.data('count')-1);
if(time.length && time.data('count') <= 0)
{
time.remove();
}
break; break;
} }
}; };
@ -804,17 +824,7 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
{ {
// Create drag action that allows linking // Create drag action that allows linking
drag_action = mgr.addAction('drag', 'egw_link_drag', egw.lang('link'), 'link', function(action, selected) { drag_action = mgr.addAction('drag', 'egw_link_drag', egw.lang('link'), 'link', function(action, selected) {
// Drag helper - list titles. Arbitrarily limited to 10. // Drag helper - list titles.
var helper = $j(document.createElement("div"));
for(var i = 0; i < selected.length && i < 10; i++)
{
var id = selected[i].id.split('::');
var span = $j(document.createElement('span')).appendTo(helper);
egw.link_title(id[0],id[1], function(title) {
this.append(title);
this.append('<br />');
}, span);
}
// As we wanted to have a general defaul helper interface, we return null here and not using customize helper for links // As we wanted to have a general defaul helper interface, we return null here and not using customize helper for links
// TODO: Need to decide if we need to create a customized helper interface for links anyway // TODO: Need to decide if we need to create a customized helper interface for links anyway
//return helper; //return helper;
@ -823,7 +833,7 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
} }
if(actionLinks.indexOf(drag_action.id) < 0) if(actionLinks.indexOf(drag_action.id) < 0)
{ {
//actionLinks.push(drag_action.id); actionLinks.push(drag_action.id);
} }
drag_action.set_dragType('link'); drag_action.set_dragType('link');
}, },
@ -1038,7 +1048,7 @@ var et2_calendar_timegrid = et2_valueWidget.extend([et2_IDetachedDOM, et2_IResiz
if (this.onevent_change) if (this.onevent_change)
{ {
var event_data = this._get_event_info(dom_node); var event_data = this._get_event_info(dom_node);
var event_widget = this.getWidgetById(event_data.id); var event_widget = this.getWidgetById('event_'+event_data.id);
et2_calendar_event.recur_prompt(event_data, jQuery.proxy(function(button_id, event_data) { et2_calendar_event.recur_prompt(event_data, jQuery.proxy(function(button_id, event_data) {
// No need to continue // No need to continue
if(button_id === 'cancel') return false; if(button_id === 'cancel') return false;