mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-24 18:58:46 +02:00
Added datatables with turbo frames.
This commit is contained in:
parent
41e0b251a9
commit
fed1621a58
5 changed files with 308 additions and 180 deletions
|
@ -57,21 +57,12 @@ require('bootstrap');
|
||||||
import "patternfly-bootstrap-treeview";
|
import "patternfly-bootstrap-treeview";
|
||||||
|
|
||||||
import "./sidebar"
|
import "./sidebar"
|
||||||
|
import "./datatables";
|
||||||
|
import "./register_events";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
//require( 'jszip' );
|
|
||||||
//#require( 'pdfmake' );
|
require('bootstrap-select');
|
||||||
require( 'datatables.net-bs4' );
|
|
||||||
require( 'datatables.net-buttons-bs4' );
|
|
||||||
require( 'datatables.net-buttons/js/buttons.colVis.js' );
|
|
||||||
//require( 'datatables.net-buttons/js/buttons.html5.js' );
|
|
||||||
//require( 'datatables.net-buttons/js/buttons.print.js' );
|
|
||||||
require( 'datatables.net-fixedheader-bs4' );
|
|
||||||
require( 'datatables.net-select-bs4' );
|
|
||||||
require('datatables.net-colreorder-bs4');
|
|
||||||
require('datatables.net-responsive-bs4');
|
|
||||||
require('datatables.net-responsive-bs4/css/responsive.bootstrap4.css');
|
|
||||||
require('bootstrap-select');
|
|
||||||
require('jquery-form');
|
require('jquery-form');
|
||||||
require('corejs-typeahead/dist/typeahead.bundle.min');
|
require('corejs-typeahead/dist/typeahead.bundle.min');
|
||||||
window.Bloodhound = require('corejs-typeahead/dist/bloodhound.js');
|
window.Bloodhound = require('corejs-typeahead/dist/bloodhound.js');
|
||||||
|
|
|
@ -1,185 +1,122 @@
|
||||||
/**
|
"use strict";
|
||||||
* Symfony DataTables Bundle
|
|
||||||
* (c) Omines Internetbureau B.V. - https://omines.nl/
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*
|
|
||||||
* @author Niels Keurentjes <niels.keurentjes@omines.com>
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function($) {
|
import 'datatables.net-bs4';
|
||||||
/**
|
import 'datatables.net-buttons-bs4';
|
||||||
* Initializes the datatable dynamically.
|
import 'datatables.net-buttons/js/buttons.colVis.js';
|
||||||
*/
|
//require( 'datatables.net-buttons/js/buttons.html5.js' );
|
||||||
$.fn.initDataTables = function(config, options) {
|
//require( 'datatables.net-buttons/js/buttons.print.js' );
|
||||||
|
import 'datatables.net-fixedheader-bs4';
|
||||||
|
import 'datatables.net-select-bs4';
|
||||||
|
import 'datatables.net-colreorder-bs4';
|
||||||
|
import 'datatables.net-responsive-bs4';
|
||||||
|
import 'datatables.net-responsive-bs4/css/responsive.bootstrap4.css';
|
||||||
|
import './lib/datatables';
|
||||||
|
|
||||||
//Update default used url, so it reflects the current location (useful on single side apps)
|
|
||||||
//CHANGED jbtronics: Preserve the get parameters (needed so we can pass additional params to query)
|
|
||||||
$.fn.initDataTables.defaults.url = window.location.origin + window.location.pathname + window.location.search;
|
|
||||||
|
|
||||||
var root = this,
|
const DatatablesHelper = class {
|
||||||
config = $.extend({}, $.fn.initDataTables.defaults, config),
|
constructor() {
|
||||||
state = ''
|
this.registerLoadHandler(() => this.initDataTables());
|
||||||
;
|
}
|
||||||
|
|
||||||
// Load page state if needed
|
registerLoadHandler(fn) {
|
||||||
switch (config.state) {
|
document.addEventListener('turbo:load', fn);
|
||||||
case 'fragment':
|
}
|
||||||
state = window.location.hash;
|
|
||||||
break;
|
|
||||||
case 'query':
|
|
||||||
state = window.location.search;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
state = (state.length > 1 ? deparam(state.substr(1)) : {});
|
|
||||||
var persistOptions = config.state === 'none' ? {} : {
|
|
||||||
stateSave: true,
|
|
||||||
stateLoadCallback: function(s, cb) {
|
|
||||||
// Only need stateSave to expose state() function as loading lazily is not possible otherwise
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Promise((fulfill, reject) => {
|
initDataTables()
|
||||||
// Perform initial load
|
{
|
||||||
$.ajax(config.url, {
|
//@ts-ignore
|
||||||
method: config.method,
|
$($.fn.DataTable.tables()).DataTable().fixedHeader.disable();
|
||||||
data: {
|
//@ts-ignore
|
||||||
_dt: config.name,
|
$($.fn.DataTable.tables()).DataTable().destroy();
|
||||||
_init: true
|
|
||||||
}
|
|
||||||
}).done(function(data) {
|
|
||||||
var baseState;
|
|
||||||
|
|
||||||
// Merge all options from different sources together and add the Ajax loader
|
//Find all datatables and init it.
|
||||||
var dtOpts = $.extend({}, data.options, config.options, options, persistOptions, {
|
let $tables = $('[data-datatable]');
|
||||||
ajax: function (request, drawCallback, settings) {
|
$.each($tables, function(index, table) {
|
||||||
if (data) {
|
let $table = $(table);
|
||||||
data.draw = request.draw;
|
let settings = $table.data('settings');
|
||||||
drawCallback(data);
|
|
||||||
data = null;
|
//@ts-ignore
|
||||||
if (Object.keys(state).length && dt.state != null) {
|
var promise = $('#part_list').initDataTables(settings,
|
||||||
var merged = $.extend(true, {}, dt.state(), state);
|
{
|
||||||
dt
|
colReorder: true,
|
||||||
.order(merged.order)
|
responsive: true,
|
||||||
.search(merged.search.search)
|
"fixedHeader": { header: $(window).width() >= 768, //Only enable fixedHeaders on devices with big screen. Fixes scrolling issues on smartphones.
|
||||||
.page.len(merged.length)
|
headerOffset: $("#navbar").height()},
|
||||||
.page(merged.start / merged.length)
|
"buttons": [ {
|
||||||
.draw(false);
|
"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);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
request._dt = config.name;
|
|
||||||
$.ajax(config.url, {
|
|
||||||
method: config.method,
|
|
||||||
data: request
|
|
||||||
}).done(function(data) {
|
|
||||||
drawCallback(data);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
root.html(data.template);
|
//Register links.
|
||||||
dt = $('table', root).DataTable(dtOpts);
|
promise.then(function() {
|
||||||
if (config.state !== 'none') {
|
//ajaxUI.registerLinks();
|
||||||
dt.on('draw.dt', function(e) {
|
|
||||||
var data = $.param(dt.state()).split('&');
|
|
||||||
|
|
||||||
// First draw establishes state, subsequent draws run diff on the first
|
//Set the correct title in the table.
|
||||||
if (!baseState) {
|
let title = $('#part-card-header-src');
|
||||||
baseState = data;
|
$('#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 {
|
} else {
|
||||||
var diff = data.filter(el => { return baseState.indexOf(el) === -1 && el.indexOf('time=') !== 0; });
|
$('#select_panel').addClass('d-none');
|
||||||
switch (config.state) {
|
|
||||||
case 'fragment':
|
|
||||||
history.replaceState(null, null, window.location.origin + window.location.pathname + window.location.search
|
|
||||||
+ '#' + decodeURIComponent(diff.join('&')));
|
|
||||||
break;
|
|
||||||
case 'query':
|
|
||||||
history.replaceState(null, null, window.location.origin + window.location.pathname
|
|
||||||
+ '?' + decodeURIComponent(diff.join('&') + window.location.hash));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
$('#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);
|
||||||
|
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
fulfill(dt);
|
//Attach event listener to update links after new page selection:
|
||||||
}).fail(function(xhr, cause, msg) {
|
$('#dt').on('draw.dt column-visibility.dt', function() {
|
||||||
console.error('DataTables request failed: ' + msg);
|
//ajaxUI.registerLinks();
|
||||||
reject(cause);
|
$(document).trigger('ajaxUI:dt_loaded');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
console.debug('Datatables inited.');
|
||||||
* Provide global component defaults.
|
|
||||||
*/
|
|
||||||
$.fn.initDataTables.defaults = {
|
|
||||||
method: 'POST',
|
|
||||||
state: 'fragment',
|
|
||||||
url: window.location.origin + window.location.pathname
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a querystring to a proper array - reverses $.param
|
|
||||||
*/
|
|
||||||
function deparam(params, coerce) {
|
|
||||||
var obj = {},
|
|
||||||
coerce_types = {'true': !0, 'false': !1, 'null': null};
|
|
||||||
$.each(params.replace(/\+/g, ' ').split('&'), function (j, v) {
|
|
||||||
var param = v.split('='),
|
|
||||||
key = decodeURIComponent(param[0]),
|
|
||||||
val,
|
|
||||||
cur = obj,
|
|
||||||
i = 0,
|
|
||||||
keys = key.split(']['),
|
|
||||||
keys_last = keys.length - 1;
|
|
||||||
|
|
||||||
if (/\[/.test(keys[0]) && /\]$/.test(keys[keys_last])) {
|
|
||||||
keys[keys_last] = keys[keys_last].replace(/\]$/, '');
|
|
||||||
keys = keys.shift().split('[').concat(keys);
|
|
||||||
keys_last = keys.length - 1;
|
|
||||||
} else {
|
|
||||||
keys_last = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (param.length === 2) {
|
|
||||||
val = decodeURIComponent(param[1]);
|
|
||||||
|
|
||||||
if (coerce) {
|
|
||||||
val = val && !isNaN(val) ? +val // number
|
|
||||||
: val === 'undefined' ? undefined // undefined
|
|
||||||
: coerce_types[val] !== undefined ? coerce_types[val] // true, false, null
|
|
||||||
: val; // string
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keys_last) {
|
|
||||||
for (; i <= keys_last; i++) {
|
|
||||||
key = keys[i] === '' ? cur.length : keys[i];
|
|
||||||
cur = cur[key] = i < keys_last
|
|
||||||
? cur[key] || (keys[i + 1] && isNaN(keys[i + 1]) ? {} : [])
|
|
||||||
: val;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if ($.isArray(obj[key])) {
|
|
||||||
obj[key].push(val);
|
|
||||||
} else if (obj[key] !== undefined) {
|
|
||||||
obj[key] = [obj[key], val];
|
|
||||||
} else {
|
|
||||||
obj[key] = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (key) {
|
|
||||||
obj[key] = coerce
|
|
||||||
? undefined
|
|
||||||
: '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
}($));
|
}
|
||||||
|
|
||||||
|
export default new DatatablesHelper();
|
185
assets/js/lib/datatables.js
Normal file
185
assets/js/lib/datatables.js
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
/**
|
||||||
|
* Symfony DataTables Bundle
|
||||||
|
* (c) Omines Internetbureau B.V. - https://omines.nl/
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*
|
||||||
|
* @author Niels Keurentjes <niels.keurentjes@omines.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function($) {
|
||||||
|
/**
|
||||||
|
* Initializes the datatable dynamically.
|
||||||
|
*/
|
||||||
|
$.fn.initDataTables = function(config, options) {
|
||||||
|
|
||||||
|
//Update default used url, so it reflects the current location (useful on single side apps)
|
||||||
|
//CHANGED jbtronics: Preserve the get parameters (needed so we can pass additional params to query)
|
||||||
|
$.fn.initDataTables.defaults.url = window.location.origin + window.location.pathname + window.location.search;
|
||||||
|
|
||||||
|
var root = this,
|
||||||
|
config = $.extend({}, $.fn.initDataTables.defaults, config),
|
||||||
|
state = ''
|
||||||
|
;
|
||||||
|
|
||||||
|
// Load page state if needed
|
||||||
|
switch (config.state) {
|
||||||
|
case 'fragment':
|
||||||
|
state = window.location.hash;
|
||||||
|
break;
|
||||||
|
case 'query':
|
||||||
|
state = window.location.search;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
state = (state.length > 1 ? deparam(state.substr(1)) : {});
|
||||||
|
var persistOptions = config.state === 'none' ? {} : {
|
||||||
|
stateSave: true,
|
||||||
|
stateLoadCallback: function(s, cb) {
|
||||||
|
// Only need stateSave to expose state() function as loading lazily is not possible otherwise
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise((fulfill, reject) => {
|
||||||
|
// Perform initial load
|
||||||
|
$.ajax(config.url, {
|
||||||
|
method: config.method,
|
||||||
|
data: {
|
||||||
|
_dt: config.name,
|
||||||
|
_init: true
|
||||||
|
}
|
||||||
|
}).done(function(data) {
|
||||||
|
var baseState;
|
||||||
|
|
||||||
|
// Merge all options from different sources together and add the Ajax loader
|
||||||
|
var dtOpts = $.extend({}, data.options, config.options, options, persistOptions, {
|
||||||
|
ajax: function (request, drawCallback, settings) {
|
||||||
|
if (data) {
|
||||||
|
data.draw = request.draw;
|
||||||
|
drawCallback(data);
|
||||||
|
data = null;
|
||||||
|
if (Object.keys(state).length && dt.state != null) {
|
||||||
|
var merged = $.extend(true, {}, dt.state(), state);
|
||||||
|
dt
|
||||||
|
.order(merged.order)
|
||||||
|
.search(merged.search.search)
|
||||||
|
.page.len(merged.length)
|
||||||
|
.page(merged.start / merged.length)
|
||||||
|
.draw(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
request._dt = config.name;
|
||||||
|
$.ajax(config.url, {
|
||||||
|
method: config.method,
|
||||||
|
data: request
|
||||||
|
}).done(function(data) {
|
||||||
|
drawCallback(data);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
root.html(data.template);
|
||||||
|
dt = $('table', root).DataTable(dtOpts);
|
||||||
|
if (config.state !== 'none') {
|
||||||
|
dt.on('draw.dt', function(e) {
|
||||||
|
var data = $.param(dt.state()).split('&');
|
||||||
|
|
||||||
|
// First draw establishes state, subsequent draws run diff on the first
|
||||||
|
if (!baseState) {
|
||||||
|
baseState = data;
|
||||||
|
} else {
|
||||||
|
var diff = data.filter(el => { return baseState.indexOf(el) === -1 && el.indexOf('time=') !== 0; });
|
||||||
|
switch (config.state) {
|
||||||
|
case 'fragment':
|
||||||
|
history.replaceState(null, null, window.location.origin + window.location.pathname + window.location.search
|
||||||
|
+ '#' + decodeURIComponent(diff.join('&')));
|
||||||
|
break;
|
||||||
|
case 'query':
|
||||||
|
history.replaceState(null, null, window.location.origin + window.location.pathname
|
||||||
|
+ '?' + decodeURIComponent(diff.join('&') + window.location.hash));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fulfill(dt);
|
||||||
|
}).fail(function(xhr, cause, msg) {
|
||||||
|
console.error('DataTables request failed: ' + msg);
|
||||||
|
reject(cause);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide global component defaults.
|
||||||
|
*/
|
||||||
|
$.fn.initDataTables.defaults = {
|
||||||
|
method: 'POST',
|
||||||
|
state: 'fragment',
|
||||||
|
url: window.location.origin + window.location.pathname
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a querystring to a proper array - reverses $.param
|
||||||
|
*/
|
||||||
|
function deparam(params, coerce) {
|
||||||
|
var obj = {},
|
||||||
|
coerce_types = {'true': !0, 'false': !1, 'null': null};
|
||||||
|
$.each(params.replace(/\+/g, ' ').split('&'), function (j, v) {
|
||||||
|
var param = v.split('='),
|
||||||
|
key = decodeURIComponent(param[0]),
|
||||||
|
val,
|
||||||
|
cur = obj,
|
||||||
|
i = 0,
|
||||||
|
keys = key.split(']['),
|
||||||
|
keys_last = keys.length - 1;
|
||||||
|
|
||||||
|
if (/\[/.test(keys[0]) && /\]$/.test(keys[keys_last])) {
|
||||||
|
keys[keys_last] = keys[keys_last].replace(/\]$/, '');
|
||||||
|
keys = keys.shift().split('[').concat(keys);
|
||||||
|
keys_last = keys.length - 1;
|
||||||
|
} else {
|
||||||
|
keys_last = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param.length === 2) {
|
||||||
|
val = decodeURIComponent(param[1]);
|
||||||
|
|
||||||
|
if (coerce) {
|
||||||
|
val = val && !isNaN(val) ? +val // number
|
||||||
|
: val === 'undefined' ? undefined // undefined
|
||||||
|
: coerce_types[val] !== undefined ? coerce_types[val] // true, false, null
|
||||||
|
: val; // string
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keys_last) {
|
||||||
|
for (; i <= keys_last; i++) {
|
||||||
|
key = keys[i] === '' ? cur.length : keys[i];
|
||||||
|
cur = cur[key] = i < keys_last
|
||||||
|
? cur[key] || (keys[i + 1] && isNaN(keys[i + 1]) ? {} : [])
|
||||||
|
: val;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if ($.isArray(obj[key])) {
|
||||||
|
obj[key].push(val);
|
||||||
|
} else if (obj[key] !== undefined) {
|
||||||
|
obj[key] = [obj[key], val];
|
||||||
|
} else {
|
||||||
|
obj[key] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (key) {
|
||||||
|
obj[key] = coerce
|
||||||
|
? undefined
|
||||||
|
: '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}($));
|
17
assets/js/register_events.js
Normal file
17
assets/js/register_events.js
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const RegisterEventHelper = class {
|
||||||
|
constructor() {
|
||||||
|
this.registerToasts();
|
||||||
|
}
|
||||||
|
|
||||||
|
registerLoadHandler(fn) {
|
||||||
|
document.addEventListener('turbo:load', fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
registerToasts() {
|
||||||
|
this.registerLoadHandler(() => $(".toast").toast('show'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new RegisterEventHelper();
|
|
@ -1,7 +1,5 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import * as Turbo from '@hotwired/turbo';
|
|
||||||
|
|
||||||
const SidebarHelper = class {
|
const SidebarHelper = class {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.BASE = $("body").data("base-url");
|
this.BASE = $("body").data("base-url");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue