diff --git a/calendar/js/et2_widget_planner.ts b/calendar/js/et2_widget_planner.ts
index a29c8b7ad1..14194d68d0 100644
--- a/calendar/js/et2_widget_planner.ts
+++ b/calendar/js/et2_widget_planner.ts
@@ -214,6 +214,11 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
*/
onstart: function(event : InteractEvent)
{
+ if(event.type == "resizestart")
+ {
+ event.target.removeAttribute("draggable");
+ }
+ egw.tooltipDestroy();
if(planner.drag_create.start)
{
// Abort drag to create, we're dragging to resize
@@ -358,6 +363,13 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
{
// Cancel drag to create, we're dragging an existing event
planner._drag_create_end();
+ })
+ .on("dragend", () =>
+ {
+ this.div.removeClass(["drop-hover", "et2-dropzone"]);
+
+ // Remove helper
+ document.body.querySelectorAll(".calendar_d-n-d_helper").forEach(n => n.remove());
});
return true;
}
@@ -1488,6 +1500,7 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
aoi.doTriggerEvent = function(_event, _data)
{
+ egw.tooltipDestroy();
// Determine target node
var event = _data.event || false;
@@ -1506,17 +1519,26 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
*/
if(event.type === 'drop')
{
- this.getWidget()._event_drop.call(jQuery('.calendar_d-n-d_timeCounter', _data.ui.draggable)[0], this.getWidget(), event, _data.ui);
+ this.getWidget()._event_drop.call(_data.ui.draggable, this.getWidget(), event, _data.ui);
}
var drag_listener = function(event)
{
+ event.preventDefault();
+
+ const helper = document.body.querySelector(".calendar_d-n-d_helper");
+ if(helper)
+ {
+ helper.style.top = (event.clientY + 20) + "px";
+ helper.style.left = (event.clientX - (helper.clientWidth / 2)) + "px";
+ }
+
let style = getComputedStyle(_data.ui.helper);
- aoi.getWidget()._drag_helper(jQuery('.calendar_d-n-d_timeCounter', _data.ui.draggable)[0], {
- top: parseInt(style.top),
+ aoi.getWidget()._drag_helper(helper, {
+ top: Number.isNaN(style.top) ? event.clientY : parseInt(style.top),
left: event.clientX - jQuery(this).parent().offset().left
}, 0);
};
- var time = jQuery('.calendar_d-n-d_timeCounter', _data.ui.draggable);
+ var time = jQuery('.calendar_d-n-d_timeCounter', _data.ui.helper);
switch(_event)
{
// Triggered once, when something is dragged into the timegrid's div
@@ -1527,6 +1549,11 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
jQuery(_data.ui.draggable).on('dragend.et2_timegrid' + widget_object.id, function()
{
jQuery(_data.ui.draggable).off('drag.et2_timegrid' + widget_object.id);
+
+ aoi.getWidget().div.removeClass(["drop-hover", "et2-dropzone"]);
+
+ // Remove helper
+ document.body.querySelectorAll(".calendar_d-n-d_helper").forEach(n => n.remove());
});
if(time.length)
{
@@ -1535,7 +1562,7 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
}
else
{
- jQuery(_data.ui.draggable).prepend('
');
+ jQuery(_data.ui.helper).prepend('
');
}
break;
@@ -1639,6 +1666,24 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
for(var i = 0; i < source.length; i++)
{
if(!source[i].id) continue;
+
+ if(source[i].manager === dropped.manager)
+ {
+ // Find the planner, could have dropped on an event
+ let planner = dropped.iface.getWidget();
+ while(planner.getParent() && planner.instanceOf && !planner.instanceOf(et2_calendar_planner))
+ {
+ planner = planner.getParent();
+ }
+
+ if(planner && planner._drop_data)
+ {
+ planner._event_drop.call(source[i].iface.getDOMNode(), planner, null, action.ui);
+ }
+ planner._drop_data = false;
+ // Ok, stop.
+ return false;
+ }
id = source[i].id.split('::');
links.push({app: id[0] == 'filemanager' ? 'link' : id[0], id: id[1]});
}
@@ -1753,10 +1798,15 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
{
// Create drag action that allows linking
drag_action = mgr.addAction('drag', 'egw_link_drag', egw.lang('link'), 'link', function(action, selected) {
- // 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
- //return helper;
- return null;
+ const helper = selected[0].iface.getWidget().getDOMNode().cloneNode();
+ helper.classList.add("calendar_d-n-d_helper");
+ let position = selected[0].iface.getDOMNode().getBoundingClientRect();
+
+ self._drag_helper(helper, position, position.height);
+ document.body.append(helper);
+
+ // System drag helper - empty span so we can update with the target time
+ return document.createElement("span");
},true);
}
// The planner itself is not draggable, the action is there for the children
@@ -1809,11 +1859,24 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
*/
_drag_helper(element, position ,height)
{
+ if(!element)
+ {
+ return;
+ }
+ if(position.height)
+ {
+ element.style.height = position.height + "px";
+ }
let time = this._get_time_from_position(position.left, position.top);
element.dropEnd = time;
+ if(time)
+ {
+ this._drop_data = {...element.dataset};
+ }
let formatted_time = formatTime(time);
element.innerHTML = ''+formatted_time+'
';
+ element.querySelector('.calendar_d-n-d_timeCounter').dropEnd = time;
//jQuery(element).width(jQuery(helper).width());
}
@@ -1833,6 +1896,7 @@ export class et2_calendar_planner extends et2_calendar_view implements et2_IDeta
if(typeof this.dropEnd != 'undefined' && this.dropEnd)
{
var drop_date = this.dropEnd.toJSON() || false;
+ this.dropEnd = undefined;
var event_data = planner._get_event_info(ui.draggable);
var event_widget = planner.getWidgetById(event_data.widget_id);
diff --git a/calendar/js/et2_widget_planner_row.ts b/calendar/js/et2_widget_planner_row.ts
index 37aaf4d9b1..8cade8beed 100644
--- a/calendar/js/et2_widget_planner_row.ts
+++ b/calendar/js/et2_widget_planner_row.ts
@@ -150,7 +150,7 @@ export class et2_calendar_planner_row extends et2_valueWidget implements et2_IRe
{
var event = event.iface.getWidget();
const row = target.iface.getWidget() || false;
- if(event === row || !event || !row ||
+ if(event === row || !event || !row || !row.node ||
!event.options || !event.options.value.participants
)
{
@@ -162,7 +162,7 @@ export class et2_calendar_planner_row extends et2_valueWidget implements et2_IRe
for (let id in event.options.value.participants)
{
- owner_match = owner_match || row.node.dataset.participants === '' + id;
+ owner_match = owner_match || (row.node.dataset?.participants ?? false) === '' + id;
}
const enabled = !owner_match &&
@@ -195,14 +195,18 @@ export class et2_calendar_planner_row extends et2_valueWidget implements et2_IRe
*/
if(event.type === 'drop' && widget_object.getActionLink('egw_link_drop').enabled)
{
- this.getWidget().getParent()._event_drop.call(
- jQuery('.calendar_d-n-d_timeCounter', _data.ui.draggable)[0],
- this.getWidget().getParent(), event, _data.ui,
+ const helper = document.body.querySelector(".calendar_d-n-d_helper");
+ const planner = this.getWidget().getParent();
+ planner._event_drop.call(
+ helper,
+ planner, event, _data.ui,
this.getWidget()
);
+ planner._drop_data = false;
}
const drag_listener = function(_event)
{
+ _event.preventDefault();
let position = {};
if(planner.options.group_by === 'month')
{
@@ -212,11 +216,10 @@ export class et2_calendar_planner_row extends et2_valueWidget implements et2_IRe
{
let style = getComputedStyle(_data.ui.helper);
position = {
- top: parseInt(style.top),
+ top: parseInt(style.top || "0"),
left: _event.clientX - jQuery(this).parent().offset().left
}
}
- aoi.getWidget().getParent()._drag_helper(jQuery('.calendar_d-n-d_timeCounter', _data.ui.draggable)[0], position, 0);
var event = _data.ui.selected[0];
if(!event || event.id && event.id.indexOf('calendar') !== 0)
@@ -232,17 +235,23 @@ export class et2_calendar_planner_row extends et2_valueWidget implements et2_IRe
);
}
};
- const time = jQuery('.calendar_d-n-d_timeCounter', _data.ui.draggable);
+ const time = jQuery('.calendar_d-n-d_timeCounter', _data.ui.helper);
switch(_event)
{
// Triggered once, when something is dragged into the timegrid's div
case EGW_AI_DRAG_ENTER:
// Listen to the drag and update the helper with the time
// This part lets us drag between different timegrids
- jQuery(_data.ui.draggable).on('drag.et2_timegrid_row' + widget_object.id, drag_listener);
- jQuery(_data.ui.draggable).on('dragend.et2_timegrid_row' + widget_object.id, function()
+ planner.div.on('dragover.et2_timegrid_row' + widget_object.id, drag_listener);
+ planner.div.on('dragend.et2_timegrid_row' + widget_object.id, function()
{
jQuery(_data.ui.draggable).off('drag.et2_timegrid_row' + widget_object.id);
+
+
+ planner.div.removeClass(["drop-hover", "et2-dropzone"]);
+
+ // Remove helper
+ document.body.querySelectorAll(".calendar_d-n-d_helper").forEach(n => n.remove());
});
widget_object.iface.getWidget().div.addClass('drop-hover');
@@ -265,11 +274,6 @@ export class et2_calendar_planner_row extends et2_valueWidget implements et2_IRe
// The out will trigger after the over, so we count
time.data('count',time.data('count')+1);
}
- else
- {
- jQuery(_data.ui.draggable).prepend('
');
- }
-
break;