From 2b6970d33afd75be5bfef951dc3691d492004d43 Mon Sep 17 00:00:00 2001 From: George Halkiadakis Date: Tue, 18 Apr 2023 01:11:37 +0300 Subject: admin back-office environment (skeleton); admin categories --- public/assets/js/admin/categories.js | 288 +++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 public/assets/js/admin/categories.js (limited to 'public/assets/js/admin') diff --git a/public/assets/js/admin/categories.js b/public/assets/js/admin/categories.js new file mode 100644 index 0000000..0ff2b85 --- /dev/null +++ b/public/assets/js/admin/categories.js @@ -0,0 +1,288 @@ +// Globals +// ----------------------------------------------------------------------------- +var categories = []; +var table; + + + +// Supplamentary functions +// ----------------------------------------------------------------------------- + +// array.indexOf polyfill +// --- -- -- - - - +if (!Array.prototype.indexOf) +{ + Array.prototype.indexOf = function(elt /*, from*/) + { + var len = this.length >>> 0; + + var from = Number(arguments[1]) || 0; + from = (from < 0) + ? Math.ceil(from) + : Math.floor(from); + if (from < 0) + from += len; + + for (; from < len; from++) + { + if (from in this && + this[from] === elt) + return from; + } + return -1; + }; +} + + +// function for sorting an array by 'breadcrumb' attribute +// --- -- -- - - - +function compare_breadcrumb (a,b) { + if ( a.breadcrumb < b.breadcrumb ) { return -1; } + if ( a.breadcrumb > b.breadcrumb ) { return 1; } + return 0; +} + +// return category record by category-id +// --- -- -- - - - +function category_record(id) { + var record = 0; + categories.forEach(el => { if (el.id == id) record = el; }); + + return record; +} + + +// return children of parent +// --- -- -- - - - +function childs_of_parents(list) { + // if 'list' is integer then make it an one-item list + parents = (Number.isInteger(list)) ? [ list ] : list; + + var childs = []; + + if (parents.length == 0) { return []; } + + parents.forEach( pid => { + categories.forEach( el => { if (el.parent == pid) childs.push(el.id)}); + }); + + var grandchilds = childs_of_parents(childs); + + return childs.concat(grandchilds); +} + + +// create actions html (edit and delete buttons) +// --- -- -- - - - +function create_actions_html(id) { + + var del, edit; + + del = ""; + + edit = [ + '' + ].join('\n'); + + return edit +' '+ del; +} + + + +$(document).ready(function() { + + // When document is ready + // ------------------------------------------------------------------------- + + + /** init selec2 element (used to specify parent-category) + * --- -- -- - - - + */ + $("#parent_id").select2({ + placeholder: 'Γονική Κατηγορία', + dropdownParent: $('#manageCategory'), + width: '100%', + // dropdownParent: "#manageCategory" // ref: https://github.com/select2/select2-bootstrap-theme/issues/41 + }); + + + /** init_table + * --- -- -- - - - + * get categories + * constuct categories array + * render dataTable + */ + function init_table() { + + // get all categories from server (ajax) + $.getJSON( "/admin/api/categories?exclude=0") + .done(function( json ) { + // then ... + + // reset categories + categories.length = 0; + + // construct (new) categories data + Object.keys(json).forEach( key => { + el = json[key]; + categories.push({ + id: parseInt(el.rec.id), + label: el.rec.label, + breadcrumb: el.breadcrumb.replaceAll('\t', ' / '), + parent: parseInt(el.rec.parent), + actions: create_actions_html(el.rec.id) + }); + }); + + // sort by breadcrumb + categories.sort( compare_breadcrumb ); + + // destroy previous datatable table instances + $('#dt-categories').dataTable().fnClearTable(); + $('#dt-categories').dataTable().fnDestroy(); + + // (re-)create categories datatable + table = $('#dt-categories').DataTable({ + language: { url: '/libs/DataTables/localization/Greek.json' }, + data: categories, + ordering: false, + columns: [ + { data: 'breadcrumb' }, + { data: 'actions' } + ] + }); + + }) + .fail(function( jqxhr, textStatus, error ) { + console.log( "Request Failed (" + error +")" ); + }); + + } + init_table(); // init table on first run + + + + /** When modal show-up + * ------------------------------------------------------------------------- + * ... prepare the manage-category form + * ... update select2 with possible parents + */ + $('#manageCategory').on('show.bs.modal', event => { + var button = $(event.relatedTarget); // Button that triggered the modal + var id = parseInt( button.data('id') ); // category_id from data-id + // var modal = $(this); // modal object + + // update modal literature + // --- + $('#manageCategory .modal-title').html( // modal title + (id) ? 'Ενημέρωση Κατηγορίας' : 'Δημιουργία Κατηγορίας' + ); + $('#manageCategory form input[name=id]').val( id ); // category id (hidden) + $('#manageCategory form input[name=label]').val( // category label + (id) ? category_record(id).label : "" + ); + prepare_parents_element(id); // prepare + * -> choose selected parent + * @param parents (array): array of parents + * @param selected (int): selected parent + */ + function set_parent_options(parents, selected) { + // sort parents by breadcrumb + parents.sort( compare_breadcrumb ); + + // remove any olded options from select2 + $('#parent_id option').each(function() { $(this).remove(); }); + + // first option is the root category + $('#parent_id').append('') + + // add all other parent options + parents.forEach( i => { + $('#parent_id').append(``); + }); + + if (selected == -1) { // new category; remove any parent pre-selection + $('#parent_id').val(null).trigger('change'); + + } else { // category exists; choose selected parent + $('#parent_id').val(selected).trigger('change'); + } + } + + + + + // When form is submited + // ------------------------------------------------------------------------- + + $('#manageCategory form').submit( event => { + event.preventDefault(); + + // prepare data to POST + var data = { + id: parseInt($('#manageCategory form input[name=id]').val()), + label: $('#manageCategory form input[name=label]').val(), + parent_id: parseInt($('#parent_id').select2('data')[0].id) + }; + + // select action url (add or update) + var request = '/admin/category?action=' + ((data.id == 0) ? 'add' : 'update'); + + // send POST request + $.post(request, data) + .done(function( data ) { + + $('#manageCategory').modal('hide'); // when done, close modal + + init_table(); // reload table of categories + }); + + }); + +}); -- cgit v1.2.3