Fix Et2Tree dragging of tree items

This commit is contained in:
nathan 2024-10-18 13:28:57 -06:00
parent 853d6ddd89
commit eb105dfad4
4 changed files with 61 additions and 14 deletions

View File

@ -9,7 +9,13 @@
*/
import {egwActionObjectInterface} from "./egw_action";
import {Et2Tree} from "../etemplate/Et2Tree/Et2Tree";
import {EGW_AI_DRAG_ENTER, EGW_AI_DRAG_OUT, EGW_AO_STATE_FOCUSED, EGW_AO_STATE_SELECTED} from "./egw_action_constants";
import {
EGW_AI_DRAG,
EGW_AI_DRAG_ENTER,
EGW_AI_DRAG_OUT,
EGW_AO_STATE_FOCUSED,
EGW_AO_STATE_SELECTED
} from "./egw_action_constants";
import {egwBitIsSet} from "./egw_action_common";
import {SlTreeItem} from "@shoelace-style/shoelace";
import {FindActionTarget} from "../etemplate/FindActionTarget";
@ -62,6 +68,10 @@ export class EgwDragDropShoelaceTree extends egwActionObjectInterface{
target.target.classList.remove("draggedOver", "drop-hover");
clearTimeout(this.timeouts[target.target.id])
}
else if(egw_event == EGW_AI_DRAG)
{
target.action.setSelected(true);
}
return true
}

View File

@ -103,6 +103,7 @@ export class EgwDropActionImplementation implements EgwActionImplementation {
if (!self.getTheDraggedDOM()) return;
let dropActionObject = _context;
const helper = self.getHelperDOM();
// remove the hover class
this.classList.remove('drop-hover');
@ -111,16 +112,23 @@ export class EgwDropActionImplementation implements EgwActionImplementation {
{
dropActionObject = this.findActionTarget(event).action ?? _context;
}
else if(self.isTheDraggedDOM(this))
{
// clean up the helper dom
if(helper)
{
helper.remove();
}
return;
}
const helper = self.getHelperDOM();
let ui = self.getTheDraggedData();
ui.position = {top: event.clientY, left: event.clientX};
ui.offset = {top: event.offsetY, left: event.offsetX};
let data = JSON.parse(event.dataTransfer.getData('application/json'));
let data = JSON.parse(event.dataTransfer.getData('application/json'));
if(!self.isAccepted(data, dropActionObject, _callback, undefined) || self.isTheDraggedDOM(this))
if(!self.isAccepted(data, dropActionObject, _callback, undefined))
{
// clean up the helper dom
if (helper) helper.remove();

View File

@ -46,10 +46,10 @@ export class EgwDragActionImplementation implements EgwActionImplementation {
_selected[0]._context?._selectionMgr?._total : _selected.length;
// Clone nodes but use copy webComponent properties
const carefulClone = (node) =>
const carefulClone = (node, skip_text = false) =>
{
// Don't clone text nodes, it causes duplication in et2-description
if(node.nodeType == node.TEXT_NODE)
if(skip_text && node.nodeType == node.TEXT_NODE)
{
return;
}
@ -65,7 +65,8 @@ export class EgwDragActionImplementation implements EgwActionImplementation {
// Children
node.childNodes.forEach(c =>
{
const child = carefulClone(c)
// Don't clone text in et2-description, it causes duplication
const child = carefulClone(c, skip_text || ["ET2-DESCRIPTION"].indexOf(c.tagName) != -1)
if(child)
{
clone.appendChild(child);
@ -80,7 +81,12 @@ export class EgwDragActionImplementation implements EgwActionImplementation {
for(const egwActionObject of _selected)
{
const row : Node = carefulClone(egwActionObject.iface.getDOMNode());
let rowNode = egwActionObject.iface.getDOMNode();
if(egwActionObject._context && egwActionObject._context instanceof HTMLElement)
{
rowNode = egwActionObject._context;
}
const row : Node = carefulClone(rowNode);
if(row)
{
rows.push(row);
@ -191,14 +197,20 @@ export class EgwDragActionImplementation implements EgwActionImplementation {
const ai = this
const dragstart = function (event) {
// The helper function is called before the start function
let dragActionObject = _context;
if(this.findActionTarget)
{
dragActionObject = this.findActionTarget(event).action ?? _context;
}
// The helper function is called before the start function
// is evoked. Call the given callback function. The callback
// function will gather the selected elements and action links
// and call the doExecuteImplementation function. This
// will call the onExecute function of the first action
// in order to obtain the helper object (stored in ai.helper)
// and the multiple dragDropTypes (ai.ddTypes)
_callback.call(_context, false, ai);
_callback.call(dragActionObject, false, ai);
// Stop parent elements from also starting to drag if we're nested
if(ai.selected.length)
@ -208,9 +220,12 @@ export class EgwDragActionImplementation implements EgwActionImplementation {
if(action && egw.app_name() == 'filemanager')
{
if (_context.isSelection(event)) return;
if(dragActionObject.isSelection(event))
{
return;
}
// Get all selected
// Get all selected
const selected = ai.selected;
// Set file data

View File

@ -13,7 +13,12 @@ import {EgwActionObject} from "../../egw_action/EgwActionObject";
import {EgwAction} from "../../egw_action/EgwAction";
import {EgwDragDropShoelaceTree} from "../../egw_action/EgwDragDropShoelaceTree";
import {FindActionTarget} from "../FindActionTarget";
import {EGW_AI_DRAG_ENTER, EGW_AI_DRAG_OUT, EGW_AO_FLAG_IS_CONTAINER} from "../../egw_action/egw_action_constants";
import {
EGW_AI_DRAG,
EGW_AI_DRAG_ENTER,
EGW_AI_DRAG_OUT,
EGW_AO_FLAG_IS_CONTAINER
} from "../../egw_action/egw_action_constants";
import styles from "./Et2Tree.styles";
export type TreeItemData = SelectOption & {
@ -789,6 +794,7 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement) implements Fin
//console.log(event.type, id, event.target);
const typeMap = {
dragstart: EGW_AI_DRAG,
dragenter: EGW_AI_DRAG_ENTER,
dragleave: EGW_AI_DRAG_OUT,
}
@ -926,6 +932,7 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement) implements Fin
}
const value = selectOption.value ?? selectOption.id;
const selected = typeof this.value == "string" && this.value == value || Array.isArray(this.value) && this.value.includes(value);
const draggable = this.widget_object?.actionLinks?.filter(al => al.actionObj.type == "drag").length > 0
return html`
<sl-tree-item
@ -940,6 +947,7 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement) implements Fin
?disabled=${selectOption.disabled}
?lazy=${lazy}
?focused=${selectOption.focused || nothing}
draggable=${draggable}
@click=${async(event) =>
{
// Don't react to expand or children
@ -1036,6 +1044,7 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement) implements Fin
}
}
@dragstart=${(event) => {this.handleDragEvent(event);}}
@dragenter=${(event) => {this.handleDragEvent(event);}}
@dragleave=${(event) => {this.handleDragEvent(event);}}
@drop=${(event) => {this.handleDragEvent(event);}}
@ -1218,6 +1227,10 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement) implements Fin
let target = e.composedPath().find(element => {
return element.tagName == "SL-TREE-ITEM"
});
if(!target)
{
return {target: null, action: null};
}
let action : EgwActionObject = this.widget_object.getObjectById(target.id);
// Create on the fly if not there? Action handlers might need the EgwActionObject
@ -1225,6 +1238,7 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement) implements Fin
{
// NOTE: FLAT object structure under the tree ActionObject to avoid nested selection
action = this.widget_object.addObject(target.id, this.widget_object.iface)
action._context = target;
action.setSelected = (set) =>
{
target.action_selected = set;