Commit bf1602ad authored by Benni Mack's avatar Benni Mack
Browse files

[TASK] Move temporary mount point handling into PageTreeElement

As the temporary mount point functionality is not bound to
the actual PageTree, but the navigation component, this
code is now moved outside of the PageTree, and using
lit-based rendering and proper event handling.

The advantages of this change are that the SVG
Tree / PageTree component
- does not access HTML outside its own wrapper (parentNode)
- the mount point information is now rendered via LIT (= automatically updated)
- additional setting "temporaryMountPointPath" is not needed inside the PageTree anymore
- We also now use <typo3-backend-icon> and the $lll lit helper

Resolves: #93697
Releases: master
Change-Id: Idaa56f12e6d1444a1abdf23d2a37b71948d47023
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/68307


Tested-by: default avatarDaniel Sattler <sattler@b13.de>
Tested-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Tested-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: core-ci's avatarcore-ci <typo3@b13.com>
Reviewed-by: default avatarDaniel Sattler <sattler@b13.de>
Reviewed-by: Benni Mack's avatarBenni Mack <benni@typo3.org>
Reviewed-by: Benjamin Franzke's avatarBenjamin Franzke <bfr@qbus.de>
parent 8378e1a2
......@@ -325,34 +325,23 @@ $svgColors: (
}
.node-mount-point {
display: table;
width: 100%;
max-width: 265px;
margin: 10px 10px 0;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
display: flex;
border: 0;
background-color: #6daae0;
background-color: $info;
color: #fff;
padding: 11px;
border-radius: 2px;
padding: 1em;
&__icon {
display: table-cell;
width: 1%;
flex: 0 auto;
&[data-tree-icon=actions-close] {
&.mountpoint-close {
cursor: pointer;
}
}
&__text {
display: table-cell;
padding-left: 10px;
padding-right: 10px;
& > div {
max-width: 185px;
overflow: hidden;
}
flex: 1 0 0;
padding: 0 0.5em;
overflow: hidden;
}
}
......@@ -13,19 +13,14 @@
import * as d3selection from 'd3-selection';
import AjaxRequest from 'TYPO3/CMS/Core/Ajax/AjaxRequest';
import {SvgTree, SvgTreeSettings, TreeNodeSelection} from '../SvgTree';
import {SvgTree, TreeNodeSelection} from '../SvgTree';
import {TreeNode} from '../Tree/TreeNode';
import {PageTreeDragDrop, PageTreeNodeDragHandler} from './PageTreeDragDrop';
import Icons = require('../Icons');
import ContextMenu = require('../ContextMenu');
import Persistent from '../Storage/Persistent';
import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {KeyTypesEnum as KeyTypes} from '../Enum/KeyTypes';
interface PageTreeSettings extends SvgTreeSettings {
temporaryMountPoint?: string;
}
/**
* A Tree based on SVG for pages, which has a AJAX-based loading of the tree
* and also handles search + filter via AJAX.
......@@ -33,7 +28,6 @@ interface PageTreeSettings extends SvgTreeSettings {
export class PageTree extends SvgTree
{
public nodeIsEdit: boolean;
public settings: PageTreeSettings;
protected networkErrorTitle: string = TYPO3.lang.pagetree_networkErrorTitle;
protected networkErrorMessage: string = TYPO3.lang.pagetree_networkErrorDesc;
protected searchQuery: string = '';
......@@ -72,9 +66,6 @@ export class PageTree extends SvgTree
this.dispatch.on('prepareLoadedNode.pageTree', (node: TreeNode) => this.prepareLoadedNode(node));
this.dragDrop = dragDrop;
if (this.settings.temporaryMountPoint) {
this.addMountPoint(this.settings.temporaryMountPoint);
}
return true;
}
......@@ -175,7 +166,9 @@ export class PageTree extends SvgTree
.attr('dx', 30)
.attr('dy', 5)
.attr('visibility', (node: TreeNode) => node.stopPageTree && node.depth !== 0 ? 'visible' : 'hidden')
.on('click', (evt: MouseEvent, node: TreeNode) => this.setTemporaryMountPoint(parseInt(node.identifier, 10)));
.on('click', (evt: MouseEvent, node: TreeNode) => {
document.dispatchEvent(new CustomEvent('typo3:pagetree:mountPoint', {detail: {pageId: parseInt(node.identifier, 10)}}));
});
return nodes;
}
......@@ -243,36 +236,6 @@ export class PageTree extends SvgTree
}
}
public setTemporaryMountPoint(pid: number): void {
const params = 'pid=' + pid;
(new AjaxRequest(top.TYPO3.settings.ajaxUrls.page_tree_set_temporary_mount_point))
.post(params, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'},
})
.then((response) => {
return response.resolve();
})
.then((response) => {
if (response && response.hasErrors) {
this.errorNotification(response.message, true);
this.update();
} else {
this.addMountPoint(response.mountPointPath);
this.refreshOrFilterTree();
}
})
.catch((error) => {
this.errorNotification(error, true);
});
}
public unsetTemporaryMountPoint() {
Persistent.unset('pageTree_temporaryMountPoint').then(() => {
this.refreshTree();
});
}
/**
* Initializes a drag&drop when called on the page tree. Should be moved somewhere else at some point
*/
......@@ -493,32 +456,4 @@ export class PageTree extends SvgTree
.select();
}
private addMountPoint(breadcrumb: string) {
let existingMountPointInfo = this.wrapper.parentNode.querySelector('.node-mount-point');
if (existingMountPointInfo) {
existingMountPointInfo.parentNode.removeChild(existingMountPointInfo);
}
this.wrapper.insertAdjacentHTML('beforebegin',
'<div class="node-mount-point">' +
'<div class="node-mount-point__icon" data-tree-icon="actions-document-info"></div>' +
'<div class="node-mount-point__text"><div>' + breadcrumb + '</div></div>' +
'<div class="node-mount-point__icon" data-tree-icon="actions-close" title="' + TYPO3.lang['labels.temporaryDBmount'] + '"></div>' +
'</div>'
);
this.wrapper.parentNode
.querySelector('[data-tree-icon=actions-close]')
.addEventListener('click', () => {
this.unsetTemporaryMountPoint();
this.wrapper.parentNode.querySelector('.node-mount-point').remove();
});
// get icons
this.wrapper.parentNode.querySelectorAll('.node-mount-point [data-tree-icon]').forEach((iconElement: HTMLElement) => {
Icons.getIcon(iconElement.dataset.treeIcon, Icons.sizes.small, null, null, 'inline' as any).then((icon: string) => {
iconElement.insertAdjacentHTML('beforeend', icon);
});
});
}
}
......@@ -20,6 +20,7 @@ import {AjaxResponse} from 'TYPO3/CMS/Core/Ajax/AjaxResponse';
import {select as d3select} from 'd3-selection';
import DebounceEvent from 'TYPO3/CMS/Core/Event/DebounceEvent';
import 'TYPO3/CMS/Backend/Element/IconElement';
import Persistent from 'TYPO3/CMS/Backend/Storage/Persistent';
/**
* This module defines the Custom Element for rendering the navigation component for an editable page tree
......@@ -36,6 +37,8 @@ const toolbarComponentName: string = 'typo3-backend-navigation-component-pagetre
@customElement(navigationComponentName)
export class PageTreeNavigationComponent extends LitElement {
@property({type: String}) mountPointPath: string = null;
// @todo: Migrate svg-tree-wrapper into a custom element
@query('.svg-tree-wrapper') treeWrapper: HTMLElement;
......@@ -73,6 +76,7 @@ export class PageTreeNavigationComponent extends LitElement {
<typo3-backend-navigation-component-pagetree-toolbar .tree="${this.tree}"></typo3-backend-navigation-component-pagetree-toolbar>
</div>
<div id="typo3-pagetree-treeContainer" class="navigation-tree-container">
${this.renderMountPoint()}
<div id="typo3-pagetree-tree" class="svg-tree-wrapper">
<div class="node-loader">
<typo3-backend-icon identifier="spinner-circle-light" size="small"></typo3-backend-icon>
......@@ -99,13 +103,14 @@ export class PageTreeNavigationComponent extends LitElement {
showIcons: true
});
const dragDrop = new PageTreeDragDrop(this.tree);
// both toolbar and tree are loaded independently through require js,
// so we don't know which is loaded first
// in case of toolbar being loaded first, we wait for an event from svgTree
// Initialize the toolbar once the tree was rendered
this.treeWrapper.addEventListener('svg-tree:initialized', () => {
// set up toolbar now with updated settings
const toolbar = this.querySelector(toolbarComponentName) as Toolbar;
toolbar.requestUpdate('tree').then(() => toolbar.initializeDragDrop(dragDrop));
if (configuration.temporaryMountPoint) {
this.mountPointPath = configuration.temporaryMountPoint;
}
});
this.tree.initialize(this.treeWrapper, configuration, dragDrop);
});
......@@ -116,7 +121,7 @@ export class PageTreeNavigationComponent extends LitElement {
}
private setMountPoint = (e: CustomEvent): void => {
this.tree.setTemporaryMountPoint(e.detail.pageId as number);
this.setTemporaryMountPoint(e.detail.pageId as number);
}
private selectFirstNode = (): void => {
......@@ -125,6 +130,48 @@ export class PageTreeNavigationComponent extends LitElement {
this.tree.selectNode(node);
}
}
private unsetTemporaryMountPoint() {
this.mountPointPath = null;
Persistent.unset('pageTree_temporaryMountPoint').then(() => {
this.tree.refreshTree();
});
}
private renderMountPoint(): TemplateResult {
if (this.mountPointPath === null) {
return html``;
}
return html`
<div class="node-mount-point">
<div class="node-mount-point__icon"><typo3-backend-icon identifier="actions-document-info" size="small"></typo3-backend-icon></div>
<div class="node-mount-point__text">${this.mountPointPath}</div>
<div class="node-mount-point__icon mountpoint-close" @click="${() => this.unsetTemporaryMountPoint()}" title="${lll('labels.temporaryDBmount')}">
<typo3-backend-icon identifier="actions-close" size="small"></typo3-backend-icon>
</div>
</div>
`;
}
private setTemporaryMountPoint(pid: number): void {
(new AjaxRequest(top.TYPO3.settings.ajaxUrls.page_tree_set_temporary_mount_point))
.post('pid=' + pid, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest'},
})
.then((response) => response.resolve())
.then((response) => {
if (response && response.hasErrors) {
this.tree.errorNotification(response.message, true);
this.tree.update();
} else {
this.mountPointPath = response.mountPointPath;
this.tree.refreshOrFilterTree();
}
})
.catch((error) => {
this.tree.errorNotification(error, true);
});
}
}
@customElement(toolbarComponentName)
......
......@@ -10,4 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,i,o){void 0===o&&(o=i),Object.defineProperty(e,o,{enumerable:!0,get:function(){return t[i]}})}:function(e,t,i,o){void 0===o&&(o=i),e[o]=t[i]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&__createBinding(t,e,i);return __setModuleDefault(t,e),t},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","d3-selection","TYPO3/CMS/Core/Ajax/AjaxRequest","../SvgTree","./PageTreeDragDrop","../Icons","../ContextMenu","../Storage/Persistent","../Enum/KeyTypes"],(function(e,t,i,o,r,s,n,d,a,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PageTree=void 0,i=__importStar(i),o=__importDefault(o),a=__importDefault(a);class h extends r.SvgTree{constructor(){super(),this.networkErrorTitle=TYPO3.lang.pagetree_networkErrorTitle,this.networkErrorMessage=TYPO3.lang.pagetree_networkErrorDesc,this.searchQuery="",this.originalNodes="",this.settings.defaultProperties={hasChildren:!1,nameSourceField:"title",itemType:"pages",prefix:"",suffix:"",locked:!1,loaded:!1,overlayIcon:"",selectable:!0,expanded:!1,checked:!1,backgroundColor:"",stopPageTree:!1,class:"",readableRootline:"",isMountPoint:!1}}initialize(e,t,i){return!!super.initialize(e,t)&&(this.dispatch.on("nodeSelectedAfter.pageTree",e=>this.nodeSelectedAfter(e)),this.dispatch.on("nodeRightClick.pageTree",e=>this.nodeRightClick(e)),this.dispatch.on("prepareLoadedNode.pageTree",e=>this.prepareLoadedNode(e)),this.dragDrop=i,this.settings.temporaryMountPoint&&this.addMountPoint(this.settings.temporaryMountPoint),!0)}sendChangeCommand(e){let t="",i=0;e.target&&(i=e.target.identifier,"after"===e.position&&(i=-i)),"new"===e.command?t="&data[pages][NEW_1][pid]="+i+"&data[pages][NEW_1][title]="+encodeURIComponent(e.name)+"&data[pages][NEW_1][doktype]="+e.type:"edit"===e.command?t="&data[pages]["+e.uid+"]["+e.nameSourceField+"]="+encodeURIComponent(e.title):"delete"===e.command?(e.uid===window.fsMod.recentIds.web&&this.selectNode(this.nodes[0]),t="&cmd[pages]["+e.uid+"][delete]=1"):t="cmd[pages]["+e.uid+"]["+e.command+"]="+i,this.nodesAddPlaceholder(),new o.default(top.TYPO3.settings.ajaxUrls.record_process).post(t,{headers:{"Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"}}).then(e=>e.resolve()).then(e=>{e&&e.hasErrors?(this.errorNotification(e.messages,!1),this.nodesContainer.selectAll(".node").remove(),this.update(),this.nodesRemovePlaceholder()):this.refreshOrFilterTree()}).catch(e=>{this.errorNotification(e)})}nodeRightClick(e){d.show(e.itemType,parseInt(e.identifier,10),"tree","","",this.getNodeElement(e))}prepareLoadedNode(e){e.stateIdentifier===top.window.fsMod.navFrameHighlightedID.web&&(e.checked=!0)}hideChildren(e){super.hideChildren(e),a.default.set("BackendComponents.States.Pagetree.stateHash."+e.stateIdentifier,"0")}showChildren(e){this.loadChildrenOfNode(e),super.showChildren(e),a.default.set("BackendComponents.States.Pagetree.stateHash."+e.stateIdentifier,"1")}updateNodeBgClass(e){return super.updateNodeBgClass.call(this,e).call(this.initializeDragForNode())}nodesUpdate(e){return(e=super.nodesUpdate.call(this,e).call(this.initializeDragForNode())).append("text").text("+").attr("class","node-stop").attr("dx",30).attr("dy",5).attr("visibility",e=>e.stopPageTree&&0!==e.depth?"visible":"hidden").on("click",(e,t)=>this.setTemporaryMountPoint(parseInt(t.identifier,10))),e}selectNode(e){this.isNodeSelectable(e)&&(this.disableSelectedNodes(),e.checked=!0,this.dispatch.call("nodeSelectedAfter",this,e),this.update())}refreshOrFilterTree(e){"string"==typeof e&&(this.searchQuery=e),""!==this.searchQuery?this.filterTree():this.refreshTree()}resetFilter(){if(this.searchQuery="",this.originalNodes.length>0){let e=this.getSelectedNodes()[0];if(void 0===e)return void this.refreshTree();this.nodes=JSON.parse(this.originalNodes),this.originalNodes="";const t=this.nodes.find(t=>t.stateIdentifier===e.stateIdentifier);t?this.selectNode(t):this.refreshTree()}else this.refreshTree();this.prepareDataForVisibleNodes(),this.update()}switchFocusNode(e){this.nodeIsEdit||this.switchFocus(this.getNodeElement(e))}setTemporaryMountPoint(e){const t="pid="+e;new o.default(top.TYPO3.settings.ajaxUrls.page_tree_set_temporary_mount_point).post(t,{headers:{"Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"}}).then(e=>e.resolve()).then(e=>{e&&e.hasErrors?(this.errorNotification(e.message,!0),this.update()):(this.addMountPoint(e.mountPointPath),this.refreshOrFilterTree())}).catch(e=>{this.errorNotification(e,!0)})}unsetTemporaryMountPoint(){a.default.unset("pageTree_temporaryMountPoint").then(()=>{this.refreshTree()})}initializeDragForNode(){return this.dragDrop.connectDragHandler(new s.PageTreeNodeDragHandler(this,this.dragDrop))}removeEditedText(){const e=i.selectAll(".node-edit");if(e.size())try{e.remove(),this.nodeIsEdit=!1}catch(e){}}filterTree(){this.nodesAddPlaceholder(),new o.default(this.settings.filterUrl+"&q="+this.searchQuery).get({cache:"no-cache"}).then(e=>e.resolve()).then(e=>{let t=Array.isArray(e)?e:[];t.length>0&&(""===this.originalNodes&&(this.originalNodes=JSON.stringify(this.nodes)),this.replaceData(t)),this.nodesRemovePlaceholder()}).catch(e=>{throw this.errorNotification(e,!1),this.nodesRemovePlaceholder(),e})}loadChildrenOfNode(e){e.loaded||(this.nodesAddPlaceholder(),new o.default(this.settings.dataUrl+"&pid="+e.identifier+"&mount="+e.mountPoint+"&pidDepth="+e.depth).get({cache:"no-cache"}).then(e=>e.resolve()).then(t=>{let i=Array.isArray(t)?t:[];i.shift();const o=this.nodes.indexOf(e)+1;i.forEach((e,t)=>{this.nodes.splice(o+t,0,e)}),e.loaded=!0,this.setParametersNode(),this.prepareDataForVisibleNodes(),this.update(),this.nodesRemovePlaceholder(),this.switchFocusNode(e)}).catch(e=>{throw this.errorNotification(e,!1),this.nodesRemovePlaceholder(),e}))}nodeSelectedAfter(e){if(!e.checked)return;top.window.fsMod.recentIds.web=e.identifier,top.window.fsMod.currentBank=e.stateIdentifier.split("_")[0],top.window.fsMod.navFrameHighlightedID.web=e.stateIdentifier;let t="?";-1!==top.window.currentSubScript.indexOf("?")&&(t="&"),top.TYPO3.Backend.ContentContainer.setUrl(top.window.currentSubScript+t+"id="+e.identifier)}appendTextElement(e){let t=0;return super.appendTextElement(e).attr("dx",e=>{let t=this.textPosition;return e.stopPageTree&&0!==e.depth&&(t+=15),e.locked&&(t+=15),t}).on("click",(e,i)=>{"0"!==i.identifier?1==++t&&setTimeout(()=>{1===t?this.selectNode(i):this.editNodeLabel(i),t=0},300):this.selectNode(i)})}sendEditNodeLabelCommand(e){const t="&data[pages]["+e.identifier+"]["+e.nameSourceField+"]="+encodeURIComponent(e.newName);this.nodesAddPlaceholder(e),new o.default(top.TYPO3.settings.ajaxUrls.record_process).post(t,{headers:{"Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"}}).then(e=>e.resolve()).then(t=>{t&&t.hasErrors?this.errorNotification(t.messages,!1):e.name=e.newName,this.refreshOrFilterTree()}).catch(e=>{this.errorNotification(e,!0)})}editNodeLabel(e){e.allowEdit&&(this.removeEditedText(),this.nodeIsEdit=!0,i.select(this.svg.node().parentNode).append("input").attr("class","node-edit").style("top",()=>e.y+this.settings.marginTop+"px").style("left",e.x+this.textPosition+5+"px").style("width",this.settings.width-(e.x+this.textPosition+20)+"px").style("height",this.settings.nodeHeight+"px").attr("type","text").attr("value",e.name).on("keydown",t=>{const i=t.keyCode;if(i===l.KeyTypesEnum.ENTER||i===l.KeyTypesEnum.TAB){const i=t.target.value.trim();this.nodeIsEdit=!1,this.removeEditedText(),i.length&&i!==e.name&&(e.nameSourceField=e.nameSourceField||"title",e.newName=i,this.sendEditNodeLabelCommand(e))}else i===l.KeyTypesEnum.ESCAPE&&(this.nodeIsEdit=!1,this.removeEditedText())}).on("blur",t=>{if(!this.nodeIsEdit)return;const i=t.target.value.trim();i.length&&i!==e.name&&(e.nameSourceField=e.nameSourceField||"title",e.newName=i,this.sendEditNodeLabelCommand(e)),this.removeEditedText()}).node().select())}addMountPoint(e){let t=this.wrapper.parentNode.querySelector(".node-mount-point");t&&t.parentNode.removeChild(t),this.wrapper.insertAdjacentHTML("beforebegin",'<div class="node-mount-point"><div class="node-mount-point__icon" data-tree-icon="actions-document-info"></div><div class="node-mount-point__text"><div>'+e+'</div></div><div class="node-mount-point__icon" data-tree-icon="actions-close" title="'+TYPO3.lang["labels.temporaryDBmount"]+'"></div></div>'),this.wrapper.parentNode.querySelector("[data-tree-icon=actions-close]").addEventListener("click",()=>{this.unsetTemporaryMountPoint(),this.wrapper.parentNode.querySelector(".node-mount-point").remove()}),this.wrapper.parentNode.querySelectorAll(".node-mount-point [data-tree-icon]").forEach(e=>{n.getIcon(e.dataset.treeIcon,n.sizes.small,null,null,"inline").then(t=>{e.insertAdjacentHTML("beforeend",t)})})}}t.PageTree=h}));
\ No newline at end of file
var __createBinding=this&&this.__createBinding||(Object.create?function(e,t,i,s){void 0===s&&(s=i),Object.defineProperty(e,s,{enumerable:!0,get:function(){return t[i]}})}:function(e,t,i,s){void 0===s&&(s=i),e[s]=t[i]}),__setModuleDefault=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),__importStar=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)"default"!==i&&Object.prototype.hasOwnProperty.call(e,i)&&__createBinding(t,e,i);return __setModuleDefault(t,e),t},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","d3-selection","TYPO3/CMS/Core/Ajax/AjaxRequest","../SvgTree","./PageTreeDragDrop","../ContextMenu","../Storage/Persistent","../Enum/KeyTypes"],(function(e,t,i,s,r,o,d,n,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PageTree=void 0,i=__importStar(i),s=__importDefault(s),n=__importDefault(n);class l extends r.SvgTree{constructor(){super(),this.networkErrorTitle=TYPO3.lang.pagetree_networkErrorTitle,this.networkErrorMessage=TYPO3.lang.pagetree_networkErrorDesc,this.searchQuery="",this.originalNodes="",this.settings.defaultProperties={hasChildren:!1,nameSourceField:"title",itemType:"pages",prefix:"",suffix:"",locked:!1,loaded:!1,overlayIcon:"",selectable:!0,expanded:!1,checked:!1,backgroundColor:"",stopPageTree:!1,class:"",readableRootline:"",isMountPoint:!1}}initialize(e,t,i){return!!super.initialize(e,t)&&(this.dispatch.on("nodeSelectedAfter.pageTree",e=>this.nodeSelectedAfter(e)),this.dispatch.on("nodeRightClick.pageTree",e=>this.nodeRightClick(e)),this.dispatch.on("prepareLoadedNode.pageTree",e=>this.prepareLoadedNode(e)),this.dragDrop=i,!0)}sendChangeCommand(e){let t="",i=0;e.target&&(i=e.target.identifier,"after"===e.position&&(i=-i)),"new"===e.command?t="&data[pages][NEW_1][pid]="+i+"&data[pages][NEW_1][title]="+encodeURIComponent(e.name)+"&data[pages][NEW_1][doktype]="+e.type:"edit"===e.command?t="&data[pages]["+e.uid+"]["+e.nameSourceField+"]="+encodeURIComponent(e.title):"delete"===e.command?(e.uid===window.fsMod.recentIds.web&&this.selectNode(this.nodes[0]),t="&cmd[pages]["+e.uid+"][delete]=1"):t="cmd[pages]["+e.uid+"]["+e.command+"]="+i,this.nodesAddPlaceholder(),new s.default(top.TYPO3.settings.ajaxUrls.record_process).post(t,{headers:{"Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"}}).then(e=>e.resolve()).then(e=>{e&&e.hasErrors?(this.errorNotification(e.messages,!1),this.nodesContainer.selectAll(".node").remove(),this.update(),this.nodesRemovePlaceholder()):this.refreshOrFilterTree()}).catch(e=>{this.errorNotification(e)})}nodeRightClick(e){d.show(e.itemType,parseInt(e.identifier,10),"tree","","",this.getNodeElement(e))}prepareLoadedNode(e){e.stateIdentifier===top.window.fsMod.navFrameHighlightedID.web&&(e.checked=!0)}hideChildren(e){super.hideChildren(e),n.default.set("BackendComponents.States.Pagetree.stateHash."+e.stateIdentifier,"0")}showChildren(e){this.loadChildrenOfNode(e),super.showChildren(e),n.default.set("BackendComponents.States.Pagetree.stateHash."+e.stateIdentifier,"1")}updateNodeBgClass(e){return super.updateNodeBgClass.call(this,e).call(this.initializeDragForNode())}nodesUpdate(e){return(e=super.nodesUpdate.call(this,e).call(this.initializeDragForNode())).append("text").text("+").attr("class","node-stop").attr("dx",30).attr("dy",5).attr("visibility",e=>e.stopPageTree&&0!==e.depth?"visible":"hidden").on("click",(e,t)=>{document.dispatchEvent(new CustomEvent("typo3:pagetree:mountPoint",{detail:{pageId:parseInt(t.identifier,10)}}))}),e}selectNode(e){this.isNodeSelectable(e)&&(this.disableSelectedNodes(),e.checked=!0,this.dispatch.call("nodeSelectedAfter",this,e),this.update())}refreshOrFilterTree(e){"string"==typeof e&&(this.searchQuery=e),""!==this.searchQuery?this.filterTree():this.refreshTree()}resetFilter(){if(this.searchQuery="",this.originalNodes.length>0){let e=this.getSelectedNodes()[0];if(void 0===e)return void this.refreshTree();this.nodes=JSON.parse(this.originalNodes),this.originalNodes="";const t=this.nodes.find(t=>t.stateIdentifier===e.stateIdentifier);t?this.selectNode(t):this.refreshTree()}else this.refreshTree();this.prepareDataForVisibleNodes(),this.update()}switchFocusNode(e){this.nodeIsEdit||this.switchFocus(this.getNodeElement(e))}initializeDragForNode(){return this.dragDrop.connectDragHandler(new o.PageTreeNodeDragHandler(this,this.dragDrop))}removeEditedText(){const e=i.selectAll(".node-edit");if(e.size())try{e.remove(),this.nodeIsEdit=!1}catch(e){}}filterTree(){this.nodesAddPlaceholder(),new s.default(this.settings.filterUrl+"&q="+this.searchQuery).get({cache:"no-cache"}).then(e=>e.resolve()).then(e=>{let t=Array.isArray(e)?e:[];t.length>0&&(""===this.originalNodes&&(this.originalNodes=JSON.stringify(this.nodes)),this.replaceData(t)),this.nodesRemovePlaceholder()}).catch(e=>{throw this.errorNotification(e,!1),this.nodesRemovePlaceholder(),e})}loadChildrenOfNode(e){e.loaded||(this.nodesAddPlaceholder(),new s.default(this.settings.dataUrl+"&pid="+e.identifier+"&mount="+e.mountPoint+"&pidDepth="+e.depth).get({cache:"no-cache"}).then(e=>e.resolve()).then(t=>{let i=Array.isArray(t)?t:[];i.shift();const s=this.nodes.indexOf(e)+1;i.forEach((e,t)=>{this.nodes.splice(s+t,0,e)}),e.loaded=!0,this.setParametersNode(),this.prepareDataForVisibleNodes(),this.update(),this.nodesRemovePlaceholder(),this.switchFocusNode(e)}).catch(e=>{throw this.errorNotification(e,!1),this.nodesRemovePlaceholder(),e}))}nodeSelectedAfter(e){if(!e.checked)return;top.window.fsMod.recentIds.web=e.identifier,top.window.fsMod.currentBank=e.stateIdentifier.split("_")[0],top.window.fsMod.navFrameHighlightedID.web=e.stateIdentifier;let t="?";-1!==top.window.currentSubScript.indexOf("?")&&(t="&"),top.TYPO3.Backend.ContentContainer.setUrl(top.window.currentSubScript+t+"id="+e.identifier)}appendTextElement(e){let t=0;return super.appendTextElement(e).attr("dx",e=>{let t=this.textPosition;return e.stopPageTree&&0!==e.depth&&(t+=15),e.locked&&(t+=15),t}).on("click",(e,i)=>{"0"!==i.identifier?1==++t&&setTimeout(()=>{1===t?this.selectNode(i):this.editNodeLabel(i),t=0},300):this.selectNode(i)})}sendEditNodeLabelCommand(e){const t="&data[pages]["+e.identifier+"]["+e.nameSourceField+"]="+encodeURIComponent(e.newName);this.nodesAddPlaceholder(e),new s.default(top.TYPO3.settings.ajaxUrls.record_process).post(t,{headers:{"Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"}}).then(e=>e.resolve()).then(t=>{t&&t.hasErrors?this.errorNotification(t.messages,!1):e.name=e.newName,this.refreshOrFilterTree()}).catch(e=>{this.errorNotification(e,!0)})}editNodeLabel(e){e.allowEdit&&(this.removeEditedText(),this.nodeIsEdit=!0,i.select(this.svg.node().parentNode).append("input").attr("class","node-edit").style("top",()=>e.y+this.settings.marginTop+"px").style("left",e.x+this.textPosition+5+"px").style("width",this.settings.width-(e.x+this.textPosition+20)+"px").style("height",this.settings.nodeHeight+"px").attr("type","text").attr("value",e.name).on("keydown",t=>{const i=t.keyCode;if(i===a.KeyTypesEnum.ENTER||i===a.KeyTypesEnum.TAB){const i=t.target.value.trim();this.nodeIsEdit=!1,this.removeEditedText(),i.length&&i!==e.name&&(e.nameSourceField=e.nameSourceField||"title",e.newName=i,this.sendEditNodeLabelCommand(e))}else i===a.KeyTypesEnum.ESCAPE&&(this.nodeIsEdit=!1,this.removeEditedText())}).on("blur",t=>{if(!this.nodeIsEdit)return;const i=t.target.value.trim();i.length&&i!==e.name&&(e.nameSourceField=e.nameSourceField||"title",e.newName=i,this.sendEditNodeLabelCommand(e)),this.removeEditedText()}).node().select())}}t.PageTree=l}));
\ No newline at end of file
......@@ -10,13 +10,14 @@
*
* The TYPO3 project - inspiring people to share!
*/
var __decorate=this&&this.__decorate||function(e,t,r,i){var o,n=arguments.length,s=n<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,r):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,i);else for(var a=e.length-1;a>=0;a--)(o=e[a])&&(s=(n<3?o(s):n>3?o(t,r,s):o(t,r))||s);return n>3&&s&&Object.defineProperty(t,r,s),s},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","lit-element","TYPO3/CMS/Core/lit-helper","./PageTree","./PageTreeDragDrop","TYPO3/CMS/Core/Ajax/AjaxRequest","d3-selection","TYPO3/CMS/Core/Event/DebounceEvent","TYPO3/CMS/Backend/Element/IconElement"],(function(e,t,r,i,o,n,s,a,l){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PageTreeNavigationComponent=t.navigationComponentName=void 0,s=__importDefault(s),l=__importDefault(l),t.navigationComponentName="typo3-backend-navigation-component-pagetree";let c=class extends r.LitElement{constructor(){super(),this.tree=null,this.refresh=()=>{this.tree.refreshOrFilterTree()},this.setMountPoint=e=>{this.tree.setTemporaryMountPoint(e.detail.pageId)},this.selectFirstNode=()=>{const e=this.tree.nodes[0];e&&this.tree.selectNode(e)},this.tree=new o.PageTree}connectedCallback(){super.connectedCallback(),document.addEventListener("typo3:pagetree:refresh",this.refresh),document.addEventListener("typo3:pagetree:mountPoint",this.setMountPoint),document.addEventListener("typo3:pagetree:selectFirstNode",this.selectFirstNode)}disconnectedCallback(){document.removeEventListener("typo3:pagetree:refresh",this.refresh),document.removeEventListener("typo3:pagetree:mountPoint",this.setMountPoint),document.removeEventListener("typo3:pagetree:selectFirstNode",this.selectFirstNode),super.disconnectedCallback()}createRenderRoot(){return this}render(){return r.html`
var __decorate=this&&this.__decorate||function(e,t,r,o){var i,n=arguments.length,s=n<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,r):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,r,o);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(n<3?i(s):n>3?i(t,r,s):i(t,r))||s);return n>3&&s&&Object.defineProperty(t,r,s),s},__importDefault=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};define(["require","exports","lit-element","TYPO3/CMS/Core/lit-helper","./PageTree","./PageTreeDragDrop","TYPO3/CMS/Core/Ajax/AjaxRequest","d3-selection","TYPO3/CMS/Core/Event/DebounceEvent","TYPO3/CMS/Backend/Storage/Persistent","TYPO3/CMS/Backend/Element/IconElement"],(function(e,t,r,o,i,n,s,a,l,d){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.PageTreeNavigationComponent=t.navigationComponentName=void 0,s=__importDefault(s),l=__importDefault(l),d=__importDefault(d),t.navigationComponentName="typo3-backend-navigation-component-pagetree";let c=class extends r.LitElement{constructor(){super(),this.mountPointPath=null,this.tree=null,this.refresh=()=>{this.tree.refreshOrFilterTree()},this.setMountPoint=e=>{this.setTemporaryMountPoint(e.detail.pageId)},this.selectFirstNode=()=>{const e=this.tree.nodes[0];e&&this.tree.selectNode(e)},this.tree=new i.PageTree}connectedCallback(){super.connectedCallback(),document.addEventListener("typo3:pagetree:refresh",this.refresh),document.addEventListener("typo3:pagetree:mountPoint",this.setMountPoint),document.addEventListener("typo3:pagetree:selectFirstNode",this.selectFirstNode)}disconnectedCallback(){document.removeEventListener("typo3:pagetree:refresh",this.refresh),document.removeEventListener("typo3:pagetree:mountPoint",this.setMountPoint),document.removeEventListener("typo3:pagetree:selectFirstNode",this.selectFirstNode),super.disconnectedCallback()}createRenderRoot(){return this}render(){return r.html`
<div id="typo3-pagetree" class="svg-tree">
<div>
<div id="typo3-pagetree-toolbar" class="svg-toolbar">
<typo3-backend-navigation-component-pagetree-toolbar .tree="${this.tree}"></typo3-backend-navigation-component-pagetree-toolbar>
</div>
<div id="typo3-pagetree-treeContainer" class="navigation-tree-container">
${this.renderMountPoint()}
<div id="typo3-pagetree-tree" class="svg-tree-wrapper">
<div class="node-loader">
<typo3-backend-icon identifier="spinner-circle-light" size="small"></typo3-backend-icon>
......@@ -28,13 +29,21 @@ var __decorate=this&&this.__decorate||function(e,t,r,i){var o,n=arguments.length
<typo3-backend-icon identifier="spinner-circle-light" size="large"></typo3-backend-icon>
</div>
</div>
`}firstUpdated(){this.treeWrapper.dispatchEvent(new Event("svg-tree:visible"));const e=top.TYPO3.settings.ajaxUrls.page_tree_configuration;new s.default(e).get().then(async e=>{const t=await e.resolve("json");Object.assign(t,{dataUrl:top.TYPO3.settings.ajaxUrls.page_tree_data,filterUrl:top.TYPO3.settings.ajaxUrls.page_tree_filter,showIcons:!0});const r=new n.PageTreeDragDrop(this.tree);this.treeWrapper.addEventListener("svg-tree:initialized",()=>{const e=this.querySelector("typo3-backend-navigation-component-pagetree-toolbar");e.requestUpdate("tree").then(()=>e.initializeDragDrop(r))}),this.tree.initialize(this.treeWrapper,t,r)})}};__decorate([r.query(".svg-tree-wrapper")],c.prototype,"treeWrapper",void 0),c=__decorate([r.customElement(t.navigationComponentName)],c),t.PageTreeNavigationComponent=c;let d=class extends r.LitElement{constructor(){super(...arguments),this.tree=null,this.settings={searchInput:".search-input",filterTimeout:450}}initializeDragDrop(e){var t,r;(null===(r=null===(t=this.tree.settings)||void 0===t?void 0:t.doktypes)||void 0===r?void 0:r.length)&&this.tree.settings.doktypes.forEach(t=>{if(t.icon){const r=this.querySelector('[data-tree-icon="'+t.icon+'"]');a.select(r).call(this.dragToolbar(t,e))}else console.warn("Missing icon definition for doktype: "+t.nodeType)})}createRenderRoot(){return this}firstUpdated(){const e=this.querySelector(this.settings.searchInput);e&&(new l.default("input",e=>{this.search(e.target)},this.settings.filterTimeout).bindTo(e),e.focus(),e.clearable({onClear:()=>{this.tree.resetFilter(),this.tree.prepareDataForVisibleNodes(),this.tree.update()}}))}render(){var e,t;return r.html`
`}firstUpdated(){this.treeWrapper.dispatchEvent(new Event("svg-tree:visible"));const e=top.TYPO3.settings.ajaxUrls.page_tree_configuration;new s.default(e).get().then(async e=>{const t=await e.resolve("json");Object.assign(t,{dataUrl:top.TYPO3.settings.ajaxUrls.page_tree_data,filterUrl:top.TYPO3.settings.ajaxUrls.page_tree_filter,showIcons:!0});const r=new n.PageTreeDragDrop(this.tree);this.treeWrapper.addEventListener("svg-tree:initialized",()=>{const e=this.querySelector("typo3-backend-navigation-component-pagetree-toolbar");e.requestUpdate("tree").then(()=>e.initializeDragDrop(r)),t.temporaryMountPoint&&(this.mountPointPath=t.temporaryMountPoint)}),this.tree.initialize(this.treeWrapper,t,r)})}unsetTemporaryMountPoint(){this.mountPointPath=null,d.default.unset("pageTree_temporaryMountPoint").then(()=>{this.tree.refreshTree()})}renderMountPoint(){return null===this.mountPointPath?r.html``:r.html`
<div class="node-mount-point">
<div class="node-mount-point__icon"><typo3-backend-icon identifier="actions-document-info" size="small"></typo3-backend-icon></div>
<div class="node-mount-point__text">${this.mountPointPath}</div>
<div class="node-mount-point__icon mountpoint-close" @click="${()=>this.unsetTemporaryMountPoint()}" title="${o.lll("labels.temporaryDBmount")}">
<typo3-backend-icon identifier="actions-close" size="small"></typo3-backend-icon>
</div>
</div>
`}setTemporaryMountPoint(e){new s.default(top.TYPO3.settings.ajaxUrls.page_tree_set_temporary_mount_point).post("pid="+e,{headers:{"Content-Type":"application/x-www-form-urlencoded","X-Requested-With":"XMLHttpRequest"}}).then(e=>e.resolve()).then(e=>{e&&e.hasErrors?(this.tree.errorNotification(e.message,!0),this.tree.update()):(this.mountPointPath=e.mountPointPath,this.tree.refreshOrFilterTree())}).catch(e=>{this.tree.errorNotification(e,!0)})}};__decorate([r.property({type:String})],c.prototype,"mountPointPath",void 0),__decorate([r.query(".svg-tree-wrapper")],c.prototype,"treeWrapper",void 0),c=__decorate([r.customElement(t.navigationComponentName)],c),t.PageTreeNavigationComponent=c;let p=class extends r.LitElement{constructor(){super(...arguments),this.tree=null,this.settings={searchInput:".search-input",filterTimeout:450}}initializeDragDrop(e){var t,r;(null===(r=null===(t=this.tree.settings)||void 0===t?void 0:t.doktypes)||void 0===r?void 0:r.length)&&this.tree.settings.doktypes.forEach(t=>{if(t.icon){const r=this.querySelector('[data-tree-icon="'+t.icon+'"]');a.select(r).call(this.dragToolbar(t,e))}else console.warn("Missing icon definition for doktype: "+t.nodeType)})}createRenderRoot(){return this}firstUpdated(){const e=this.querySelector(this.settings.searchInput);e&&(new l.default("input",e=>{this.search(e.target)},this.settings.filterTimeout).bindTo(e),e.focus(),e.clearable({onClear:()=>{this.tree.resetFilter(),this.tree.prepareDataForVisibleNodes(),this.tree.update()}}))}render(){var e,t;return r.html`
<div class="tree-toolbar">
<div class="svg-toolbar__menu">
<div class="svg-toolbar__search">
<input type="text" class="form-control form-control-sm search-input" placeholder="${i.lll("tree.searchTermInfo")}">
<input type="text" class="form-control form-control-sm search-input" placeholder="${o.lll("tree.searchTermInfo")}">
</div>
<button class="btn btn-default btn-borderless btn-sm" @click="${()=>this.refreshTree()}" data-tree-icon="actions-refresh" title="${i.lll("labels.refresh")}">
<button class="btn btn-default btn-borderless btn-sm" @click="${()=>this.refreshTree()}" data-tree-icon="actions-refresh" title="${o.lll("labels.refresh")}">
<typo3-backend-icon identifier="actions-refresh" size="small"></typo3-backend-icon>
</button>
</div>
......@@ -47,4 +56,4 @@ var __decorate=this&&this.__decorate||function(e,t,r,i){var o,n=arguments.length
`):""}
</div>
</div>
`}refreshTree(){this.tree.refreshOrFilterTree()}search(e){this.tree.refreshOrFilterTree(e.value.trim()),this.tree.prepareDataForVisibleNodes(),this.tree.update()}dragToolbar(e,t){return t.connectDragHandler(new n.ToolbarDragHandler(e,this.tree,t))}};__decorate([r.property({type:o.PageTree})],d.prototype,"tree",void 0),d=__decorate([r.customElement("typo3-backend-navigation-component-pagetree-toolbar")],d)}));
\ No newline at end of file
`}refreshTree(){this.tree.refreshOrFilterTree()}search(e){this.tree.refreshOrFilterTree(e.value.trim()),this.tree.prepareDataForVisibleNodes(),this.tree.update()}dragToolbar(e,t){return t.connectDragHandler(new n.ToolbarDragHandler(e,this.tree,t))}};__decorate([r.property({type:i.PageTree})],p.prototype,"tree",void 0),p=__decorate([r.customElement("typo3-backend-navigation-component-pagetree-toolbar")],p)}));
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment