import { Resources } from '../../resources/resources';
import { Events } from './components';
import { checkBrowserCompatibility } from '../../view/helpers';
import $ from 'jquery';
import { createTree } from 'jquery.fancytree/dist/modules/jquery.fancytree';
import 'jquery.fancytree/dist/modules/jquery.fancytree.dnd5';
import 'jquery.fancytree/dist/skin-win8/ui.fancytree.min.css';
import 'font-awesome/css/font-awesome.css';
// meta data tree view class
var nodeTypes = {
ServerNode: "servernode",
FormNode: "formnode",
FieldNode: "fieldnode",
ValueNode: "valuenode",
SlideNode: "slidenode",
};
function loadServerNode(forms, serverIndex) {
var result = [];
for (var i = 0; i < forms.length; i++) {
var form = forms[i];
var formNode = {
title: form.FormName,
type: nodeTypes.FormNode,
lazy: false,
serverIndex: serverIndex,
folder: true,
formId: form.FormID,
children: [],
};
for (var j = 0; j < form.FormFields.length; j++) {
var field = form.FormFields[j];
if (this.showAllFields || field.FormList != null) {
formNode.children.push({
title: field.Label,
type: nodeTypes.FieldNode,
fieldId: field.FieldID,
formId: form.FormID,
formListValues: field.FormList ? field.FormList.FormListValues : null,
lazy: true,
serverIndex: serverIndex,
folder: true,
});
}
}
if (formNode.children.length > 0) {
result.push(formNode);
}
}
return result;
}
function loadNode(event, data) {
var dfd = new $.Deferred();
data.result = dfd.promise();
var node = data.node;
var _this = this;
var serverIndex = node.data.serverIndex;
if (node.type == nodeTypes.ServerNode) {
this.context.getFormDefinitions(_this.servers[serverIndex].url, [], "", function (sessionId, forms) {
var result = loadServerNode.call(_this, forms, serverIndex);
dfd.resolve(result);
},
function (error) {
dfd.reject(error.Message ? error.Message : Resources.translate("Error loading forms"));
});
}
else if (node.type == nodeTypes.FieldNode) {
this.context.distinctValues({
serverUrl: _this.servers[serverIndex].url,
formId: node.data.formId,
fieldId: node.data.fieldId,
success: function (sessionId, values) {
var result = [];
for (var i = 0; i < values.length; i++) {
var label = values[i];
if (node.data.formListValues) {
for (var v = 0; v < node.data.formListValues.length; v++) {
if (node.data.formListValues[v].ValueID == label) {
label = node.data.formListValues[v].Value;
break;
}
}
}
result.push({
title: label,
type: nodeTypes.ValueNode,
formId: node.data.formId,
fieldId: node.data.fieldId,
value: values[i],
lazy: true,
serverIndex: serverIndex,
folder: true,
});
}
dfd.resolve(result);
},
failure: function (error) {
dfd.reject(error.Message ? error.Message : Resources.translate("Error loading field"));
}
});
}
else if (node.type == nodeTypes.ValueNode) {
this.context.metadata({
serverUrl: _this.servers[serverIndex].url,
expressions: [{
FormID: node.data.formId,
FieldID: node.data.fieldId,
Operator: 0,
Value: node.data.value
}],
success: function (sessionId, slides) {
var result = [];
for (var i = 0; i < slides.length; i++) {
var slide = slides[i];
result.push({
title: slide,
type: nodeTypes.SlideNode,
formId: node.data.formId,
fieldId: node.data.fieldId,
path: slide,
lazy: false,
serverIndex: serverIndex,
folder: false,
});
}
dfd.resolve(result);
},
failure: function (error) {
dfd.reject(error.Message ? error.Message : Resources.translate("Error loading field"));
}
});
}
}
function serverVersionResult(server, version) {
server.version = version;
}
/**
* Represents a UI component that shows a tree view that allows browsing through the forms and their values submitted from multiple PMA.core servers. This component uses {@link https://github.com/mar10/fancytree|fancytree} under the hood.
* @param {PMA.UI.Components.Context} context
* @param {object} options - Configuration options
* @param {PMA.UI.Components.Tree~server[]} options.servers An array of servers to show files from
* @param {string|HTMLElement} options.element - The element that hosts the tree view. It can be either a valid CSS selector or an HTMLElement instance.
* @param {function} [options.renderNode] - Allows tweaking after node state was rendered
* @param {PMA.UI.Components.Tree~rootDirSortCb} [options.rootDirSortCb] - Function that sorts an array of directories
* @param {boolean} [options.autoExpandNodes=false] - Whether the tree should expand nodes on single click
* @param {boolean} [options.showAllFields=false] - Whether to show all fields or list fields only
* @fires PMA.UI.Components.Events#ValueExpanded
* @fires PMA.UI.Components.Events#SlideSelected
*/
export class MetadataTree {
constructor(context, options) {
if (!checkBrowserCompatibility()) {
return;
}
if (options.element instanceof HTMLElement) {
this.element = element;
}
else if (typeof options.element == "string") {
var el = document.querySelector(options.element);
if (!el) {
console.error("Invalid selector for element");
}
else {
this.element = el;
}
}
this.context = context;
this.servers = options.servers || [];
var _this = this;
this.autoExpand = options.autoExpandNodes === true;
this.lastSearchResults = {};
this.showAllFields = options.showAllFields === true ? true : false;
this.listeners = {};
this.listeners[Events.ValueExpanded] = [];
this.listeners[Events.SlideSelected] = [];
if (typeof options.rootDirSortCb === "function") {
this.rootDirSortCb = options.rootDirSortCb;
}
var sourceData = [];
for (var i = 0; i < this.servers.length; i++) {
sourceData.push({
title: this.servers[i].name,
type: nodeTypes.ServerNode,
serverNode: true,
key: this.servers[i].url,
serverIndex: i,
extraClasses: "server",
dirPath: "/",
lazy: true,
unselectableStatus: false,
unselectable: true,
selected: false,
});
// try get version for each server
this.context.getVersionInfo(this.servers[i].url, serverVersionResult.bind(this, this.servers[i]));
}
var tree = createTree(this.element, {
keyPathSeparator: "?",
extensions: [],
selectMode: 3,
toggleEffect: { effect: "drop", options: { direction: "left" }, duration: 400 },
wide: {
iconWidth: "1em",
iconSpacing: "0.5em",
levelOfs: "1.5em" // Adjust this if ul padding != "16px"
},
icon: function (event, data) {
switch (data.node.type) {
case nodeTypes.ServerNode:
return "server";
case nodeTypes.FormNode:
return "fa fa-table";
case nodeTypes.SlideNode:
return "image";
case nodeTypes.FieldNode:
return "fa fa-tag";
case nodeTypes.ValueNode:
return "fa fa-code";
default:
return "fa fa-table";
}
},
renderNode: (typeof options.renderNode === "function" ? options.renderNode : null),
source: sourceData,
lazyLoad: loadNode.bind(this),
activate: function (event, data) {
// A node was activated:
var node = data.node;
if (_this.autoExpand === true) {
node.setExpanded(true);
}
if (node.type == nodeTypes.SlideNode) {
_this.fireEvent(Events.SlideSelected, { serverUrl: _this.servers[node.data.serverIndex].url, path: node.data.path });
}
},
select: function (event, data) {
var n = data.tree.getSelectedNodes();
var selectionArray = [];
},
expand: function (event, data) {
var node = data.node;
if (node.type == nodeTypes.ValueNode) {
var slides = [];
if (node.children && node.children.length > 0) {
for (var i = 0; i < node.children.length; i++) {
slides.push(node.children[i].data.path);
}
}
_this.fireEvent(Events.ValueExpanded, { serverUrl: _this.servers[node.data.serverIndex].url, slides: slides });
}
},
dblclick: function (event, data) {
var node = data.node;
}
});
}
/**
* Adds a new server to the tree
* @param {PMA.UI.Components.Tree~server} server A server object
*/
addServer(server) {
if (server) {
this.servers.push(server);
var serverInfo = {
title: this.servers[this.servers.length - 1].name,
serverNode: true,
key: this.servers[this.servers.length - 1].url,
serverIndex: this.servers.length - 1,
extraClasses: "server",
dirPath: "/",
lazy: true,
unselectableStatus: false,
unselectable: true,
selected: false,
};
// try get version for server
this.context.getVersionInfo(server.url, serverVersionResult.bind(this, server));
$(this.element).fancytree("getRootNode").addChildren(serverInfo);
}
}
/**
* Removes a server from the tree
* @param {number} index The index of the server to remove
*/
removeServer(index) {
var children = $(this.element).fancytree("getRootNode").getChildren();
if (children && children.length && index >= 0 && index < children.length) {
children[index].remove();
}
else {
console.error("No children found or index out of range");
}
}
/**
* Attaches an event listener
* @param {PMA.UI.Components.Events} eventName - The name of the event to listen to
* @param {function} callback - The function to call when the event occurs
*/
listen(eventName, callback) {
if (!this.listeners.hasOwnProperty(eventName)) {
console.error(eventName + " is not a valid event");
}
this.listeners[eventName].push(callback);
}
// fires an event
fireEvent(eventName, eventArgs) {
if (!this.listeners.hasOwnProperty(eventName)) {
console.error(eventName + " does not exist");
return;
}
for (var i = 0, max = this.listeners[eventName].length; i < max; i++) {
this.listeners[eventName][i].call(this, eventArgs);
}
}
}