mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 01:25:55 +02:00
Removed old frontend code
This commit is contained in:
parent
efb38173e6
commit
750bdc45d1
3 changed files with 1 additions and 1017 deletions
|
@ -17,15 +17,6 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Welcome to your app's main JavaScript file!
|
|
||||||
*
|
|
||||||
* We recommend including the built version of this JavaScript file
|
|
||||||
* (and its CSS file) in your base layout (base.html.twig).
|
|
||||||
*/
|
|
||||||
|
|
||||||
// any CSS you require will output into a single css file (app.css in this case)
|
|
||||||
|
|
||||||
// Main CSS files
|
// Main CSS files
|
||||||
import '../css/app.css';
|
import '../css/app.css';
|
||||||
|
|
||||||
|
@ -46,57 +37,4 @@ import "./register_events";
|
||||||
import "./tristate_checkboxes";
|
import "./tristate_checkboxes";
|
||||||
|
|
||||||
//Define jquery globally
|
//Define jquery globally
|
||||||
window.$ = window.jQuery = require("jquery")
|
window.$ = window.jQuery = require("jquery")
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
|
|
||||||
require('bootstrap-select');
|
|
||||||
require('jquery-form');
|
|
||||||
require('corejs-typeahead/dist/typeahead.bundle.min');
|
|
||||||
window.Bloodhound = require('corejs-typeahead/dist/bloodhound.js');
|
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
require('bootstrap-fileinput');
|
|
||||||
|
|
||||||
require('./datatables.js');
|
|
||||||
|
|
||||||
window.bootbox = require('bootbox');
|
|
||||||
|
|
||||||
require("marked");
|
|
||||||
window.DOMPurify = require("dompurify");
|
|
||||||
|
|
||||||
// Includes required for tag input
|
|
||||||
require('./tagsinput.js');
|
|
||||||
require('../css/tagsinput.css');
|
|
||||||
|
|
||||||
//Tristate checkbox support
|
|
||||||
require('./jquery.tristate.js');
|
|
||||||
|
|
||||||
require('darkmode-js');
|
|
||||||
|
|
||||||
//Equation rendering
|
|
||||||
require('katex');
|
|
||||||
window.renderMathInElement = require('katex/contrib/auto-render/auto-render').default;
|
|
||||||
import 'katex/dist/katex.css';
|
|
||||||
|
|
||||||
window.ClipboardJS = require('clipboard');
|
|
||||||
|
|
||||||
require('../ts_src/ajax_ui');
|
|
||||||
//import {ajaxUI} from "../ts_src/ajax_ui";
|
|
||||||
|
|
||||||
//window.ajaxUI = ajaxUI;
|
|
||||||
|
|
||||||
//Require all events;
|
|
||||||
require('../ts_src/event_listeners');
|
|
||||||
|
|
||||||
|
|
||||||
//Start AjaxUI AFTER all event has been registered
|
|
||||||
//$(document).ready(ajaxUI.start());
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
//console.log('Hello Webpack Encore! Edit me in assets/js/app.js');
|
|
|
@ -1,605 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 - 2020 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 Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 : string) : string {
|
|
||||||
let title : string = "";
|
|
||||||
let regex = /<title>(.*?)<\/title>/gi;
|
|
||||||
if (regex.test(html)) {
|
|
||||||
let matches = html.match(regex);
|
|
||||||
for(let match in matches) {
|
|
||||||
title = $(matches[match]).text();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class AjaxUI {
|
|
||||||
|
|
||||||
protected BASE = "/";
|
|
||||||
|
|
||||||
private trees_filled : boolean = false;
|
|
||||||
|
|
||||||
private statePopped : boolean = false;
|
|
||||||
|
|
||||||
public xhr : XMLHttpRequest;
|
|
||||||
|
|
||||||
public constructor()
|
|
||||||
{
|
|
||||||
//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.
|
|
||||||
*/
|
|
||||||
public start(disabled : boolean = false)
|
|
||||||
{
|
|
||||||
if(disabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.info("AjaxUI started!");
|
|
||||||
|
|
||||||
this.BASE = $("body").data("base-url");
|
|
||||||
//If path doesn't end with slash, add it.
|
|
||||||
if(this.BASE[this.BASE.length - 1] !== '/') {
|
|
||||||
this.BASE = this.BASE + '/';
|
|
||||||
}
|
|
||||||
console.info("Base path is " + this.BASE);
|
|
||||||
|
|
||||||
//Show flash messages
|
|
||||||
$(".toast").toast('show');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save the XMLHttpRequest that jQuery used, to the class, so we can acess the responseURL property.
|
|
||||||
* This is a work-around as long jQuery does not implement this property in its jQXHR objects.
|
|
||||||
*/
|
|
||||||
//@ts-ignore
|
|
||||||
jQuery.ajaxSettings.xhr = function () {
|
|
||||||
//@ts-ignore
|
|
||||||
let xhr = new window.XMLHttpRequest();
|
|
||||||
//Save the XMLHttpRequest to the class.
|
|
||||||
ajaxUI.xhr = xhr;
|
|
||||||
return xhr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
this.registerLinks();
|
|
||||||
this.registerForm();
|
|
||||||
this.fillTrees();
|
|
||||||
|
|
||||||
this.initDataTables();
|
|
||||||
|
|
||||||
//Trigger start event
|
|
||||||
$(document).trigger("ajaxUI:start");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fill the trees with the given data.
|
|
||||||
*/
|
|
||||||
public fillTrees()
|
|
||||||
{
|
|
||||||
let categories = localStorage.getItem("tree_datasource_tree-categories");
|
|
||||||
let devices = localStorage.getItem("tree_datasource_tree-devices");
|
|
||||||
let tools = localStorage.getItem("tree_datasource_tree-tools");
|
|
||||||
|
|
||||||
if(categories == null) {
|
|
||||||
categories = "categories";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(devices == null) {
|
|
||||||
devices = "devices";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(tools == null) {
|
|
||||||
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 {
|
|
||||||
localStorage.setItem("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');
|
|
||||||
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,
|
|
||||||
searchResultBackColor: '#ffc107',
|
|
||||||
searchResultColor: '#000',
|
|
||||||
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"})
|
|
||||||
.on('initialized', function() {
|
|
||||||
$(this).treeview('collapseAll', { silent: true });
|
|
||||||
|
|
||||||
//Implement searching if needed.
|
|
||||||
if($(this).data('treeSearch')) {
|
|
||||||
let _this = this;
|
|
||||||
let $search = $($(this).data('treeSearch'));
|
|
||||||
$search.on( 'input', function() {
|
|
||||||
$(_this).treeview('collapseAll', { silent: true });
|
|
||||||
$(_this).treeview('search', [$search.val()]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register all links, for loading via ajax.
|
|
||||||
*/
|
|
||||||
public registerLinks()
|
|
||||||
{
|
|
||||||
// Unbind all old handlers, so the things are not executed multiple times.
|
|
||||||
$('a').not(".link-external, [data-no-ajax], .page-link, [href^='javascript'], [href^='#']").unbind('click').click(function (event) {
|
|
||||||
let a = $(this);
|
|
||||||
let 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();
|
|
||||||
ajaxUI.navigateTo(href);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
console.debug('Links registered!');
|
|
||||||
}
|
|
||||||
|
|
||||||
protected getFormOptions() : JQueryFormOptions
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
success: this.onAjaxComplete,
|
|
||||||
beforeSerialize: function($form, options) : boolean {
|
|
||||||
|
|
||||||
//Update the content of textarea fields using CKEDITOR before submitting.
|
|
||||||
//@ts-ignore
|
|
||||||
if(typeof CKEDITOR !== 'undefined') {
|
|
||||||
//@ts-ignore
|
|
||||||
for (let name in CKEDITOR.instances) {
|
|
||||||
//@ts-ignore
|
|
||||||
CKEDITOR.instances[name].updateElement();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check every checkbox field, so that it will be submitted (only valid fields are submitted)
|
|
||||||
$form.find("input[type=checkbox].tristate").prop('checked', true);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
beforeSubmit: function (arr, $form, options) : boolean {
|
|
||||||
//When data-with-progbar is specified, then show progressbar.
|
|
||||||
if($form.data("with-progbar") != undefined) {
|
|
||||||
ajaxUI.showProgressBar();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register all forms for loading via ajax.
|
|
||||||
*/
|
|
||||||
public registerForm()
|
|
||||||
{
|
|
||||||
|
|
||||||
let options = this.getFormOptions();
|
|
||||||
|
|
||||||
$('form').not('[data-no-ajax]').ajaxForm(options);
|
|
||||||
|
|
||||||
console.debug('Forms registered!');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submits the given form via ajax.
|
|
||||||
* @param form The form that will be submmitted.
|
|
||||||
* @param btn The btn via which the form is submitted
|
|
||||||
*/
|
|
||||||
public submitForm(form, btn = null)
|
|
||||||
{
|
|
||||||
let options = ajaxUI.getFormOptions();
|
|
||||||
|
|
||||||
if(btn) {
|
|
||||||
options.data = {};
|
|
||||||
options.data[$(btn).attr('name')] = $(btn).attr('value');
|
|
||||||
}
|
|
||||||
|
|
||||||
$(form).ajaxSubmit(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the progressbar
|
|
||||||
*/
|
|
||||||
public showProgressBar()
|
|
||||||
{
|
|
||||||
//Blur content background
|
|
||||||
$('#content').addClass('loading-content');
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
$('#progressModal').modal({
|
|
||||||
keyboard: false,
|
|
||||||
backdrop: false,
|
|
||||||
show: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hides the progressbar.
|
|
||||||
*/
|
|
||||||
public hideProgressBar()
|
|
||||||
{
|
|
||||||
// @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.
|
|
||||||
*/
|
|
||||||
public navigateTo(url : string, show_loading : boolean = 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.
|
|
||||||
*/
|
|
||||||
private onAjaxError (event, request, settings) {
|
|
||||||
'use strict';
|
|
||||||
//Ignore aborted requests.
|
|
||||||
if (request.statusText =='abort' || request.status == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Ignore ajax errors with 200 code (like the ones during 2FA authentication)
|
|
||||||
if(request.status == 200) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error("Error getting the ajax data from server!");
|
|
||||||
console.log(event);
|
|
||||||
console.log(request);
|
|
||||||
console.log(settings);
|
|
||||||
|
|
||||||
ajaxUI.hideProgressBar();
|
|
||||||
|
|
||||||
//Create error text
|
|
||||||
let title = request.statusText;
|
|
||||||
|
|
||||||
switch(request.status) {
|
|
||||||
case 500:
|
|
||||||
title = 'Internal Server Error!';
|
|
||||||
break;
|
|
||||||
case 404:
|
|
||||||
title = "Site not found!";
|
|
||||||
break;
|
|
||||||
case 403:
|
|
||||||
title = "Permission denied!";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var alert = bootbox.alert(
|
|
||||||
{
|
|
||||||
size: 'large',
|
|
||||||
message: function() {
|
|
||||||
let msg = "Error getting data from Server! <b>Status Code: " + request.status + "</b>";
|
|
||||||
|
|
||||||
msg += '<br><br><a class=\"btn btn-link\" data-toggle=\"collapse\" href=\"#iframe_div\" >' + 'Show response' + "</a>";
|
|
||||||
msg += "<div class=\" collapse\" id='iframe_div'><iframe height='512' width='100%' id='iframe'></iframe></div>";
|
|
||||||
|
|
||||||
return msg;
|
|
||||||
},
|
|
||||||
title: title,
|
|
||||||
callback: function () {
|
|
||||||
//Remove blur
|
|
||||||
$('#content').removeClass('loading-content');
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
alert.init(function (){
|
|
||||||
var dstFrame = document.getElementById('iframe');
|
|
||||||
//@ts-ignore
|
|
||||||
var dstDoc = dstFrame.contentDocument || dstFrame.contentWindow.document;
|
|
||||||
dstDoc.write(request.responseText);
|
|
||||||
dstDoc.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//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
|
|
||||||
*/
|
|
||||||
private onPopState(event)
|
|
||||||
{
|
|
||||||
let page : string = location.href;
|
|
||||||
ajaxUI.statePopped = true;
|
|
||||||
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
|
|
||||||
*/
|
|
||||||
private onAjaxComplete(responseText: string, textStatus: string, jqXHR: any)
|
|
||||||
{
|
|
||||||
console.debug("Ajax load completed!");
|
|
||||||
|
|
||||||
|
|
||||||
ajaxUI.hideProgressBar();
|
|
||||||
|
|
||||||
/* We need to do the url checking before the parseHTML, so that we dont get wrong url name, caused by scripts
|
|
||||||
in the new content */
|
|
||||||
// @ts-ignore
|
|
||||||
let url = this.url;
|
|
||||||
//Check if we were redirect to a new url, then we should use that as new url.
|
|
||||||
if(ajaxUI.xhr.responseURL) {
|
|
||||||
url = ajaxUI.xhr.responseURL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Parse response to DOM structure
|
|
||||||
//We need to preserve javascript, so the table ca
|
|
||||||
let dom = $.parseHTML(responseText, document, true);
|
|
||||||
//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
|
|
||||||
let title = extractTitle(responseText);
|
|
||||||
document.title = title;
|
|
||||||
|
|
||||||
//Push to history, if we currently arent poping an old value.
|
|
||||||
if(!ajaxUI.statePopped) {
|
|
||||||
history.pushState(null, title, url);
|
|
||||||
} else {
|
|
||||||
//Clear pop state
|
|
||||||
ajaxUI.statePopped = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Do things on the new dom
|
|
||||||
ajaxUI.registerLinks();
|
|
||||||
ajaxUI.registerForm();
|
|
||||||
ajaxUI.initDataTables();
|
|
||||||
|
|
||||||
//Trigger reload event
|
|
||||||
$(document).trigger("ajaxUI:reload");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Init all datatables marked with data-datatable based on their data-settings attribute.
|
|
||||||
*/
|
|
||||||
protected initDataTables()
|
|
||||||
{
|
|
||||||
//@ts-ignore
|
|
||||||
$($.fn.DataTable.tables()).DataTable().fixedHeader.disable();
|
|
||||||
//@ts-ignore
|
|
||||||
$($.fn.DataTable.tables()).DataTable().destroy();
|
|
||||||
|
|
||||||
//Find all datatables and init it.
|
|
||||||
let $tables = $('[data-datatable]');
|
|
||||||
$.each($tables, function(index, table) {
|
|
||||||
let $table = $(table);
|
|
||||||
let settings = $table.data('settings');
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
var promise = $('#part_list').initDataTables(settings,
|
|
||||||
{
|
|
||||||
colReorder: true,
|
|
||||||
responsive: true,
|
|
||||||
"fixedHeader": { header: $(window).width() >= 768, //Only enable fixedHeaders on devices with big screen. Fixes scrolling issues on smartphones.
|
|
||||||
headerOffset: $("#navbar").height()},
|
|
||||||
"buttons": [ {
|
|
||||||
"extend": 'colvis',
|
|
||||||
'className': 'mr-2 btn-light',
|
|
||||||
"text": "<i class='fa fa-cog'></i>"
|
|
||||||
}],
|
|
||||||
"select": $table.data('select') ?? false,
|
|
||||||
"rowCallback": function( row, data, index ) {
|
|
||||||
//Check if we have a level, then change color of this row
|
|
||||||
if (data.level) {
|
|
||||||
let style = "";
|
|
||||||
switch(data.level) {
|
|
||||||
case "emergency":
|
|
||||||
case "alert":
|
|
||||||
case "critical":
|
|
||||||
case "error":
|
|
||||||
style = "table-danger";
|
|
||||||
break;
|
|
||||||
case "warning":
|
|
||||||
style = "table-warning";
|
|
||||||
break;
|
|
||||||
case "notice":
|
|
||||||
style = "table-info";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (style){
|
|
||||||
$(row).addClass(style);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//Register links.
|
|
||||||
promise.then(function() {
|
|
||||||
ajaxUI.registerLinks();
|
|
||||||
|
|
||||||
//Set the correct title in the table.
|
|
||||||
let title = $('#part-card-header-src');
|
|
||||||
$('#part-card-header').html(title.html());
|
|
||||||
$(document).trigger('ajaxUI:dt_loaded');
|
|
||||||
|
|
||||||
|
|
||||||
if($table.data('part_table')) {
|
|
||||||
//@ts-ignore
|
|
||||||
$('#dt').on( 'select.dt deselect.dt', function ( e, dt, items ) {
|
|
||||||
let selected_elements = dt.rows({selected: true});
|
|
||||||
let count = selected_elements.count();
|
|
||||||
|
|
||||||
if(count > 0) {
|
|
||||||
$('#select_panel').removeClass('d-none');
|
|
||||||
} else {
|
|
||||||
$('#select_panel').addClass('d-none');
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#select_count').text(count);
|
|
||||||
|
|
||||||
let selected_ids_string = selected_elements.data().map(function(value, index) {
|
|
||||||
return value['id']; }
|
|
||||||
).join(",");
|
|
||||||
|
|
||||||
$('#select_ids').val(selected_ids_string);
|
|
||||||
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
//Attach event listener to update links after new page selection:
|
|
||||||
$('#dt').on('draw.dt column-visibility.dt', function() {
|
|
||||||
ajaxUI.registerLinks();
|
|
||||||
$(document).trigger('ajaxUI:dt_loaded');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
console.debug('Datatables inited.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export let ajaxUI = new AjaxUI();
|
|
|
@ -1,349 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
|
|
||||||
*
|
|
||||||
* Copyright (C) 2019 - 2020 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 Affero General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import {ajaxUI} from "./ajax_ui";
|
|
||||||
import "bootbox";
|
|
||||||
import "marked";
|
|
||||||
import * as marked from "marked";
|
|
||||||
import {parse} from "marked";
|
|
||||||
import * as ZXing from "@zxing/library";
|
|
||||||
|
|
||||||
/************************************
|
|
||||||
*
|
|
||||||
* In this file all the functions that has to be called using AjaxUIoperation are registered.
|
|
||||||
* You can use AjaxUI:start and AjaxUI:reload events.
|
|
||||||
*
|
|
||||||
***********************************/
|
|
||||||
|
|
||||||
// Add bootstrap treeview on divs with data-tree-data attribute
|
|
||||||
$(document).on("ajaxUI:start ajaxUI:reload", function() {
|
|
||||||
$("[data-tree-data]").each(function(index, element) {
|
|
||||||
let data = $(element).data('treeData');
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
$(element).treeview({
|
|
||||||
data: data,
|
|
||||||
enableLinks: false,
|
|
||||||
showIcon: false,
|
|
||||||
showBorder: true,
|
|
||||||
searchResultBackColor: '#ffc107',
|
|
||||||
searchResultColor: '#000',
|
|
||||||
showTags: true,
|
|
||||||
//@ts-ignore
|
|
||||||
wrapNode: true,
|
|
||||||
//@ts-ignore
|
|
||||||
tagsClass: 'badge badge-secondary badge-pill pull-right',
|
|
||||||
expandIcon: "fas fa-plus fa-fw fa-treeview", collapseIcon: "fas fa-minus fa-fw fa-treeview",
|
|
||||||
onNodeSelected: function(event, data) {
|
|
||||||
if(data.href) {
|
|
||||||
ajaxUI.navigateTo(data.href);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).on('initialized', function() {
|
|
||||||
$(this).treeview('collapseAll', { silent: true });
|
|
||||||
let selected = $(this).treeview('getSelected');
|
|
||||||
$(this).treeview('revealNode', [ selected, {silent: true } ]);
|
|
||||||
|
|
||||||
//Implement searching if needed.
|
|
||||||
if($(this).data('treeSearch')) {
|
|
||||||
let _this = this;
|
|
||||||
let $search = $($(this).data('treeSearch'));
|
|
||||||
$search.on( 'input', function() {
|
|
||||||
$(_this).treeview('collapseAll', { silent: true });
|
|
||||||
$(_this).treeview('search', [$search.val()]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//Add tree expand and reduce buttons if needed.
|
|
||||||
if($(this).data('treeReduce')) {
|
|
||||||
let _this = this;
|
|
||||||
let $btn = $($(this).data('treeReduce'));
|
|
||||||
$btn.click(function () {
|
|
||||||
$(_this).treeview('collapseAll');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if($(this).data('treeExpand')) {
|
|
||||||
let _this = this;
|
|
||||||
let $btn = $($(this).data('treeExpand'));
|
|
||||||
$btn.click(function () {
|
|
||||||
$(_this).treeview('expandAll');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on("ajaxUI:start ajaxUI:reload", function() {
|
|
||||||
$("[data-delete-form]").unbind('submit').submit(function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
let form = this;
|
|
||||||
|
|
||||||
//Get the submit button
|
|
||||||
let btn = document.activeElement;
|
|
||||||
|
|
||||||
let title = $(this).data("title");
|
|
||||||
let message = $(this).data("message");
|
|
||||||
|
|
||||||
bootbox.confirm({
|
|
||||||
message: message, title: title, callback: function (result) {
|
|
||||||
//If the dialog was confirmed, then submit the form.
|
|
||||||
if (result) {
|
|
||||||
ajaxUI.submitForm(form, btn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
//Register for forms with delete-buttons
|
|
||||||
$("[data-delete-btn]").parents('form').unbind('submit').submit(function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
let form = this;
|
|
||||||
//Get the submit button
|
|
||||||
let btn = document.activeElement;
|
|
||||||
|
|
||||||
let title = $(btn).data("title");
|
|
||||||
let message = $(btn).data("message");
|
|
||||||
|
|
||||||
//If not the button with the message was pressed, then simply submit the form.
|
|
||||||
if(!btn.hasAttribute('data-delete-btn')) {
|
|
||||||
ajaxUI.submitForm(form, btn);
|
|
||||||
}
|
|
||||||
|
|
||||||
bootbox.confirm({
|
|
||||||
message: message, title: title, callback: function (result) {
|
|
||||||
//If the dialog was confirmed, then submit the form.
|
|
||||||
if (result) {
|
|
||||||
ajaxUI.submitForm(form, btn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on("ajaxUI:start ajaxUI:reload", function() {
|
|
||||||
//@ts-ignore
|
|
||||||
$(".tristate").tristate( {
|
|
||||||
checked: "true",
|
|
||||||
unchecked: "false",
|
|
||||||
indeterminate: "indeterminate",
|
|
||||||
});
|
|
||||||
|
|
||||||
$('.permission_multicheckbox:checkbox').change(function() {
|
|
||||||
//Find the other checkboxes in this row, and change their value
|
|
||||||
var $row = $(this).parents('tr');
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
var new_state = $(this).tristate('state');
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
$('.tristate:checkbox', $row).tristate('state', new_state);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//Re initialize fileinputs on reload
|
|
||||||
$(document).on("ajaxUI:reload", function () {
|
|
||||||
//@ts-ignore
|
|
||||||
$(".file").fileinput();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This listener keeps track of which tab is currently selected (using hash and localstorage) and will try to open
|
|
||||||
* that tab on reload. That means that if the user changes something, he does not have to switch back to the tab
|
|
||||||
* where he was before submit.
|
|
||||||
*/
|
|
||||||
$(document).on("ajaxUI:reload ajaxUI:start", function () {
|
|
||||||
//Determine which tab should be shown (use hash if specified, otherwise use localstorage)
|
|
||||||
var $activeTab = null;
|
|
||||||
if (location.hash) {
|
|
||||||
$activeTab = $('a[href=\'' + location.hash + '\']');
|
|
||||||
} else if(localStorage.getItem('activeTab')) {
|
|
||||||
$activeTab = $('a[href="' + localStorage.getItem('activeTab') + '"]');
|
|
||||||
}
|
|
||||||
|
|
||||||
if($activeTab) {
|
|
||||||
//Findout if the tab has any parent tab we have to show before
|
|
||||||
var parents = $($activeTab).parents('.tab-pane');
|
|
||||||
parents.each(function(n) {
|
|
||||||
$('a[href="#' + $(this).attr('id') + '"]').tab('show');
|
|
||||||
});
|
|
||||||
//Finally show the active tab itself
|
|
||||||
$activeTab.tab('show');
|
|
||||||
}
|
|
||||||
|
|
||||||
$('body').on('click', 'a[data-toggle=\'tab\']', function (e) {
|
|
||||||
e.preventDefault()
|
|
||||||
var tab_name = this.getAttribute('href')
|
|
||||||
if (history.replaceState) {
|
|
||||||
history.replaceState(null, null, tab_name)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
location.hash = tab_name
|
|
||||||
}
|
|
||||||
localStorage.setItem('activeTab', tab_name)
|
|
||||||
|
|
||||||
$(this).tab('show');
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the higher resolution version of hover pictures.
|
|
||||||
*/
|
|
||||||
$(document).on("ajaxUI:reload ajaxUI:start ajaxUI:dt_loaded", function () {
|
|
||||||
|
|
||||||
$('.hoverpic[data-thumbnail]').popover({
|
|
||||||
html: true,
|
|
||||||
trigger: 'hover',
|
|
||||||
placement: 'right',
|
|
||||||
container: 'body',
|
|
||||||
content: function () {
|
|
||||||
return '<img class="img-fluid" src="' + $(this).data('thumbnail') + '" />';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
//Register typeaheads
|
|
||||||
$(document).on("ajaxUI:reload ajaxUI:start attachment:create", function () {
|
|
||||||
$('input[data-autocomplete]').each(function() {
|
|
||||||
//@ts-ignore
|
|
||||||
var engine = new Bloodhound({
|
|
||||||
//@ts-ignore
|
|
||||||
datumTokenizer: Bloodhound.tokenizers.obj.whitespace(''),
|
|
||||||
//@ts-ignore
|
|
||||||
queryTokenizer: Bloodhound.tokenizers.obj.whitespace(''),
|
|
||||||
remote: {
|
|
||||||
url: $(this).data('autocomplete'),
|
|
||||||
wildcard: 'QUERY'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
$(this).typeahead({
|
|
||||||
hint: true,
|
|
||||||
highlight: true,
|
|
||||||
minLength: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'states',
|
|
||||||
source: engine,
|
|
||||||
limit: 250,
|
|
||||||
templates: {
|
|
||||||
suggestion: function(data) {
|
|
||||||
if (typeof data === "string") {
|
|
||||||
return "<div>" + data + "</div>";
|
|
||||||
} else if(typeof data === "object" && typeof data.image === "string") {
|
|
||||||
return "<div class='row m-0'><div class='col-2 pl-0 pr-1'><img class='typeahead-image' src='" + data.image + "'/></div><div class='col-10'>" + data.name + "</div></div>"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
display: 'name',
|
|
||||||
});
|
|
||||||
|
|
||||||
//Make the typeahead input fill the container (remove block-inline attr)
|
|
||||||
$(this).parent(".twitter-typeahead").css('display', 'block');
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
$(document).on("ajaxUI:start ajaxUI:reload attachment:create", function() {
|
|
||||||
let updater = function() {
|
|
||||||
//@ts-ignore
|
|
||||||
let selected_option = $(this)[0].selectedOptions[0];
|
|
||||||
let filter_string = $(selected_option).data('filetype_filter');
|
|
||||||
//Find associated file input
|
|
||||||
|
|
||||||
let $row = $(this).parents('tr');
|
|
||||||
//Set accept filter
|
|
||||||
$('input[type="file"]', $row).prop('accept', filter_string);
|
|
||||||
};
|
|
||||||
|
|
||||||
//Register a change handler on all change listeners, and update it when the events are triggered
|
|
||||||
$('select.attachment_type_selector').change(updater).each(updater);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
$(document).on("ajaxUI:start ajaxUI:reload", function() {
|
|
||||||
function setTooltip(btn, message) {
|
|
||||||
$(btn).tooltip('hide')
|
|
||||||
.attr('data-original-title', message)
|
|
||||||
.tooltip('show');
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideTooltip(btn) {
|
|
||||||
setTimeout(function() {
|
|
||||||
$(btn).tooltip('hide');
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
//@ts-ignore
|
|
||||||
var clipboard = new ClipboardJS('.btn[data-clipboard-target], .btn[data-clipboard-text], .btn[data-clipboard-action]');
|
|
||||||
clipboard.on('success', function(e) {
|
|
||||||
setTooltip(e.trigger, 'Copied!');
|
|
||||||
hideTooltip(e.trigger);
|
|
||||||
});
|
|
||||||
|
|
||||||
clipboard.on('error', function(e) {
|
|
||||||
setTooltip(e.trigger, 'Failed!');
|
|
||||||
hideTooltip(e.trigger);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//Register U2F on page reload too...
|
|
||||||
$(document).on("ajaxUI:reload", function() {
|
|
||||||
//@ts-ignore
|
|
||||||
window.u2fauth.ready(function () {
|
|
||||||
const form = document.getElementById('u2fForm')
|
|
||||||
if (!form) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const type = form.dataset.action
|
|
||||||
|
|
||||||
if (type === 'auth') {
|
|
||||||
//@ts-ignore
|
|
||||||
u2fauth.authenticate()
|
|
||||||
} else if (type === 'reg' && form.addEventListener) {
|
|
||||||
form.addEventListener('submit', function (event) {
|
|
||||||
event.preventDefault()
|
|
||||||
//@ts-ignore
|
|
||||||
u2fauth.register()
|
|
||||||
}, false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
//Need for proper body padding, with every navbar height
|
|
||||||
$(window).resize(function () {
|
|
||||||
let height : number = $('#navbar').height() + 10;
|
|
||||||
$('body').css('padding-top', height);
|
|
||||||
$('#fixed-sidebar').css('top', height);
|
|
||||||
});
|
|
||||||
|
|
||||||
$(window).on('load', function () {
|
|
||||||
let height : number = $('#navbar').height() + 10;
|
|
||||||
$('body').css('padding-top', height);
|
|
||||||
$('#fixed-sidebar').css('top', height);
|
|
||||||
});
|
|
Loading…
Add table
Add a link
Reference in a new issue