From ee8c491c7751c09b8419d581bbede87a46ddf297 Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 23 Jul 2024 14:41:17 -0600 Subject: [PATCH] Calendar: Drag & drop working for planner by user view --- calendar/js/et2_widget_planner.ts | 82 ++++++++++++++++++++++++--- calendar/js/et2_widget_planner_row.ts | 34 ++++++----- 2 files changed, 92 insertions(+), 24 deletions(-) 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;