Bootgrid plugin, before adding new code, do some drastic cleanups to simplify logic.

Funcitonally this is backwards compatible with the previous version, but has a beter seperation between actions/events.
This commit is contained in:
Ad Schellevis 2019-03-17 18:40:54 +01:00
parent cb8b83f56b
commit ee30b0771c

View File

@ -1,5 +1,5 @@
/**
* Copyright (C) 2015 Deciso B.V.
* Copyright (C) 2015-2019 Deciso B.V.
*
* All rights reserved.
*
@ -27,78 +27,6 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
/**
* wrapper around bootgrid component to use our defaults (including scaling footer)
* @param id
* @param sourceUrl
* @param options associative array containing extra bootgrid options or overwrites
*/
function stdBootgridUI(obj, sourceUrl, options) {
// set defaults our defaults
var gridopt = {
ajax: true,
selection: true,
multiSelect: true,
rowCount:[7,14,20,-1],
url: sourceUrl,
formatters: {
"commands": function (column, row) {
return "<button type=\"button\" class=\"btn btn-xs btn-default command-edit\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-pencil\"></span></button> " +
"<button type=\"button\" class=\"btn btn-xs btn-default command-copy\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-clone\"></span></button>" +
"<button type=\"button\" class=\"btn btn-xs btn-default command-delete\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-trash-o\"></span></button>";
},
"commandsWithInfo": function(column, row) {
return "<button type=\"button\" class=\"btn btn-xs btn-default command-info\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-info-circle\"></span></button> " +
"<button type=\"button\" class=\"btn btn-xs btn-default command-edit\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-pencil\"></span></button>" +
"<button type=\"button\" class=\"btn btn-xs btn-default command-copy\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-clone\"></span></button>" +
"<button type=\"button\" class=\"btn btn-xs btn-default command-delete\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-trash-o\"></span></button>";
},
"rowtoggle": function (column, row) {
if (parseInt(row[column.id], 2) == 1) {
return "<span style=\"cursor: pointer;\" class=\"fa fa-check-square-o command-toggle\" data-value=\"1\" data-row-id=\"" + row.uuid + "\"></span>";
} else {
return "<span style=\"cursor: pointer;\" class=\"fa fa-square-o command-toggle\" data-value=\"0\" data-row-id=\"" + row.uuid + "\"></span>";
}
},
"boolean": function (column, row) {
if (parseInt(row[column.id], 2) == 1) {
return "<span class=\"fa fa-check\" data-value=\"1\" data-row-id=\"" + row.uuid + "\"></span>";
} else {
return "<span class=\"fa fa-times\" data-value=\"0\" data-row-id=\"" + row.uuid + "\"></span>";
}
},
}
};
// merge additional options (if any)
if (options != undefined) {
$.each(options, function(key, value) {
gridopt[key] = value;
});
}
// construct a new grid
var grid = obj.bootgrid(gridopt).on("loaded.rs.jquery.bootgrid", function (e)
{
// scale footer on resize
$(this).find("tfoot td:first-child").attr('colspan',$(this).find("th").length - 1);
// invert colors if needed (check if there is a disabled field instead of an enabled field
var inverted = $(this).find("thead th[data-column-id=disabled]").length > 0;
$(this).find('tr[data-row-id]').each(function(index, entry){
['[class*="command-toggle"]', '[class*="command-boolean"]'].forEach(function (selector) {
var selected_element = $(entry).find(selector).first();
if (selected_element.length > 0) {
if ((selected_element.data("value") == "0") != inverted ) {
$(entry).addClass("text-muted");
}
}
});
});
});
return grid;
}
/**
* reload bootgrid, return to current selected page
@ -133,197 +61,307 @@ function std_bootgrid_reload(gridId) {
* @constructor
*/
$.fn.UIBootgrid = function (params) {
return this.each((function(){
var gridId = $(this).attr('id');
var gridParams = params;
if (gridParams != undefined) {
if (gridParams['search'] != undefined) {
// create new bootgrid component and link source
var grid = stdBootgridUI($(this), gridParams['search'],gridParams['options']);
var this_grid = this;
// edit dialog id to use ( see base_dialog.volt template for details)
var editDlg = $(this).attr('data-editDialog');
// link edit and delete event buttons
grid.on("loaded.rs.jquery.bootgrid", function(){
// info item
grid.find(".command-info").on("click", function(e) {
if(gridParams['info'] != undefined) {
var uuid=$(this).data("row-id");
ajaxGet(gridParams['info'] + uuid,
{}, function(data, status) {
if(status == 'success') {
var title = data['title'] || "Information";
var message = data['message'] || "A Message";
var close = data['close'] || "Close";
stdDialogInform(title, message, close, undefined, "info");
}
});
} else {
console.log("[grid] action info missing");
}
}).end();
// edit item
grid.find(".command-edit").on("click", function(e)
{
if (editDlg != undefined && gridParams['get'] != undefined) {
var uuid = $(this).data("row-id");
var urlMap = {};
urlMap['frm_' + editDlg] = gridParams['get'] + uuid;
mapDataToFormUI(urlMap).done(function () {
// update selectors
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
// clear validation errors (if any)
clearFormValidation('frm_' + editDlg);
// show dialog for pipe edit
$('#'+editDlg).modal({backdrop: 'static', keyboard: false});
// define save action
$("#btn_"+editDlg+"_save").unbind('click').click(function(){
if (gridParams['set'] != undefined) {
saveFormToEndpoint(gridParams['set']+uuid,
'frm_' + editDlg, function(){
$("#"+editDlg).modal('hide');
std_bootgrid_reload(gridId);
}, true);
} else {
console.log("[grid] action set missing")
}
});
$('#'+editDlg).trigger('opnsense_bootgrid_mapped', ['edit']);
});
} else {
console.log("[grid] action get or data-editDialog missing")
}
}).end();
// copy item, save as new
grid.find(".command-copy").on("click", function(e)
{
if (editDlg != undefined && gridParams['get'] != undefined) {
var uuid = $(this).data("row-id");
var urlMap = {};
urlMap['frm_' + editDlg] = gridParams['get'] + uuid;
mapDataToFormUI(urlMap).done(function () {
// update selectors
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
// clear validation errors (if any)
clearFormValidation('frm_' + editDlg);
// show dialog for pipe edit
$('#'+editDlg).modal({backdrop: 'static', keyboard: false});
// define save action
$("#btn_"+editDlg+"_save").unbind('click').click(function(){
if (gridParams['add'] != undefined) {
saveFormToEndpoint(gridParams['add'],
'frm_' + editDlg, function(){
$("#"+editDlg).modal('hide');
std_bootgrid_reload(gridId);
}, true);
} else {
console.log("[grid] action add missing")
}
});
$('#'+editDlg).trigger('opnsense_bootgrid_mapped', ['copy']);
});
} else {
console.log("[grid] action get or data-editDialog missing")
}
}).end();
// delete item
grid.find(".command-delete").on("click", function(e)
{
if (gridParams['del'] != undefined) {
var uuid=$(this).data("row-id");
// XXX must be replaced, cannot translate
stdDialogRemoveItem('Remove selected item?',function() {
ajaxCall(gridParams['del'] + uuid,
{},function(data,status){
// reload grid after delete
std_bootgrid_reload(gridId);
});
});
} else {
console.log("[grid] action del missing")
}
}).end();
// toggle item
grid.find(".command-toggle").on("click", function(e)
{
if (gridParams['toggle'] != undefined) {
var uuid=$(this).data("row-id");
$(this).addClass("fa-spinner fa-pulse");
ajaxCall(gridParams['toggle'] + uuid,
{},function(data,status){
// reload grid after delete
std_bootgrid_reload(gridId);
});
} else {
console.log("[grid] action toggle missing")
}
}).end();
});
// link Add new to child button with data-action = add
$(this).find("*[data-action=add]").click(function(){
if ( gridParams['get'] != undefined && gridParams['add'] != undefined) {
var urlMap = {};
urlMap['frm_' + editDlg] = gridParams['get'];
mapDataToFormUI(urlMap).done(function(){
// update selectors
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
// clear validation errors (if any)
clearFormValidation('frm_' + editDlg);
$('#'+editDlg).trigger('opnsense_bootgrid_mapped', ['add']);
});
// show dialog for edit
$('#'+editDlg).modal({backdrop: 'static', keyboard: false});
//
$("#btn_"+editDlg+"_save").unbind('click').click(function(){
saveFormToEndpoint(gridParams['add'],
'frm_' + editDlg, function(){
$("#"+editDlg).modal('hide');
std_bootgrid_reload(gridId);
}, true);
});
} else {
console.log("[grid] action add missing")
}
});
// link delete selected items action
$(this).find("*[data-action=deleteSelected]").click(function(){
if ( gridParams['del'] != undefined) {
// XXX must be replaced, cannot translate
stdDialogRemoveItem("Remove selected items?",function(){
var rows =$("#"+gridId).bootgrid('getSelectedRows');
if (rows != undefined){
var deferreds = [];
$.each(rows, function(key,uuid){
deferreds.push(ajaxCall(gridParams['del'] + uuid, {},null));
});
// refresh after load
$.when.apply(null, deferreds).done(function(){
std_bootgrid_reload(gridId);
});
}
});
} else {
console.log("[grid] action del missing")
}
});
return grid;
/**
* register commands
*/
this.getCommands = function() {
var result = {
"command-add": {
method: this_grid.command_add,
requires: ['get', 'set']
},
"command-edit": {
method: this_grid.command_edit,
requires: ['get', 'set']
},
"command-delete": {
method: this_grid.command_delete,
requires: ['del']
},
"command-copy": {
method: this_grid.command_copy,
requires: ['get', 'set']
},
"command-info": {
method: this_grid.command_info,
requires: ['get']
},
"command-toggle": {
method: this_grid.command_toggle,
requires: ['toggle']
},
"command-delete-selected": {
method: this_grid.command_delete_selected,
requires: ['del']
}
};
return result;
}
/**
* construct new bootgrid
*/
this.construct = function() {
// set defaults our defaults
var gridopt = {
ajax: true,
selection: true,
multiSelect: true,
rowCount:[7,14,20,-1],
url: params['search'],
formatters: {
"commands": function (column, row) {
return "<button type=\"button\" class=\"btn btn-xs btn-default command-edit\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-pencil\"></span></button> " +
"<button type=\"button\" class=\"btn btn-xs btn-default command-copy\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-clone\"></span></button>" +
"<button type=\"button\" class=\"btn btn-xs btn-default command-delete\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-trash-o\"></span></button>";
},
"commandsWithInfo": function(column, row) {
return "<button type=\"button\" class=\"btn btn-xs btn-default command-info\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-info-circle\"></span></button> " +
"<button type=\"button\" class=\"btn btn-xs btn-default command-edit\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-pencil\"></span></button>" +
"<button type=\"button\" class=\"btn btn-xs btn-default command-copy\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-clone\"></span></button>" +
"<button type=\"button\" class=\"btn btn-xs btn-default command-delete\" data-row-id=\"" + row.uuid + "\"><span class=\"fa fa-trash-o\"></span></button>";
},
"rowtoggle": function (column, row) {
if (parseInt(row[column.id], 2) == 1) {
return "<span style=\"cursor: pointer;\" class=\"fa fa-check-square-o command-toggle\" data-value=\"1\" data-row-id=\"" + row.uuid + "\"></span>";
} else {
return "<span style=\"cursor: pointer;\" class=\"fa fa-square-o command-toggle\" data-value=\"0\" data-row-id=\"" + row.uuid + "\"></span>";
}
},
"boolean": function (column, row) {
if (parseInt(row[column.id], 2) == 1) {
return "<span class=\"fa fa-check\" data-value=\"1\" data-row-id=\"" + row.uuid + "\"></span>";
} else {
return "<span class=\"fa fa-times\" data-value=\"0\" data-row-id=\"" + row.uuid + "\"></span>";
}
},
}
};
// merge additional options (if any)
if (params['options'] != undefined) {
$.each(params['options'], function(key, value) {
gridopt[key] = value;
});
}
// construct a new grid
var grid = this_grid.bootgrid(gridopt).on("loaded.rs.jquery.bootgrid", function (e)
{
// scale footer on resize
$(this).find("tfoot td:first-child").attr('colspan',$(this).find("th").length - 1);
// invert colors if needed (check if there is a disabled field instead of an enabled field
var inverted = $(this).find("thead th[data-column-id=disabled]").length > 0;
$(this).find('tr[data-row-id]').each(function(index, entry){
['[class*="command-toggle"]', '[class*="command-boolean"]'].forEach(function (selector) {
var selected_element = $(entry).find(selector).first();
if (selected_element.length > 0) {
if ((selected_element.data("value") == "0") != inverted ) {
$(entry).addClass("text-muted");
}
}
});
});
});
return grid;
}
/**
* add event
*/
this.command_add = function(event) {
var editDlg = this_grid.attr('data-editDialog');
if (editDlg !== undefined) {
var urlMap = {};
urlMap['frm_' + editDlg] = params['get'];
mapDataToFormUI(urlMap).done(function(){
// update selectors
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
// clear validation errors (if any)
clearFormValidation('frm_' + editDlg);
$('#'+editDlg).trigger('opnsense_bootgrid_mapped', ['add']);
});
// show dialog for edit
$('#'+editDlg).modal({backdrop: 'static', keyboard: false});
//
$("#btn_"+editDlg+"_save").unbind('click').click(function(){
saveFormToEndpoint(params['add'],
'frm_' + editDlg, function(){
$("#"+editDlg).modal('hide');
std_bootgrid_reload(this_grid.attr('id'));
}, true);
});
} else {
console.log("[grid] action get or data-editDialog missing")
}
}
/**
* edit event
*/
this.command_edit = function(event) {
var editDlg = this_grid.attr('data-editDialog');
if (editDlg !== undefined) {
var uuid = $(this).data("row-id");
var urlMap = {};
urlMap['frm_' + editDlg] = params['get'] + uuid;
mapDataToFormUI(urlMap).done(function () {
// update selectors
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
// clear validation errors (if any)
clearFormValidation('frm_' + editDlg);
// show dialog for pipe edit
$('#'+editDlg).modal({backdrop: 'static', keyboard: false});
// define save action
$("#btn_"+editDlg+"_save").unbind('click').click(function(){
saveFormToEndpoint(params['set']+uuid,
'frm_' + editDlg, function(){
$("#"+editDlg).modal('hide');
std_bootgrid_reload(this_grid.attr('id'));
}, true);
});
$('#'+editDlg).trigger('opnsense_bootgrid_mapped', ['edit']);
});
} else {
console.log("[grid] action get or data-editDialog missing")
}
}
/**
* delete event
*/
this.command_delete = function(event) {
var uuid=$(this).data("row-id");
// XXX must be replaced, cannot translate
stdDialogRemoveItem('Remove selected item?',function() {
ajaxCall(params['del'] + uuid, {},function(data,status){
// reload grid after delete
std_bootgrid_reload(this_grid.attr('id'));
});
});
}
/**
* delete selected event
*/
this.command_delete_selected = function(event) {
// XXX must be replaced, cannot translate
stdDialogRemoveItem("Remove selected items?",function(){
var rows =$("#"+this_grid.attr('id')).bootgrid('getSelectedRows');
if (rows != undefined){
var deferreds = [];
$.each(rows, function(key,uuid){
deferreds.push(ajaxCall(params['del'] + uuid, {},null));
});
// refresh after load
$.when.apply(null, deferreds).done(function(){
std_bootgrid_reload(this_grid.attr('id'));
});
}
});
}
/**
* copy event
*/
this.command_copy = function(event) {
var editDlg = this_grid.attr('data-editDialog');
if (editDlg !== undefined) {
var uuid = $(this).data("row-id");
var urlMap = {};
urlMap['frm_' + editDlg] = params['get'] + uuid;
mapDataToFormUI(urlMap).done(function () {
// update selectors
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
// clear validation errors (if any)
clearFormValidation('frm_' + editDlg);
// show dialog for pipe edit
$('#'+editDlg).modal({backdrop: 'static', keyboard: false});
// define save action
$("#btn_"+editDlg+"_save").unbind('click').click(function(){
saveFormToEndpoint(params['add'],
'frm_' + editDlg, function(){
$("#"+editDlg).modal('hide');
std_bootgrid_reload(this_grid.attr('id'));
}, true);
});
$('#'+editDlg).trigger('opnsense_bootgrid_mapped', ['copy']);
});
} else {
console.log("[grid] action get or data-editDialog missing")
}
}
/**
* info event
*/
this.command_info = function(event) {
var uuid=$(this).data("row-id");
ajaxGet(params['info'] + uuid, {}, function(data, status) {
if(status == 'success') {
var title = data['title'] || "Information";
var message = data['message'] || "A Message";
var close = data['close'] || "Close";
stdDialogInform(title, message, close, undefined, "info");
}
});
}
/**
* toggle event
*/
this.command_toggle = function(event) {
var uuid=$(this).data("row-id");
$(this).addClass("fa-spinner fa-pulse");
ajaxCall(params['toggle'] + uuid, {},function(data,status){
// reload grid after delete
std_bootgrid_reload(this_grid.attr('id'));
});
}
//
return this.each((function(){
// since we start using simple class selectors for our commands, we need to make sure "add" and
// "delete selected" actions are properly marked
$(this).find("*[data-action=add]").addClass('command-add');
$(this).find("*[data-action=deleteSelected]").addClass('command-delete-selected');
if (params != undefined && params['search'] != undefined) {
// create new bootgrid component and link source
var grid = this_grid.construct();
// edit dialog id to use ( see base_dialog.volt template for details)
var editDlg = $(this).attr('data-editDialog');
// link edit and delete event buttons
grid.on("loaded.rs.jquery.bootgrid", function(){
// hook all events
var commands = this_grid.getCommands();
Object.keys(commands).map(function (k) {
var has_option = true;
for (var i=0; i < commands[k]['requires'].length; i++) {
if (!(commands[k]['requires'][i] in params)) {
has_option = false;
}
}
if (has_option) {
grid.find("."+k).unbind('click').on("click", commands[k].method);
} else if ($("."+k).length > 0) {
console.log("not all requirements met to link " + k);
}
});
});
return grid;
}
}));
};