mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-23 02:09:03 +02:00
Added working treeviews and buttons.
This commit is contained in:
parent
82761a3454
commit
afd45d464c
17 changed files with 547 additions and 74 deletions
304
assets/ts_src/ajax_ui.js
Normal file
304
assets/ts_src/ajax_ui.js
Normal file
|
@ -0,0 +1,304 @@
|
||||||
|
"use strict";
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* part-db version 0.1
|
||||||
|
* Copyright (C) 2005 Christoph Lechner
|
||||||
|
* http://www.cl-projects.de/
|
||||||
|
*
|
||||||
|
* part-db version 0.2+
|
||||||
|
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
|
||||||
|
* http://code.google.com/p/part-db/
|
||||||
|
*
|
||||||
|
* Part-DB Version 0.4+
|
||||||
|
* Copyright (C) 2016 - 2019 Jan Böhmer
|
||||||
|
* https://github.com/jbtronics
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
var Cookies = require("js-cookie");
|
||||||
|
/**
|
||||||
|
* Extract the title (The name between the <title> tags) of a HTML snippet.
|
||||||
|
* @param {string} html The HTML code which should be searched.
|
||||||
|
* @returns {string} The title extracted from the html.
|
||||||
|
*/
|
||||||
|
function extractTitle(html) {
|
||||||
|
var title = "";
|
||||||
|
var regex = /<title>(.*?)<\/title>/gi;
|
||||||
|
if (regex.test(html)) {
|
||||||
|
var matches = html.match(regex);
|
||||||
|
for (var match in matches) {
|
||||||
|
title = $(matches[match]).text();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
var AjaxUI = /** @class */ (function () {
|
||||||
|
function AjaxUI() {
|
||||||
|
this.BASE = "/";
|
||||||
|
this.trees_filled = false;
|
||||||
|
this.statePopped = false;
|
||||||
|
//Make back in the browser go back in history
|
||||||
|
window.onpopstate = this.onPopState;
|
||||||
|
$(document).ajaxError(this.onAjaxError.bind(this));
|
||||||
|
//$(document).ajaxComplete(this.onAjaxComplete.bind(this));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Starts the ajax ui und execute handlers registered in addStartAction().
|
||||||
|
* Should be called in a document.ready, after handlers are set.
|
||||||
|
*/
|
||||||
|
AjaxUI.prototype.start = function () {
|
||||||
|
console.info("AjaxUI started!");
|
||||||
|
this.BASE = $("body").data("base-url") + "/";
|
||||||
|
console.info("Base path is " + this.BASE);
|
||||||
|
this.registerLinks();
|
||||||
|
this.registerForm();
|
||||||
|
this.fillTrees();
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Fill the trees with the given data.
|
||||||
|
*/
|
||||||
|
AjaxUI.prototype.fillTrees = function () {
|
||||||
|
var categories = Cookies.get("tree_datasource_tree-categories");
|
||||||
|
var devices = Cookies.get("tree_datasource_tree-devices");
|
||||||
|
var tools = Cookies.get("tree_datasource_tree-tools");
|
||||||
|
if (typeof categories == "undefined") {
|
||||||
|
categories = "categories";
|
||||||
|
}
|
||||||
|
if (typeof devices == "undefined") {
|
||||||
|
devices = "devices";
|
||||||
|
}
|
||||||
|
if (typeof tools == "undefined") {
|
||||||
|
tools = "tools";
|
||||||
|
}
|
||||||
|
this.treeLoadDataSource("tree-categories", categories);
|
||||||
|
this.treeLoadDataSource("tree-devices", devices);
|
||||||
|
this.treeLoadDataSource("tree-tools", tools);
|
||||||
|
this.trees_filled = true;
|
||||||
|
//Register tree btns to expand all, or to switch datasource.
|
||||||
|
$(".tree-btns").click(function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
$(this).parents("div.dropdown").removeClass('show');
|
||||||
|
//$(this).closest(".dropdown-menu").removeClass('show');
|
||||||
|
$(".dropdown-menu.show").removeClass("show");
|
||||||
|
var mode = $(this).data("mode");
|
||||||
|
var target = $(this).data("target");
|
||||||
|
var text = $(this).text() + " \n<span class='caret'></span>"; //Add caret or it will be removed, when written into title
|
||||||
|
if (mode === "collapse") {
|
||||||
|
// @ts-ignore
|
||||||
|
$('#' + target).treeview('collapseAll', { silent: true });
|
||||||
|
}
|
||||||
|
else if (mode === "expand") {
|
||||||
|
// @ts-ignore
|
||||||
|
$('#' + target).treeview('expandAll', { silent: true });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Cookies.set("tree_datasource_" + target, mode);
|
||||||
|
exports.ajaxUI.treeLoadDataSource(target, mode);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Load the given url into the tree with the given id.
|
||||||
|
* @param target_id
|
||||||
|
* @param datasource
|
||||||
|
*/
|
||||||
|
AjaxUI.prototype.treeLoadDataSource = function (target_id, datasource) {
|
||||||
|
var text = $(".tree-btns[data-mode='" + datasource + "']").html();
|
||||||
|
text = text + " \n<span class='caret'></span>"; //Add caret or it will be removed, when written into title
|
||||||
|
switch (datasource) {
|
||||||
|
case "categories":
|
||||||
|
exports.ajaxUI.initTree("#" + target_id, 'tree/categories/');
|
||||||
|
break;
|
||||||
|
case "locations":
|
||||||
|
exports.ajaxUI.initTree("#" + target_id, 'tree/locations');
|
||||||
|
break;
|
||||||
|
case "footprints":
|
||||||
|
exports.ajaxUI.initTree("#" + target_id, 'tree/footprints');
|
||||||
|
break;
|
||||||
|
case "manufacturers":
|
||||||
|
exports.ajaxUI.initTree("#" + target_id, 'tree/manufacturers');
|
||||||
|
break;
|
||||||
|
case "suppliers":
|
||||||
|
exports.ajaxUI.initTree("#" + target_id, 'tree/suppliers');
|
||||||
|
break;
|
||||||
|
case "tools":
|
||||||
|
exports.ajaxUI.initTree("#" + target_id, 'tree/tools/');
|
||||||
|
break;
|
||||||
|
case "devices":
|
||||||
|
exports.ajaxUI.initTree("#" + target_id, 'tree/devices');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$("#" + target_id + "-title").html(text);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Fill a treeview with data from the given url.
|
||||||
|
* @param tree The Jquery selector for the tree (e.g. "#tree-tools")
|
||||||
|
* @param url The url from where the data should be loaded
|
||||||
|
*/
|
||||||
|
AjaxUI.prototype.initTree = function (tree, url) {
|
||||||
|
//let contextmenu_handler = this.onNodeContextmenu;
|
||||||
|
$.getJSON(exports.ajaxUI.BASE + url, function (data) {
|
||||||
|
// @ts-ignore
|
||||||
|
$(tree).treeview({
|
||||||
|
data: data,
|
||||||
|
enableLinks: false,
|
||||||
|
showIcon: false,
|
||||||
|
showBorder: true,
|
||||||
|
onNodeSelected: function (event, data) {
|
||||||
|
if (data.href) {
|
||||||
|
exports.ajaxUI.navigateTo(data.href);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//onNodeContextmenu: contextmenu_handler,
|
||||||
|
expandIcon: "fas fa-plus fa-fw fa-treeview", collapseIcon: "fas fa-minus fa-fw fa-treeview"
|
||||||
|
}).treeview('collapseAll', { silent: true });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Register all links, for loading via ajax.
|
||||||
|
*/
|
||||||
|
AjaxUI.prototype.registerLinks = function () {
|
||||||
|
$('a').not(".link-external, [data-no-ajax]").click(function (event) {
|
||||||
|
var a = $(this);
|
||||||
|
var href = $.trim(a.attr("href"));
|
||||||
|
//Ignore links without href attr and nav links ('they only have a #)
|
||||||
|
if (href != null && href != "" && href.charAt(0) !== '#') {
|
||||||
|
event.preventDefault();
|
||||||
|
exports.ajaxUI.navigateTo(href);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.debug('Links registered!');
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Register all forms for loading via ajax.
|
||||||
|
*/
|
||||||
|
AjaxUI.prototype.registerForm = function () {
|
||||||
|
var options = {
|
||||||
|
success: this.onAjaxComplete,
|
||||||
|
beforeSubmit: function (arr, $form, options) {
|
||||||
|
//When data-with-progbar is specified, then show progressbar.
|
||||||
|
if ($form.data("with-progbar") != undefined) {
|
||||||
|
exports.ajaxUI.showProgressBar();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$('form').not('[data-no-ajax]').ajaxForm(options);
|
||||||
|
console.debug('Forms registered!');
|
||||||
|
};
|
||||||
|
AjaxUI.prototype.showProgressBar = function () {
|
||||||
|
//Blur content background
|
||||||
|
$('#content').addClass('loading-content');
|
||||||
|
// @ts-ignore
|
||||||
|
$('#progressModal').modal({
|
||||||
|
keyboard: false,
|
||||||
|
backdrop: false,
|
||||||
|
show: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
AjaxUI.prototype.hideProgressBar = function () {
|
||||||
|
// @ts-ignore
|
||||||
|
$('#progressModal').modal('hide');
|
||||||
|
//Remove the remaining things of the modal
|
||||||
|
$('.modal-backdrop').remove();
|
||||||
|
$('body').removeClass('modal-open');
|
||||||
|
$('body, .navbar').css('padding-right', "");
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Navigates to the given URL
|
||||||
|
* @param url The url which should be opened.
|
||||||
|
* @param show_loading Show the loading bar during loading.
|
||||||
|
*/
|
||||||
|
AjaxUI.prototype.navigateTo = function (url, show_loading) {
|
||||||
|
if (show_loading === void 0) { show_loading = true; }
|
||||||
|
if (show_loading) {
|
||||||
|
this.showProgressBar();
|
||||||
|
}
|
||||||
|
$.ajax(url, {
|
||||||
|
success: this.onAjaxComplete
|
||||||
|
});
|
||||||
|
//$.ajax(url).promise().done(this.onAjaxComplete);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Called when an error occurs on loading ajax. Outputs the message to the console.
|
||||||
|
*/
|
||||||
|
AjaxUI.prototype.onAjaxError = function (event, request, settings) {
|
||||||
|
'use strict';
|
||||||
|
//Ignore aborted requests.
|
||||||
|
if (request.statusText == 'abort') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.error("Error getting the ajax data from server!");
|
||||||
|
console.log(event);
|
||||||
|
console.log(request);
|
||||||
|
console.log(settings);
|
||||||
|
//If it was a server error and response is not empty, show it to user.
|
||||||
|
if (request.status == 500 && request.responseText !== "") {
|
||||||
|
console.log("Response:" + request.responseText);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This function gets called every time, the "back" button in the browser is pressed.
|
||||||
|
* We use it to load the content from history stack via ajax and to rewrite url, so we only have
|
||||||
|
* to load #content-data
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
AjaxUI.prototype.onPopState = function (event) {
|
||||||
|
var page = location.href;
|
||||||
|
exports.ajaxUI.statePopped = true;
|
||||||
|
exports.ajaxUI.navigateTo(page);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* This function takes the response of an ajax requests, and does the things we need to do for our AjaxUI.
|
||||||
|
* This includes inserting the content and pushing history.
|
||||||
|
* @param responseText
|
||||||
|
* @param textStatus
|
||||||
|
* @param jqXHR
|
||||||
|
*/
|
||||||
|
AjaxUI.prototype.onAjaxComplete = function (responseText, textStatus, jqXHR) {
|
||||||
|
console.debug("Ajax load completed!");
|
||||||
|
exports.ajaxUI.hideProgressBar();
|
||||||
|
//Parse response to DOM structure
|
||||||
|
var dom = $.parseHTML(responseText);
|
||||||
|
//And replace the content container
|
||||||
|
$("#content").replaceWith($("#content", dom));
|
||||||
|
//Replace login menu too (so everything is up to date)
|
||||||
|
$("#login-content").replaceWith($('#login-content', dom));
|
||||||
|
//Replace flash messages and show them
|
||||||
|
$("#message-container").replaceWith($('#message-container', dom));
|
||||||
|
$(".toast").toast('show');
|
||||||
|
//Set new title
|
||||||
|
var title = extractTitle(responseText);
|
||||||
|
document.title = title;
|
||||||
|
//Push to history, if we currently arent poping an old value.
|
||||||
|
if (!exports.ajaxUI.statePopped) {
|
||||||
|
// @ts-ignore
|
||||||
|
history.pushState(null, title, this.url);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//Clear pop state
|
||||||
|
exports.ajaxUI.statePopped;
|
||||||
|
}
|
||||||
|
//Do things on the new dom
|
||||||
|
exports.ajaxUI.registerLinks();
|
||||||
|
exports.ajaxUI.registerForm();
|
||||||
|
};
|
||||||
|
return AjaxUI;
|
||||||
|
}());
|
||||||
|
exports.ajaxUI = new AjaxUI();
|
||||||
|
//# sourceMappingURL=ajax_ui.js.map
|
1
assets/ts_src/ajax_ui.js.map
Normal file
1
assets/ts_src/ajax_ui.js.map
Normal file
File diff suppressed because one or more lines are too long
|
@ -50,15 +50,12 @@ function extractTitle(html : string) : string {
|
||||||
|
|
||||||
class AjaxUI {
|
class AjaxUI {
|
||||||
|
|
||||||
|
protected BASE = "/";
|
||||||
|
|
||||||
private trees_filled : boolean = false;
|
private trees_filled : boolean = false;
|
||||||
|
|
||||||
private statePopped : boolean = false;
|
private statePopped : boolean = false;
|
||||||
|
|
||||||
public test()
|
|
||||||
{
|
|
||||||
alert("Test");
|
|
||||||
}
|
|
||||||
|
|
||||||
public constructor()
|
public constructor()
|
||||||
{
|
{
|
||||||
//Make back in the browser go back in history
|
//Make back in the browser go back in history
|
||||||
|
@ -74,14 +71,132 @@ class AjaxUI {
|
||||||
public start()
|
public start()
|
||||||
{
|
{
|
||||||
console.info("AjaxUI started!");
|
console.info("AjaxUI started!");
|
||||||
|
|
||||||
|
this.BASE = $("body").data("base-url") + "/";
|
||||||
|
console.info("Base path is " + this.BASE);
|
||||||
|
|
||||||
this.registerLinks();
|
this.registerLinks();
|
||||||
this.registerForm();
|
this.registerForm();
|
||||||
|
this.fillTrees();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill the trees with the given data.
|
||||||
|
*/
|
||||||
|
public fillTrees()
|
||||||
|
{
|
||||||
|
let categories = Cookies.get("tree_datasource_tree-categories");
|
||||||
|
let devices = Cookies.get("tree_datasource_tree-devices");
|
||||||
|
let tools = Cookies.get("tree_datasource_tree-tools");
|
||||||
|
|
||||||
|
if(typeof categories == "undefined") {
|
||||||
|
categories = "categories";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof devices == "undefined") {
|
||||||
|
devices = "devices";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof tools == "undefined") {
|
||||||
|
tools = "tools";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.treeLoadDataSource("tree-categories", categories);
|
||||||
|
this.treeLoadDataSource("tree-devices", devices);
|
||||||
|
this.treeLoadDataSource("tree-tools", tools);
|
||||||
|
|
||||||
|
this.trees_filled = true;
|
||||||
|
|
||||||
|
//Register tree btns to expand all, or to switch datasource.
|
||||||
|
$(".tree-btns").click(function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
$(this).parents("div.dropdown").removeClass('show');
|
||||||
|
//$(this).closest(".dropdown-menu").removeClass('show');
|
||||||
|
$(".dropdown-menu.show").removeClass("show");
|
||||||
|
let mode = $(this).data("mode");
|
||||||
|
let target = $(this).data("target");
|
||||||
|
let text = $(this).text() + " \n<span class='caret'></span>"; //Add caret or it will be removed, when written into title
|
||||||
|
|
||||||
|
if (mode==="collapse") {
|
||||||
|
// @ts-ignore
|
||||||
|
$('#' + target).treeview('collapseAll', { silent: true });
|
||||||
|
}
|
||||||
|
else if(mode==="expand") {
|
||||||
|
// @ts-ignore
|
||||||
|
$('#' + target).treeview('expandAll', { silent: true });
|
||||||
|
} else {
|
||||||
|
Cookies.set("tree_datasource_" + target, mode);
|
||||||
|
ajaxUI.treeLoadDataSource(target, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the given url into the tree with the given id.
|
||||||
|
* @param target_id
|
||||||
|
* @param datasource
|
||||||
|
*/
|
||||||
|
protected treeLoadDataSource(target_id, datasource) {
|
||||||
|
let text : string = $(".tree-btns[data-mode='" + datasource + "']").html();
|
||||||
|
text = text + " \n<span class='caret'></span>"; //Add caret or it will be removed, when written into title
|
||||||
|
switch(datasource) {
|
||||||
|
case "categories":
|
||||||
|
ajaxUI.initTree("#" + target_id, 'tree/categories/');
|
||||||
|
break;
|
||||||
|
case "locations":
|
||||||
|
ajaxUI.initTree("#" + target_id, 'tree/locations');
|
||||||
|
break;
|
||||||
|
case "footprints":
|
||||||
|
ajaxUI.initTree("#" + target_id, 'tree/footprints');
|
||||||
|
break;
|
||||||
|
case "manufacturers":
|
||||||
|
ajaxUI.initTree("#" + target_id, 'tree/manufacturers');
|
||||||
|
break;
|
||||||
|
case "suppliers":
|
||||||
|
ajaxUI.initTree("#" + target_id, 'tree/suppliers');
|
||||||
|
break;
|
||||||
|
case "tools":
|
||||||
|
ajaxUI.initTree("#" + target_id, 'tree/tools/');
|
||||||
|
break;
|
||||||
|
case "devices":
|
||||||
|
ajaxUI.initTree("#" + target_id, 'tree/devices');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$( "#" + target_id + "-title").html(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill a treeview with data from the given url.
|
||||||
|
* @param tree The Jquery selector for the tree (e.g. "#tree-tools")
|
||||||
|
* @param url The url from where the data should be loaded
|
||||||
|
*/
|
||||||
|
public initTree(tree, url) {
|
||||||
|
//let contextmenu_handler = this.onNodeContextmenu;
|
||||||
|
$.getJSON(ajaxUI.BASE + url, function (data) {
|
||||||
|
// @ts-ignore
|
||||||
|
$(tree).treeview({
|
||||||
|
data: data,
|
||||||
|
enableLinks: false,
|
||||||
|
showIcon: false,
|
||||||
|
showBorder: true,
|
||||||
|
onNodeSelected: function(event, data) {
|
||||||
|
if(data.href) {
|
||||||
|
ajaxUI.navigateTo(data.href);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//onNodeContextmenu: contextmenu_handler,
|
||||||
|
expandIcon: "fas fa-plus fa-fw fa-treeview", collapseIcon: "fas fa-minus fa-fw fa-treeview"}).treeview('collapseAll', { silent: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register all links, for loading via ajax.
|
* Register all links, for loading via ajax.
|
||||||
*/
|
*/
|
||||||
protected registerLinks()
|
public registerLinks()
|
||||||
{
|
{
|
||||||
$('a').not(".link-external, [data-no-ajax]").click(function (event) {
|
$('a').not(".link-external, [data-no-ajax]").click(function (event) {
|
||||||
let a = $(this);
|
let a = $(this);
|
||||||
|
@ -92,14 +207,14 @@ class AjaxUI {
|
||||||
ajaxUI.navigateTo(href);
|
ajaxUI.navigateTo(href);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
console.debug('Links registered!');
|
console.debug('Links registered!');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register all forms for loading via ajax.
|
* Register all forms for loading via ajax.
|
||||||
*/
|
*/
|
||||||
protected registerForm()
|
public registerForm()
|
||||||
{
|
{
|
||||||
let options : JQueryFormOptions = {
|
let options : JQueryFormOptions = {
|
||||||
success: this.onAjaxComplete,
|
success: this.onAjaxComplete,
|
||||||
|
@ -110,7 +225,7 @@ class AjaxUI {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
$('form').not('[data-no-ajax]').ajaxForm(options);
|
$('form').not('[data-no-ajax]').ajaxForm(options);
|
||||||
|
|
||||||
console.debug('Forms registered!');
|
console.debug('Forms registered!');
|
||||||
|
@ -168,7 +283,10 @@ class AjaxUI {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.error("Error getting the ajax data from server!");
|
||||||
console.log(event);
|
console.log(event);
|
||||||
|
console.log(request);
|
||||||
|
console.log(settings);
|
||||||
//If it was a server error and response is not empty, show it to user.
|
//If it was a server error and response is not empty, show it to user.
|
||||||
if(request.status == 500 && request.responseText !== "")
|
if(request.status == 500 && request.responseText !== "")
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"typeRoots": ["../node_modules"],
|
"typeRoots": ["../node_modules"],
|
||||||
"types": ["jquery", "js-cookie", "bootstrap", "jquery.form"]
|
"types": ["jquery", "js-cookie", "bootstrap", "jquery.form", "bootstrap-treeview"]
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules"
|
"node_modules"
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ckeditor/ckeditor5-build-classic": "^12.0.0",
|
"@ckeditor/ckeditor5-build-classic": "^12.0.0",
|
||||||
"@types/bootstrap": "^4.3.0",
|
"@types/bootstrap": "^4.3.0",
|
||||||
|
"@types/bootstrap-treeview": "^1.20.0",
|
||||||
"@types/jquery": "^3.3.29",
|
"@types/jquery": "^3.3.29",
|
||||||
"@types/jquery.form": "^3.26.30",
|
"@types/jquery.form": "^3.26.30",
|
||||||
"@types/js-cookie": "^2.2.1",
|
"@types/js-cookie": "^2.2.1",
|
||||||
|
|
|
@ -30,9 +30,16 @@
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Entity\Category;
|
use App\Entity\Category;
|
||||||
|
use App\Entity\Device;
|
||||||
|
use App\Entity\Footprint;
|
||||||
|
use App\Entity\Manufacturer;
|
||||||
|
use App\Entity\Storelocation;
|
||||||
|
use App\Entity\Supplier;
|
||||||
use App\Helpers\TreeViewNode;
|
use App\Helpers\TreeViewNode;
|
||||||
use App\Services\ToolsTreeBuilder;
|
use App\Services\ToolsTreeBuilder;
|
||||||
|
use App\Services\TreeBuilder;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\LocaleType;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,10 +62,11 @@ class TreeController extends AbstractController
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/tree/category/{id}", name="tree_category")
|
* @Route("/tree/category/{id}", name="tree_category")
|
||||||
|
* @Route("/tree/categories")
|
||||||
*/
|
*/
|
||||||
public function categoryTree(TreeBuilder $builder, Category $category = null)
|
public function categoryTree(TreeBuilder $builder, Category $category = null)
|
||||||
{
|
{
|
||||||
if($category != null) {
|
if ($category != null) {
|
||||||
$tree[] = $builder->elementToTreeNode($category);
|
$tree[] = $builder->elementToTreeNode($category);
|
||||||
} else {
|
} else {
|
||||||
$tree = $builder->typeToTree(Category::class);
|
$tree = $builder->typeToTree(Category::class);
|
||||||
|
@ -68,7 +76,85 @@ class TreeController extends AbstractController
|
||||||
return $this->json($tree, 200, [], ['skip_null_values' => true]);
|
return $this->json($tree, 200, [], ['skip_null_values' => true]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/tree/footprint/{id}", name="tree_footprint")
|
||||||
|
* @Route("/tree/footprints")
|
||||||
|
*/
|
||||||
|
public function footprintTree(TreeBuilder $builder, Footprint $footprint = null)
|
||||||
|
{
|
||||||
|
if ($footprint != null) {
|
||||||
|
$tree[] = $builder->elementToTreeNode($footprint);
|
||||||
|
} else {
|
||||||
|
$tree = $builder->typeToTree(Footprint::class, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $this->json($tree, 200, [], ['skip_null_values' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/tree/location/{id}", name="tree_location")
|
||||||
|
* @Route("/tree/locations")
|
||||||
|
*/
|
||||||
|
public function locationTree(TreeBuilder $builder, Storelocation $location = null)
|
||||||
|
{
|
||||||
|
if ($location != null) {
|
||||||
|
$tree[] = $builder->elementToTreeNode($location);
|
||||||
|
} else {
|
||||||
|
$tree = $builder->typeToTree(Storelocation::class, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $this->json($tree, 200, [], ['skip_null_values' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/tree/manufacturer/{id}", name="tree_manufacturer")
|
||||||
|
* @Route("/tree/manufacturers")
|
||||||
|
*/
|
||||||
|
public function manufacturerTree(TreeBuilder $builder, Manufacturer $manufacturer = null)
|
||||||
|
{
|
||||||
|
if ($manufacturer != null) {
|
||||||
|
$tree[] = $builder->elementToTreeNode($manufacturer);
|
||||||
|
} else {
|
||||||
|
$tree = $builder->typeToTree(Manufacturer::class, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $this->json($tree, 200, [], ['skip_null_values' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/tree/supplier/{id}", name="tree_supplier")
|
||||||
|
* @Route("/tree/suppliers")
|
||||||
|
*/
|
||||||
|
public function supplierTree(TreeBuilder $builder, Supplier $supplier = null)
|
||||||
|
{
|
||||||
|
if ($supplier != null) {
|
||||||
|
$tree[] = $builder->elementToTreeNode($supplier);
|
||||||
|
} else {
|
||||||
|
$tree = $builder->typeToTree(Supplier::class, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $this->json($tree, 200, [], ['skip_null_values' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/tree/device/{id}", name="tree_device")
|
||||||
|
* @Route("/tree/devices")
|
||||||
|
*/
|
||||||
|
public function deviceTree(TreeBuilder $builder, Device $device = null)
|
||||||
|
{
|
||||||
|
if ($device != null) {
|
||||||
|
$tree[] = $builder->elementToTreeNode($device);
|
||||||
|
} else {
|
||||||
|
$tree = $builder->typeToTree(Device::class, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $this->json($tree, 200, [], ['skip_null_values' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ use Doctrine\ORM\Mapping as ORM;
|
||||||
/**
|
/**
|
||||||
* Class AttachmentType.
|
* Class AttachmentType.
|
||||||
*
|
*
|
||||||
* @ORM\Entity()
|
* @ORM\Entity(repositoryClass="App\Repository\StructuralDBElementRepository")
|
||||||
* @ORM\Table(name="attachement_types")
|
* @ORM\Table(name="attachement_types")
|
||||||
*/
|
*/
|
||||||
class AttachmentType extends StructuralDBElement
|
class AttachmentType extends StructuralDBElement
|
||||||
|
|
|
@ -28,7 +28,7 @@ use Doctrine\ORM\Mapping as ORM;
|
||||||
/**
|
/**
|
||||||
* Class AttachmentType.
|
* Class AttachmentType.
|
||||||
*
|
*
|
||||||
* @ORM\Entity
|
* @ORM\Entity(repositoryClass="App\Repository\StructuralDBElementRepository")
|
||||||
* @ORM\Table(name="categories")
|
* @ORM\Table(name="categories")
|
||||||
*/
|
*/
|
||||||
class Category extends PartsContainingDBElement
|
class Category extends PartsContainingDBElement
|
||||||
|
|
|
@ -37,7 +37,7 @@ use Doctrine\ORM\Mapping as ORM;
|
||||||
/**
|
/**
|
||||||
* Class AttachmentType.
|
* Class AttachmentType.
|
||||||
*
|
*
|
||||||
* @ORM\Entity()
|
* @ORM\Entity(repositoryClass="App\Repository\StructuralDBElementRepository")
|
||||||
* @ORM\Table(name="devices")
|
* @ORM\Table(name="devices")
|
||||||
*/
|
*/
|
||||||
class Device extends PartsContainingDBElement
|
class Device extends PartsContainingDBElement
|
||||||
|
|
|
@ -37,7 +37,7 @@ use Doctrine\ORM\Mapping as ORM;
|
||||||
/**
|
/**
|
||||||
* Class Footprint.
|
* Class Footprint.
|
||||||
*
|
*
|
||||||
* @ORM\Entity()
|
* @ORM\Entity(repositoryClass="App\Repository\StructuralDBElementRepository")
|
||||||
* @ORM\Table("footprints")
|
* @ORM\Table("footprints")
|
||||||
*/
|
*/
|
||||||
class Footprint extends PartsContainingDBElement
|
class Footprint extends PartsContainingDBElement
|
||||||
|
|
|
@ -37,7 +37,7 @@ use Doctrine\ORM\Mapping as ORM;
|
||||||
/**
|
/**
|
||||||
* Class Manufacturer.
|
* Class Manufacturer.
|
||||||
*
|
*
|
||||||
* @ORM\Entity()
|
* @ORM\Entity(repositoryClass="App\Repository\StructuralDBElementRepository")
|
||||||
* @ORM\Table("manufacturers")
|
* @ORM\Table("manufacturers")
|
||||||
*/
|
*/
|
||||||
class Manufacturer extends Company
|
class Manufacturer extends Company
|
||||||
|
|
|
@ -37,7 +37,7 @@ use Doctrine\ORM\Mapping as ORM;
|
||||||
/**
|
/**
|
||||||
* Class Storelocation.
|
* Class Storelocation.
|
||||||
*
|
*
|
||||||
* @ORM\Entity()
|
* @ORM\Entity(repositoryClass="App\Repository\StructuralDBElementRepository")
|
||||||
* @ORM\Table("storelocations")
|
* @ORM\Table("storelocations")
|
||||||
*/
|
*/
|
||||||
class Storelocation extends PartsContainingDBElement
|
class Storelocation extends PartsContainingDBElement
|
||||||
|
|
|
@ -36,8 +36,7 @@ use Doctrine\ORM\PersistentCollection;
|
||||||
* It's allowed to have instances of root elements, but if you try to change
|
* It's allowed to have instances of root elements, but if you try to change
|
||||||
* an attribute of a root element, you will get an exception!
|
* an attribute of a root element, you will get an exception!
|
||||||
*
|
*
|
||||||
* @ORM\MappedSuperclass()
|
* @ORM\MappedSuperclass(repositoryClass="App\Repository\StructuralDBElementRepository")
|
||||||
* //@ORM\Entity(repositoryClass="App\Repository\StructuralDBElementRepository")
|
|
||||||
*/
|
*/
|
||||||
abstract class StructuralDBElement extends AttachmentContainingDBElement
|
abstract class StructuralDBElement extends AttachmentContainingDBElement
|
||||||
{
|
{
|
||||||
|
@ -310,50 +309,6 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
|
||||||
return implode("\n", $html);
|
return implode("\n", $html);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildBootstrapTree(
|
|
||||||
$page,
|
|
||||||
$parameter,
|
|
||||||
$recursive = false,
|
|
||||||
$show_root = false,
|
|
||||||
$use_db_root_name = true,
|
|
||||||
$root_name = '$$'
|
|
||||||
): array {
|
|
||||||
if ('$$' == $root_name) {
|
|
||||||
$root_name = _('Oberste Ebene');
|
|
||||||
}
|
|
||||||
|
|
||||||
$subelements = $this->getSubelements(false);
|
|
||||||
$nodes = array();
|
|
||||||
|
|
||||||
foreach ($subelements as $element) {
|
|
||||||
$nodes[] = $element->buildBootstrapTree($page, $parameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we are on root level?
|
|
||||||
if (-1 == $this->getParentID()) {
|
|
||||||
if ($show_root) {
|
|
||||||
$tree = array(
|
|
||||||
array('text' => $use_db_root_name ? htmlspecialchars($this->getName()) : $root_name,
|
|
||||||
'href' => $page.'?'.$parameter.'='.$this->getID(),
|
|
||||||
'nodes' => $nodes, ),
|
|
||||||
);
|
|
||||||
} else { //Dont show root node
|
|
||||||
$tree = $nodes;
|
|
||||||
}
|
|
||||||
} elseif (!empty($nodes)) {
|
|
||||||
$tree = array('text' => htmlspecialchars($this->getName()),
|
|
||||||
'href' => $page.'?'.$parameter.'='.$this->getID(),
|
|
||||||
'nodes' => $nodes,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
$tree = array('text' => htmlspecialchars($this->getName()),
|
|
||||||
'href' => $page.'?'.$parameter.'='.$this->getID(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a template loop for a Breadcrumb bar, representing the structural DB element.
|
* Creates a template loop for a Breadcrumb bar, representing the structural DB element.
|
||||||
*
|
*
|
||||||
|
|
|
@ -37,7 +37,7 @@ use Doctrine\ORM\Mapping as ORM;
|
||||||
/**
|
/**
|
||||||
* Class Supplier.
|
* Class Supplier.
|
||||||
*
|
*
|
||||||
* @ORM\Entity()
|
* @ORM\Entity(repositoryClass="App\Repository\StructuralDBElementRepository")
|
||||||
* @ORM\Table("suppliers")
|
* @ORM\Table("suppliers")
|
||||||
*/
|
*/
|
||||||
class Supplier extends Company
|
class Supplier extends Company
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* part-db version 0.1
|
* part-db version 0.1
|
||||||
* Copyright (C) 2005 Christoph Lechner
|
* Copyright (C) 2005 Christoph Lechner
|
||||||
* http://www.cl-projects.de/.
|
* http://www.cl-projects.de/
|
||||||
*
|
*
|
||||||
* part-db version 0.2+
|
* part-db version 0.2+
|
||||||
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
|
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
|
||||||
|
@ -25,15 +26,14 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Services;
|
||||||
|
|
||||||
use App\Entity\StructuralDBElement;
|
use App\Entity\StructuralDBElement;
|
||||||
use App\Helpers\TreeViewNode;
|
use App\Helpers\TreeViewNode;
|
||||||
use App\Repository\StructuralDBElementRepository;
|
use App\Repository\StructuralDBElementRepository;
|
||||||
use App\Services\EntityURLGenerator;
|
|
||||||
use App\Services\ToolsTreeBuilder;
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,13 +59,13 @@ class TreeBuilder
|
||||||
* See EntityURLGenerator::getURL for possible types.
|
* See EntityURLGenerator::getURL for possible types.
|
||||||
* @return TreeViewNode The Node for the given Element.
|
* @return TreeViewNode The Node for the given Element.
|
||||||
*/
|
*/
|
||||||
public function elementToTreeNode(StructuralDBElement $element, string $href_type = 'list_parts') : TreeViewNode
|
public function elementToTreeNode(StructuralDBElement $element, ?string $href_type = 'list_parts') : TreeViewNode
|
||||||
{
|
{
|
||||||
$children = $element->getSubelements();
|
$children = $element->getSubelements();
|
||||||
|
|
||||||
$children_nodes = null;
|
$children_nodes = null;
|
||||||
foreach ($children as $child) {
|
foreach ($children as $child) {
|
||||||
$children_nodes[] = $this->elementToTreeNode($child);
|
$children_nodes[] = $this->elementToTreeNode($child, $href_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check if we need to generate a href type
|
//Check if we need to generate a href type
|
||||||
|
@ -86,7 +86,7 @@ class TreeBuilder
|
||||||
* See EntityURLGenerator::getURL for possible types.
|
* See EntityURLGenerator::getURL for possible types.
|
||||||
* @return TreeViewNode[] Returns an array, containing all nodes. It is empty if the given class has no elements.
|
* @return TreeViewNode[] Returns an array, containing all nodes. It is empty if the given class has no elements.
|
||||||
*/
|
*/
|
||||||
public function typeToTree(StructuralDBElement $class_name, string $href_type = 'list_parts') : array
|
public function typeToTree(string $class_name, ?string $href_type = 'list_parts') : array
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var $repo StructuralDBElementRepository
|
* @var $repo StructuralDBElementRepository
|
||||||
|
@ -96,7 +96,7 @@ class TreeBuilder
|
||||||
|
|
||||||
$array = array();
|
$array = array();
|
||||||
foreach ($root_nodes as $node) {
|
foreach ($root_nodes as $node) {
|
||||||
$array = $this->elementToTreeNode($node, $href_type);
|
$array[] = $this->elementToTreeNode($node, $href_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $array;
|
return $array;
|
|
@ -13,13 +13,12 @@
|
||||||
<meta name="msapplication-config" content="{{ asset('icons/browserconfig.xml') }}">
|
<meta name="msapplication-config" content="{{ asset('icons/browserconfig.xml') }}">
|
||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
|
|
||||||
<title>{% filter trim %}{% block title %}{{ partdb_title}}{% endblock %}{% endfilter %}</title>
|
<title>{% filter trim %}{% block title %}{{ partdb_title}}{% endblock %}{% endfilter %}</title>
|
||||||
{% block stylesheets %}
|
{% block stylesheets %}
|
||||||
{{ encore_entry_link_tags('app') }}
|
{{ encore_entry_link_tags('app') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body data-base-url="{{ app.request.schemeAndHttpHost }}">
|
||||||
{% block body %}
|
{% block body %}
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
|
@ -279,6 +278,7 @@
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
{#
|
||||||
$.getJSON("{{ path("tree_tools") }}",null, function (data) {
|
$.getJSON("{{ path("tree_tools") }}",null, function (data) {
|
||||||
$('#tree-tools').treeview({
|
$('#tree-tools').treeview({
|
||||||
data: data,
|
data: data,
|
||||||
|
@ -293,6 +293,7 @@
|
||||||
enableLinks: true
|
enableLinks: true
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
#}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
|
|
|
@ -650,6 +650,13 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
|
resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a"
|
||||||
integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==
|
integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA==
|
||||||
|
|
||||||
|
"@types/bootstrap-treeview@^1.20.0":
|
||||||
|
version "1.20.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/bootstrap-treeview/-/bootstrap-treeview-1.20.0.tgz#08157e2f26b5b278dfd70e2054bbf8aa7d6f0b2d"
|
||||||
|
integrity sha512-o1FFKSNd68ohmyvrHna11q5cLd9aiVUp/Itr7B33OmFY37GFufQvVOH9Iv/+2xcE9tVc7pHfmxucBnQkjZzHCQ==
|
||||||
|
dependencies:
|
||||||
|
"@types/jquery" "*"
|
||||||
|
|
||||||
"@types/bootstrap@^4.3.0":
|
"@types/bootstrap@^4.3.0":
|
||||||
version "4.3.0"
|
version "4.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/bootstrap/-/bootstrap-4.3.0.tgz#4cac01617f56239a5146945a98bde64274838c35"
|
resolved "https://registry.yarnpkg.com/@types/bootstrap/-/bootstrap-4.3.0.tgz#4cac01617f56239a5146945a98bde64274838c35"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue