Commit 6c512f2e authored by Andreas Fernandez's avatar Andreas Fernandez Committed by Anja Leichsenring
Browse files

[TASK] Migrate SelectElementTree to TypeScript

This patch migrates FormEngine's SelectElementTree to TypeScript.
Also, a terrible hack that puts the local tree initialitation callback
into global scope has been removed.

Resolves: #87987
Releases: master
Change-Id: Ib34ae7fe4ac1e197af2183b8890cc72e13a900e9
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/60316

Tested-by: default avatarTYPO3com <noreply@typo3.com>
Tested-by: default avatarSteffen Frese <steffenf14@gmail.com>
Tested-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: default avatarSteffen Frese <steffenf14@gmail.com>
Reviewed-by: Frank Nägler's avatarFrank Naegler <frank.naegler@typo3.org>
Reviewed-by: Anja Leichsenring's avatarAnja Leichsenring <aleichsenring@ab-softlab.de>
parent 5afb3940
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
import SelectTree = require('TYPO3/CMS/Backend/FormEngine/Element/SelectTree');
class SelectTreeElement {
private readonly treeWrapper: HTMLElement = null;
private readonly recordField: HTMLInputElement = null;
private readonly callback: Function = null;
constructor(treeWrapperId: string, treeRecordFieldId: string, callback: Function) {
this.treeWrapper = <HTMLElement>document.querySelector('#' + treeWrapperId);
this.recordField = <HTMLInputElement>document.querySelector('#' + treeRecordFieldId);
this.callback = callback;
this.initialize();
}
private initialize(): void {
const dataUrl = this.generateRequestUrl();
const tree = new SelectTree();
const settings = {
dataUrl: dataUrl,
showIcons: true,
showCheckboxes: true,
readOnlyMode: parseInt(this.recordField.dataset.readOnly, 10) === 1,
input: this.recordField,
exclusiveNodesIdentifiers: this.recordField.dataset.treeExclusiveKeys,
validation: JSON.parse(this.recordField.dataset.formengineValidationRules)[0],
expandUpToLevel: this.recordField.dataset.treeExpandUpToLevel,
};
const initialized = tree.initialize(this.treeWrapper, settings);
if (!initialized) {
return;
}
tree.dispatch.on('nodeSelectedAfter.requestUpdate', this.callback);
if (this.recordField.dataset.treeShowToolbar) {
require(['TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar'], (TreeToolbar: any): void => {
const selectTreeToolbar = new TreeToolbar();
selectTreeToolbar.initialize(this.treeWrapper);
});
}
}
private generateRequestUrl(): string {
const params = {
tableName: this.recordField.dataset.tablename,
fieldName: this.recordField.dataset.fieldname,
uid: this.recordField.dataset.uid,
recordTypeValue: this.recordField.dataset.recordtypevalue,
dataStructureIdentifier: this.recordField.dataset.datastructureidentifier !== ''
? JSON.parse(this.recordField.dataset.datastructureidentifier)
: '',
flexFormSheetName: this.recordField.dataset.flexformsheetname,
flexFormFieldName: this.recordField.dataset.flexformfieldname,
flexFormContainerName: this.recordField.dataset.flexformcontainername,
flexFormContainerIdentifier: this.recordField.dataset.flexformcontaineridentifier,
flexFormContainerFieldName: this.recordField.dataset.flexformcontainerfieldname,
flexFormSectionContainerIsNew: this.recordField.dataset.flexformsectioncontainerisnew,
command: this.recordField.dataset.command,
};
return TYPO3.settings.ajaxUrls.record_tree_data + '&' + $.param(params);
}
}
export = SelectTreeElement;
......@@ -16,7 +16,6 @@ declare namespace TYPO3 {
export let Modal: any;
export let OpendocsMenu: any;
export let Permissions: any;
export let Popover: any;
export let Severity: any;
export let ShortcutMenu: any;
export let Storage: any;
......@@ -35,6 +34,16 @@ declare namespace TYPO3 {
public validate(): void;
}
export namespace FormEngine {
export namespace Element {
export class SelectTree {
public dispatch: {[key: string]: Function};
public constructor();
public initialize(selector: HTMLElement|JQuery, settings: {[key: string]: any}): boolean;
}
}
}
export class FormEngine {
public readonly Validation: FormEngineValidation;
public legacyFieldChangedCb(): void;
......@@ -80,6 +89,10 @@ declare module 'TYPO3/CMS/Backend/FormEngine' {
export = new TYPO3.CMS.Backend.FormEngine();
}
declare module 'TYPO3/CMS/Backend/FormEngine/Element/SelectTree' {
export = TYPO3.CMS.Backend.FormEngine.Element.SelectTree;
}
declare module 'TYPO3/CMS/Backend/Wizard' {
export = new TYPO3.CMS.Backend.Wizard();
}
......
......@@ -14,6 +14,8 @@ namespace TYPO3\CMS\Backend\Form\Element;
* The TYPO3 project - inspiring people to share!
*/
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* Render data as a tree.
*
......@@ -78,7 +80,7 @@ class SelectTreeElement extends AbstractFormElement
// Field configuration from TCA:
$config = $parameterArray['fieldConf']['config'];
$readOnly = !empty($config['readOnly']) ? 'true' : 'false';
$readOnly = !empty($config['readOnly']) ? 1 : 0;
$exclusiveKeys = !empty($config['exclusiveKeys']) ? $config['exclusiveKeys'] : '';
$exclusiveKeys = $exclusiveKeys . ',';
$appearance = !empty($config['treeConfig']['appearance']) ? $config['treeConfig']['appearance'] : [];
......@@ -91,6 +93,7 @@ class SelectTreeElement extends AbstractFormElement
}
$heightInPx = $height * $this->itemHeight;
$treeWrapperId = 'tree_' . $formElementId;
$fieldId = 'tree_record_' . $formElementId;
$fieldName = $this->data['fieldName'];
......@@ -140,7 +143,7 @@ class SelectTreeElement extends AbstractFormElement
$html[] = '<div class="form-wizards-wrap">';
$html[] = '<div class="form-wizards-element">';
$html[] = '<div class="typo3-tceforms-tree">';
$html[] = '<input class="treeRecord" type="hidden"';
$html[] = '<input class="treeRecord" type="hidden" id="' . htmlspecialchars($fieldId) . '"';
$html[] = ' data-formengine-validation-rules="' . htmlspecialchars($this->getValidationDataAsJsonString($config)) . '"';
$html[] = ' data-relatedfieldname="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
$html[] = ' data-tablename="' . htmlspecialchars($this->data['tableName']) . '"';
......@@ -165,7 +168,6 @@ class SelectTreeElement extends AbstractFormElement
$html[] = '/>';
$html[] = '</div>';
$html[] = '<div id="' . $treeWrapperId . '" class="svg-tree-wrapper" style="height: ' . $heightInPx . 'px;"></div>';
$html[] = '<script type="text/javascript">var ' . $treeWrapperId . ' = ' . $this->getTreeOnChangeJs() . '</script>';
$html[] = '</div>';
if ($readOnly === 'false' && !empty($fieldWizardHtml)) {
$html[] = '<div class="form-wizards-items-bottom">';
......@@ -182,8 +184,14 @@ class SelectTreeElement extends AbstractFormElement
if ($showHeader) {
$resultArray['additionalInlineLanguageLabelFiles'][] = 'EXT:core/Resources/Private/Language/locallang_csh_corebe.xlf';
}
$resultArray['requireJsModules']['selectTreeElement'] = [
'TYPO3/CMS/Backend/FormEngine/Element/SelectTreeElement' => 'function (SelectTreeElement) { SelectTreeElement.initialize(); }'
$resultArray['requireJsModules']['selectTreeElement'] = ['TYPO3/CMS/Backend/FormEngine/Element/SelectTreeElement' => '
function(SelectTreeElement) {
require([\'jquery\'], function($) {
$(function() {
new SelectTreeElement(' . GeneralUtility::quoteJSvalue($treeWrapperId) . ', ' . GeneralUtility::quoteJSvalue($fieldId) . ', ' . $this->getTreeOnChangeJs() . ');
});
});
}'
];
return $resultArray;
......
......@@ -193,9 +193,9 @@ define(['d3', 'TYPO3/CMS/Backend/SvgTree', 'TYPO3/CMS/Backend/FormEngine'],
SelectTree.prototype.saveCheckboxes = function() {
if (typeof this.settings.input !== 'undefined') {
var selectedNodes = this.getSelectedNodes();
this.settings.input.val(selectedNodes.map(function(d) {
this.settings.input.value = selectedNodes.map(function(d) {
return d.identifier;
}));
});
}
};
......
......@@ -10,69 +10,4 @@
*
* The TYPO3 project - inspiring people to share!
*/
/**
* Initialization of the selectTree js component used e.g. for category tree rendering
*/
define(['jquery', 'TYPO3/CMS/Backend/FormEngine/Element/SelectTree'],
function($, SelectTree) {
'use strict';
var SelectTreeElement = {};
SelectTreeElement.initialize = function() {
$(document).ready(function() {
$('.typo3-tceforms-tree .treeRecord').each(function(i, element) {
/**
* Hidden input field storing selected elements.
* Tree is initialized based on values stored in it's data attributes
*
* @type {*|jQuery|HTMLElement}
*/
var $treeInput = $(element);
var dataParams = {
tableName: $treeInput.data('tablename'),
fieldName: $treeInput.data('fieldname'),
uid: $treeInput.data('uid'),
recordTypeValue: $treeInput.data('recordtypevalue'),
dataStructureIdentifier: $treeInput.data('datastructureidentifier'),
flexFormSheetName: $treeInput.data('flexformsheetname'),
flexFormFieldName: $treeInput.data('flexformfieldname'),
flexFormContainerName: $treeInput.data('flexformcontainername'),
flexFormContainerIdentifier: $treeInput.data('flexformcontaineridentifier'),
flexFormContainerFieldName: $treeInput.data('flexformcontainerfieldname'),
flexFormSectionContainerIsNew: $treeInput.data('flexformsectioncontainerisnew'),
command: $treeInput.data('command')
};
var $wrapper = $treeInput.parent().siblings('.svg-tree-wrapper');
var dataUrl = TYPO3.settings.ajaxUrls.record_tree_data + '&' + $.param(dataParams);
var tree = new SelectTree();
var initialized = tree.initialize($wrapper, {
dataUrl: dataUrl,
showIcons: true,
showCheckboxes: true,
readOnlyMode: $treeInput.data('read-only'),
input: $treeInput,
exclusiveNodesIdentifiers: $treeInput.data('tree-exclusive-keys'),
validation: $treeInput.data('formengine-validation-rules')[0],
expandUpToLevel: $treeInput.data('tree-expand-up-to-level')
});
if (!initialized) {
return;
}
tree.dispatch.on('nodeSelectedAfter.requestUpdate', window[$wrapper.attr('id')]);
if ($treeInput.data('tree-show-toolbar')) {
require(['TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar'], function(TreeToolbar) {
var selectTreeToolbar = new TreeToolbar();
selectTreeToolbar.initialize($wrapper);
});
}
});
});
};
return SelectTreeElement;
});
define(["require","exports","TYPO3/CMS/Backend/FormEngine/Element/SelectTree"],function(e,t,r){"use strict";return function(){function t(e,t,r){this.treeWrapper=null,this.recordField=null,this.callback=null,this.treeWrapper=document.querySelector("#"+e),this.recordField=document.querySelector("#"+t),this.callback=r,this.initialize()}return t.prototype.initialize=function(){var t=this,i=this.generateRequestUrl(),a=new r,d={dataUrl:i,showIcons:!0,showCheckboxes:!0,readOnlyMode:1===parseInt(this.recordField.dataset.readOnly,10),input:this.recordField,exclusiveNodesIdentifiers:this.recordField.dataset.treeExclusiveKeys,validation:JSON.parse(this.recordField.dataset.formengineValidationRules)[0],expandUpToLevel:this.recordField.dataset.treeExpandUpToLevel};a.initialize(this.treeWrapper,d)&&(a.dispatch.on("nodeSelectedAfter.requestUpdate",this.callback),this.recordField.dataset.treeShowToolbar&&e(["TYPO3/CMS/Backend/FormEngine/Element/TreeToolbar"],function(e){(new e).initialize(t.treeWrapper)}))},t.prototype.generateRequestUrl=function(){var e={tableName:this.recordField.dataset.tablename,fieldName:this.recordField.dataset.fieldname,uid:this.recordField.dataset.uid,recordTypeValue:this.recordField.dataset.recordtypevalue,dataStructureIdentifier:""!==this.recordField.dataset.datastructureidentifier?JSON.parse(this.recordField.dataset.datastructureidentifier):"",flexFormSheetName:this.recordField.dataset.flexformsheetname,flexFormFieldName:this.recordField.dataset.flexformfieldname,flexFormContainerName:this.recordField.dataset.flexformcontainername,flexFormContainerIdentifier:this.recordField.dataset.flexformcontaineridentifier,flexFormContainerFieldName:this.recordField.dataset.flexformcontainerfieldname,flexFormSectionContainerIsNew:this.recordField.dataset.flexformsectioncontainerisnew,command:this.recordField.dataset.command};return TYPO3.settings.ajaxUrls.record_tree_data+"&"+$.param(e)},t}()});
\ No newline at end of file
Markdown is supported
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