From abc1f7eb66c2b7c2525b9c5b45436e730a987a1c Mon Sep 17 00:00:00 2001 From: nathan Date: Mon, 22 Jul 2024 14:40:45 -0600 Subject: [PATCH] Calendar: Drag & drop working for normal view --- .../egw_action/EgwDropActionImplementation.ts | 9 +- calendar/js/et2_widget_timegrid.ts | 102 +++++++++++------- calendar/templates/default/app.css | 8 +- calendar/templates/mobile/app.css | 1 + calendar/templates/pixelegg/app.css | 1 + 5 files changed, 79 insertions(+), 42 deletions(-) diff --git a/api/js/egw_action/EgwDropActionImplementation.ts b/api/js/egw_action/EgwDropActionImplementation.ts index 1f7ccbdca4..e53366f727 100644 --- a/api/js/egw_action/EgwDropActionImplementation.ts +++ b/api/js/egw_action/EgwDropActionImplementation.ts @@ -38,11 +38,14 @@ export class EgwDropActionImplementation implements EgwActionImplementation { }; const dragenter = function (event) { - event.stopImmediatePropagation(); - // don't trigger dragenter if we are entering the drag element + // don't trigger dragenter if we are entering the drag element // don't go further if the dragged element is no there (happens when a none et2 dragged element is being dragged) if (!self.getTheDraggedDOM() || self.isTheDraggedDOM(this) || this == self.currentDropEl) return; + // stop the event from being fired for its children + event.stopPropagation(); + event.preventDefault(); + self.currentDropEl = event.currentTarget; event.dataTransfer.dropEffect = 'link'; @@ -60,8 +63,6 @@ export class EgwDropActionImplementation implements EgwActionImplementation { this.classList.add('drop-hover'); - // stop the event from being fired for its children - event.preventDefault(); return false; }; diff --git a/calendar/js/et2_widget_timegrid.ts b/calendar/js/et2_widget_timegrid.ts index ae59778653..f5e15f0f6f 100644 --- a/calendar/js/et2_widget_timegrid.ts +++ b/calendar/js/et2_widget_timegrid.ts @@ -287,6 +287,10 @@ export class et2_calendar_timegrid extends et2_calendar_view implements et2_IDet */ onstart: function(event) { + if(event.type == "resizestart") + { + event.target.removeAttribute("draggable"); + } if(timegrid.drag_create.start) { // Abort drag to create, we're dragging to resize @@ -341,13 +345,14 @@ export class et2_calendar_timegrid extends et2_calendar_view implements et2_IDet */ onmove: function(event) { + event.preventDefault(); + event.stopPropagation(); event.target.style.height = event.rect.height + "px"; // Add a bit for better understanding - it will show _to_ the start, // covering the 'actual' target timegrid._get_time_from_position(event.target.getBoundingClientRect().left, event.target.getBoundingClientRect().bottom + 5); - timegrid.gridHover.hide(); var drop = timegrid._drag_helper(this, event.target); - if(drop && !drop.is(':visible')) + if(drop && !jQuery(drop).is(':visible')) { drop.get(0).scrollIntoView(false); } @@ -357,20 +362,33 @@ export class et2_calendar_timegrid extends et2_calendar_view implements et2_IDet // Customize and override some draggable settings this.div - .on('dragstart', '.calendar_calEvent', function(event) - { - // Cancel drag to create, we're dragging an existing event - timegrid.drag_create.start = null; - timegrid._drag_create_end(); - timegrid._get_time_from_position(event.clientX, event.clientY); - }) + .on("dragend", () => { timegrid.div.off("drag.timegrid"); + + // Remove helper + document.body.querySelectorAll(".calendar_d-n-d_helper").forEach(n => n.remove()); }) .on('dragover', function(event) { + egw.tooltipDestroy(); + // Allow drop to work + event.preventDefault(); + timegrid._get_time_from_position(event.clientX, event.clientY); + + // Need to hide the hover marker or it will interfere with drop + timegrid.gridHover.addClass("hideme"); + + const helper = document.body.querySelector(".calendar_d-n-d_helper"); + if(helper) + { + timegrid._drag_helper(helper, helper, null); + helper.style.top = event.clientY + "px"; + helper.style.left = (event.clientX + 20) + "px"; + } + }) .on('mousemove', function(event) { @@ -380,7 +398,7 @@ export class et2_calendar_timegrid extends et2_calendar_view implements et2_IDet { if(timegrid.div.has(event.relatedTarget).length === 0) { - timegrid.gridHover.hide(); + timegrid.gridHover.addClass("hideme"); } }); @@ -408,10 +426,11 @@ export class et2_calendar_timegrid extends et2_calendar_view implements et2_IDet if(!element) return; element.dropEnd = this.gridHover; + element.style.zIndex = ''; if(element.dropEnd.length) { - this._drop_data = jQuery.extend({},element.dropEnd[0].dataset || {}); + this._drop_data = {...element.dropEnd[0].dataset}; } if (typeof element.dropEnd != 'undefined' && element.dropEnd.length) @@ -444,7 +463,7 @@ export class et2_calendar_timegrid extends et2_calendar_view implements et2_IDet // @ts-ignore time = formatTime(parseTime(element.dropEnd.attr('data-hour') + ":" + element.dropEnd.attr('data-minute'))); } - element.innerHTML = '
'+time+'
'; + element.innerHTML = '
' + time + '
'; } else { @@ -1312,25 +1331,31 @@ export class et2_calendar_timegrid extends et2_calendar_view implements et2_IDet } else { - jQuery(_data.ui.helper).prepend('
'); + drag_listener(event); } break; // Triggered once, when something is dragged out of the timegrid case EGW_AI_DRAG_OUT: - // Stop listening - jQuery(_data.ui.draggable).off('drag.et2_timegrid' + widget_object.id); - // Remove highlighted time square - var timegrid = aoi.getWidget(); - timegrid.gridHover.hide(); - timegrid.scrolling.scrollTop(timegrid._top_time); - - // Out triggers after the over, count to not accidentally remove - time.data('count', time.data('count') - 1); - if(time.length && time.data('count') <= 0) + const timegrid = aoi.getWidget(); + if(!event.composedPath().includes(timegrid.getDOMNode())) { - time.remove(); + // Remove our custom helper + document.body.querySelectorAll(".calendar_d-n-d_helper").forEach(n => n.remove()); + + // Stop listening + //jQuery(_data.ui.draggable).off('drag.et2_timegrid' + widget_object.id); + // Remove highlighted time square + timegrid.gridHover.addClass("hideme"); + timegrid.scrolling.scrollTop(timegrid._top_time); + + // 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; default: @@ -1584,11 +1609,14 @@ export class et2_calendar_timegrid extends et2_calendar_view implements et2_IDet { // Create drag action that allows linking drag_action = mgr.addAction('drag', 'egw_link_drag', egw.lang('link'), 'link', function(action, selected) { - // Drag helper - list titles. - // 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; + // Calendar drag helper - we update with time + const helper = selected[0].iface.getWidget().getDOMNode().cloneNode(); + helper.classList.add("calendar_d-n-d_helper"); + self._drag_helper(helper, selected[0].iface.getDOMNode(), null); + document.body.append(helper); + + // System drag helper - empty span so we can update with the target time + return document.createElement("span"); },true); } // The timegrid itself is not draggable, so don't add a link. @@ -2278,20 +2306,20 @@ export class et2_calendar_timegrid extends et2_calendar_view implements et2_IDet } } - if(!day) - { - return []; - } - this.gridHover - .show() - .css("position", "absolute") - .appendTo(day); + if(time) { this.gridHover .height(this.rowHeight) .css("top", time.offsetTop + "px"); } + if(day) + { + this.gridHover + .css("position", "absolute") + .appendTo(day); + this.gridHover.removeClass("hideme"); + } this.gridHover.css('left',''); return this.gridHover; } diff --git a/calendar/templates/default/app.css b/calendar/templates/default/app.css index fc9cda6c35..4d99decd59 100644 --- a/calendar/templates/default/app.css +++ b/calendar/templates/default/app.css @@ -1353,8 +1353,13 @@ Hide subsequent headers in week view with non-consolidated owners } /** * Calendar Drag and Drop - * Class for div to show forbiden drop */ +.calendar_d-n-d_helper +{ + position: absolute; + z-index:initial; +} + /* Class for div to show forbiden drop */ .calendar_d-n-d_timeCounter > span { position: absolute; background-color: #808080; @@ -1391,6 +1396,7 @@ Hide subsequent headers in week view with non-consolidated owners font-size: 1.1em; font-weight: bold; text-align: center; + min-width: 10em; } .calendar_d-n-d_timeCounter .loading { diff --git a/calendar/templates/mobile/app.css b/calendar/templates/mobile/app.css index 939ae895d2..30c5797660 100644 --- a/calendar/templates/mobile/app.css +++ b/calendar/templates/mobile/app.css @@ -1364,6 +1364,7 @@ Hide subsequent headers in week view with non-consolidated owners font-size: 1.1em; font-weight: bold; text-align: center; + min-width: 10em; } .calendar_d-n-d_timeCounter .loading { width: 16px; diff --git a/calendar/templates/pixelegg/app.css b/calendar/templates/pixelegg/app.css index d533d0b0ff..3de2ecfd25 100755 --- a/calendar/templates/pixelegg/app.css +++ b/calendar/templates/pixelegg/app.css @@ -1352,6 +1352,7 @@ Hide subsequent headers in week view with non-consolidated owners font-size: 1.1em; font-weight: bold; text-align: center; + min-width: 10em; } .calendar_d-n-d_timeCounter .loading { width: 16px;