mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-21 23:43:17 +01:00
Fix Et2Tree dragging of tree items
This commit is contained in:
parent
853d6ddd89
commit
eb105dfad4
@ -9,7 +9,13 @@
|
|||||||
*/
|
*/
|
||||||
import {egwActionObjectInterface} from "./egw_action";
|
import {egwActionObjectInterface} from "./egw_action";
|
||||||
import {Et2Tree} from "../etemplate/Et2Tree/Et2Tree";
|
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 {egwBitIsSet} from "./egw_action_common";
|
||||||
import {SlTreeItem} from "@shoelace-style/shoelace";
|
import {SlTreeItem} from "@shoelace-style/shoelace";
|
||||||
import {FindActionTarget} from "../etemplate/FindActionTarget";
|
import {FindActionTarget} from "../etemplate/FindActionTarget";
|
||||||
@ -62,6 +68,10 @@ export class EgwDragDropShoelaceTree extends egwActionObjectInterface{
|
|||||||
target.target.classList.remove("draggedOver", "drop-hover");
|
target.target.classList.remove("draggedOver", "drop-hover");
|
||||||
clearTimeout(this.timeouts[target.target.id])
|
clearTimeout(this.timeouts[target.target.id])
|
||||||
}
|
}
|
||||||
|
else if(egw_event == EGW_AI_DRAG)
|
||||||
|
{
|
||||||
|
target.action.setSelected(true);
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,6 +103,7 @@ export class EgwDropActionImplementation implements EgwActionImplementation {
|
|||||||
if (!self.getTheDraggedDOM()) return;
|
if (!self.getTheDraggedDOM()) return;
|
||||||
|
|
||||||
let dropActionObject = _context;
|
let dropActionObject = _context;
|
||||||
|
const helper = self.getHelperDOM();
|
||||||
|
|
||||||
// remove the hover class
|
// remove the hover class
|
||||||
this.classList.remove('drop-hover');
|
this.classList.remove('drop-hover');
|
||||||
@ -111,16 +112,23 @@ export class EgwDropActionImplementation implements EgwActionImplementation {
|
|||||||
{
|
{
|
||||||
dropActionObject = this.findActionTarget(event).action ?? _context;
|
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();
|
let ui = self.getTheDraggedData();
|
||||||
ui.position = {top: event.clientY, left: event.clientX};
|
ui.position = {top: event.clientY, left: event.clientX};
|
||||||
ui.offset = {top: event.offsetY, left: event.offsetX};
|
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))
|
||||||
|
|
||||||
if(!self.isAccepted(data, dropActionObject, _callback, undefined) || self.isTheDraggedDOM(this))
|
|
||||||
{
|
{
|
||||||
// clean up the helper dom
|
// clean up the helper dom
|
||||||
if (helper) helper.remove();
|
if (helper) helper.remove();
|
||||||
|
@ -46,10 +46,10 @@ export class EgwDragActionImplementation implements EgwActionImplementation {
|
|||||||
_selected[0]._context?._selectionMgr?._total : _selected.length;
|
_selected[0]._context?._selectionMgr?._total : _selected.length;
|
||||||
|
|
||||||
// Clone nodes but use copy webComponent properties
|
// 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
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
@ -65,7 +65,8 @@ export class EgwDragActionImplementation implements EgwActionImplementation {
|
|||||||
// Children
|
// Children
|
||||||
node.childNodes.forEach(c =>
|
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)
|
if(child)
|
||||||
{
|
{
|
||||||
clone.appendChild(child);
|
clone.appendChild(child);
|
||||||
@ -80,7 +81,12 @@ export class EgwDragActionImplementation implements EgwActionImplementation {
|
|||||||
|
|
||||||
for(const egwActionObject of _selected)
|
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)
|
if(row)
|
||||||
{
|
{
|
||||||
rows.push(row);
|
rows.push(row);
|
||||||
@ -191,14 +197,20 @@ export class EgwDragActionImplementation implements EgwActionImplementation {
|
|||||||
const ai = this
|
const ai = this
|
||||||
const dragstart = function (event) {
|
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
|
// is evoked. Call the given callback function. The callback
|
||||||
// function will gather the selected elements and action links
|
// function will gather the selected elements and action links
|
||||||
// and call the doExecuteImplementation function. This
|
// and call the doExecuteImplementation function. This
|
||||||
// will call the onExecute function of the first action
|
// will call the onExecute function of the first action
|
||||||
// in order to obtain the helper object (stored in ai.helper)
|
// in order to obtain the helper object (stored in ai.helper)
|
||||||
// and the multiple dragDropTypes (ai.ddTypes)
|
// 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
|
// Stop parent elements from also starting to drag if we're nested
|
||||||
if(ai.selected.length)
|
if(ai.selected.length)
|
||||||
@ -208,9 +220,12 @@ export class EgwDragActionImplementation implements EgwActionImplementation {
|
|||||||
|
|
||||||
if(action && egw.app_name() == 'filemanager')
|
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;
|
const selected = ai.selected;
|
||||||
|
|
||||||
// Set file data
|
// Set file data
|
||||||
|
@ -13,7 +13,12 @@ import {EgwActionObject} from "../../egw_action/EgwActionObject";
|
|||||||
import {EgwAction} from "../../egw_action/EgwAction";
|
import {EgwAction} from "../../egw_action/EgwAction";
|
||||||
import {EgwDragDropShoelaceTree} from "../../egw_action/EgwDragDropShoelaceTree";
|
import {EgwDragDropShoelaceTree} from "../../egw_action/EgwDragDropShoelaceTree";
|
||||||
import {FindActionTarget} from "../FindActionTarget";
|
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";
|
import styles from "./Et2Tree.styles";
|
||||||
|
|
||||||
export type TreeItemData = SelectOption & {
|
export type TreeItemData = SelectOption & {
|
||||||
@ -789,6 +794,7 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement) implements Fin
|
|||||||
//console.log(event.type, id, event.target);
|
//console.log(event.type, id, event.target);
|
||||||
|
|
||||||
const typeMap = {
|
const typeMap = {
|
||||||
|
dragstart: EGW_AI_DRAG,
|
||||||
dragenter: EGW_AI_DRAG_ENTER,
|
dragenter: EGW_AI_DRAG_ENTER,
|
||||||
dragleave: EGW_AI_DRAG_OUT,
|
dragleave: EGW_AI_DRAG_OUT,
|
||||||
}
|
}
|
||||||
@ -926,6 +932,7 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement) implements Fin
|
|||||||
}
|
}
|
||||||
const value = selectOption.value ?? selectOption.id;
|
const value = selectOption.value ?? selectOption.id;
|
||||||
const selected = typeof this.value == "string" && this.value == value || Array.isArray(this.value) && this.value.includes(value);
|
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`
|
return html`
|
||||||
<sl-tree-item
|
<sl-tree-item
|
||||||
@ -940,6 +947,7 @@ export class Et2Tree extends Et2WidgetWithSelectMixin(LitElement) implements Fin
|
|||||||
?disabled=${selectOption.disabled}
|
?disabled=${selectOption.disabled}
|
||||||
?lazy=${lazy}
|
?lazy=${lazy}
|
||||||
?focused=${selectOption.focused || nothing}
|
?focused=${selectOption.focused || nothing}
|
||||||
|
draggable=${draggable}
|
||||||
@click=${async(event) =>
|
@click=${async(event) =>
|
||||||
{
|
{
|
||||||
// Don't react to expand or children
|
// 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);}}
|
@dragenter=${(event) => {this.handleDragEvent(event);}}
|
||||||
@dragleave=${(event) => {this.handleDragEvent(event);}}
|
@dragleave=${(event) => {this.handleDragEvent(event);}}
|
||||||
@drop=${(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 => {
|
let target = e.composedPath().find(element => {
|
||||||
return element.tagName == "SL-TREE-ITEM"
|
return element.tagName == "SL-TREE-ITEM"
|
||||||
});
|
});
|
||||||
|
if(!target)
|
||||||
|
{
|
||||||
|
return {target: null, action: null};
|
||||||
|
}
|
||||||
let action : EgwActionObject = this.widget_object.getObjectById(target.id);
|
let action : EgwActionObject = this.widget_object.getObjectById(target.id);
|
||||||
|
|
||||||
// Create on the fly if not there? Action handlers might need the EgwActionObject
|
// 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
|
// NOTE: FLAT object structure under the tree ActionObject to avoid nested selection
|
||||||
action = this.widget_object.addObject(target.id, this.widget_object.iface)
|
action = this.widget_object.addObject(target.id, this.widget_object.iface)
|
||||||
|
action._context = target;
|
||||||
action.setSelected = (set) =>
|
action.setSelected = (set) =>
|
||||||
{
|
{
|
||||||
target.action_selected = set;
|
target.action_selected = set;
|
||||||
|
Loading…
Reference in New Issue
Block a user