diff options
| -rw-r--r-- | Dockerfile | 3 | ||||
| -rw-r--r-- | docker/bin/docker-entrypoint.sh | 4 | ||||
| -rw-r--r-- | public/app/controllers/admin/Course_admin.php | 93 | ||||
| -rw-r--r-- | public/app/controllers/admin/Users_admin.php | 42 | ||||
| -rw-r--r-- | public/app/models/admin/Privilege_model.php | 42 | ||||
| -rw-r--r-- | public/app/models/cms/Course_model.php | 3 | ||||
| -rw-r--r-- | public/app/routes/backend.php | 81 | ||||
| -rw-r--r-- | public/app/views/admin/admin-menu.php | 4 | ||||
| -rw-r--r-- | public/app/views/admin/categories.php | 16 | ||||
| -rw-r--r-- | public/app/views/admin/new_lesson.php | 144 | ||||
| -rw-r--r-- | public/app/views/admin/privileges.php | 93 | ||||
| -rw-r--r-- | public/assets/css/overides.css | 45 | ||||
| -rw-r--r-- | public/assets/js/admin/categories.js | 4 | ||||
| -rw-r--r-- | public/assets/js/admin/privileges.js | 291 | ||||
| -rwxr-xr-x | public/cache/.gitkeep | 0 |
15 files changed, 828 insertions, 37 deletions
@@ -78,8 +78,7 @@ RUN locale-gen # Manage permitions in specific directories # ------------------------------------------------------------------------------ # (make local storage directories writable) -# RUN chown -R www-data:www-data /var/www -RUN chmod -R 757 /var/www/public/cache +RUN chown -R www-data:www-data /var/www RUN chmod -R 757 /var/www/storage diff --git a/docker/bin/docker-entrypoint.sh b/docker/bin/docker-entrypoint.sh index a01f3a3..f421d80 100644 --- a/docker/bin/docker-entrypoint.sh +++ b/docker/bin/docker-entrypoint.sh @@ -4,8 +4,6 @@ # ------------------------------------------------------------------------------ # grand to 'cache' directory writable permissions # set file-cache directory to apache's user ownership -chmod -R 755 /var/www/public/cache -chown -R www-data:www-data /var/www/public/cache chmod -R 755 /var/www/storage chown -R www-data:www-data /var/www/storage @@ -24,4 +22,4 @@ cp /var/www/docker/config/composer-naked.json /var/www/composer.json # start apache # ------------------------------------------------------------------------------ # End with running the original command -exec /usr/sbin/apache2ctl -D FOREGROUND
\ No newline at end of file +exec /usr/sbin/apache2ctl -D FOREGROUND diff --git a/public/app/controllers/admin/Course_admin.php b/public/app/controllers/admin/Course_admin.php new file mode 100644 index 0000000..0e34e00 --- /dev/null +++ b/public/app/controllers/admin/Course_admin.php @@ -0,0 +1,93 @@ +<?php + +namespace app\controllers\admin; + +use Registry; +use Render; +use app\models\cms\Course_model; + +class Course_admin { + + + /** breadcrumbs + * --- + * responds to ajax GET: /admin/api/categories + */ + public static function breadcrumbs() + { + $tree = proxy( // cache-get categories + [\app\models\cms\Course_model::class, 'category_tree'], + [], CACHE_ROOT_TTL + ); + $breadcrumbs = proxy( // cache-get breadcrumbs + [\app\models\cms\Course_model::class, 'breadcrumbs'], + [$tree], CACHE_ROOT_TTL + ); + Render::json($breadcrumbs); // send as json + } + + /** add course + * --- + * @param void (get data from POST) + */ + public static function add_course() + { + // insert new category; id = new category id + $id = Registry::use('database')->query( + "INSERT INTO course (parent_id, label) VALUES (:parent, :label)", + [ + ':parent' => Registry::get('REQUEST')->POST['parent_id'], + ':label' => Registry::get('REQUEST')->POST['label'] + ] + )->lastInsertID(); + + $cache = self::update_courses_cache(); // update category caches + return $cache['breadcrumbs']; // return + } + + + /** update course + * --- + * @param void (get data from POST) + */ + public static function update_course() + { + Registry::use('database')->query( + "UPDATE course SET parent_id = :parent, label = :label + WHERE id = :id", + [ + ':id' => Registry::get('REQUEST')->POST['id'], + ':parent' => Registry::get('REQUEST')->POST['parent_id'], + ':label' => Registry::get('REQUEST')->POST['label'] + ] + ); + $cache = self::update_courses_cache(); + return $cache['breadcrumbs']; + } + + + /** update courses cache + * --- -- -- - - - + * Shall run if anything changes to courses + * + * @param void + * @return (array): the two course caches + */ + public static function update_courses_cache() + { + $tree = proxy( // cache-get categories + [\app\models\cms\Course_model::class, 'category_tree'], + [], CACHE_ROOT_TTL, PROXY_IGNORE_CACHE + ); + $breadcrumbs = proxy( // cache-get breadcrumbs + [\app\models\cms\Course_model::class, 'breadcrumbs'], + [$tree], CACHE_ROOT_TTL, PROXY_IGNORE_CACHE + ); + + return [ + 'tree' => $tree, + 'breadcrumbs' => $breadcrumbs + ]; + } + +}
\ No newline at end of file diff --git a/public/app/controllers/admin/Users_admin.php b/public/app/controllers/admin/Users_admin.php new file mode 100644 index 0000000..4e335c1 --- /dev/null +++ b/public/app/controllers/admin/Users_admin.php @@ -0,0 +1,42 @@ +<?php + +namespace app\controllers\admin; + +use Registry; +use Render; + + +class Users_admin { + + /** privileges + * --- + * get all privileges + * + * @param void + * @return privileges (array) + */ + public static function privileges() + { + return Registry::use('database')->runQuery( + "SELECT * FROM privilege",[] + ); + } + + /** edit privileges + * --- + */ + public static function edit_privileges() + { + // TODO: ... + } + + + /** update course + * --- + */ + public static function update_course() + { + // TODO: ... + } + +}
\ No newline at end of file diff --git a/public/app/models/admin/Privilege_model.php b/public/app/models/admin/Privilege_model.php new file mode 100644 index 0000000..c385484 --- /dev/null +++ b/public/app/models/admin/Privilege_model.php @@ -0,0 +1,42 @@ +<?php + +namespace app\models\admin; + +use Registry; +use Render; + + +class Privilege_model { + + /** privileges + * --- + * get all privileges + * + * @param void + * @return privileges (array) + */ + public static function privileges() + { + return Registry::use('database')->runQuery( + "SELECT * FROM privilege",[] + ); + } + + /** edit privileges + * --- + */ + public static function edit_privileges() + { + // TODO: ... + } + + + /** update course + * --- + */ + public static function update_course() + { + // TODO: ... + } + +}
\ No newline at end of file diff --git a/public/app/models/cms/Course_model.php b/public/app/models/cms/Course_model.php index 4fb49c0..4740a4f 100644 --- a/public/app/models/cms/Course_model.php +++ b/public/app/models/cms/Course_model.php @@ -14,7 +14,7 @@ class Course_model { public static function get_categories() { return Registry::use('database')->runQuery( - "SELECT * FROM course", + "SELECT * FROM course ORDER BY `order`", [] ); } @@ -74,6 +74,7 @@ class Course_model { 'rec' => [ 'id' => $rec['id'], 'label' => $rec['label'], + 'order' => $rec['order'], 'parent' => $rec['parent_id'] ], 'childs' => self::to_tree($dataset, $child) // recursively diff --git a/public/app/routes/backend.php b/public/app/routes/backend.php index 700fa14..5356407 100644 --- a/public/app/routes/backend.php +++ b/public/app/routes/backend.php @@ -1,7 +1,8 @@ <?php use app\controllers\Auth; -use app\models\cms\Course_model; +use app\controllers\admin\Course_admin; +use app\models\admin\Privilege_model; // admin lessons // --- @@ -15,6 +16,9 @@ Route::add('/admin/lessons', function () { // admin cateogies +// ----------------------------------------------------------------------------- + +// manage categories page // --- Route::add('/admin/categories', function () { Auth::allowRoles([1, 2, 3]); @@ -25,17 +29,70 @@ Route::add('/admin/categories', function () { }); +// ajax: get all categories (courses; with breadcrumbs) +// --- Route::add('/admin/api/categories', function () { + Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles + Course_admin::breadcrumbs(); +}); + + +// ajax: add new category (course) +// --- +Route::add('/admin/api/category/add', function () { + Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles + Course_admin::add_course(); + }, + 'post' +); + +// ajax: edit category (course) +// --- +Route::add('/admin/api/category/update', function () { + Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles + Course_admin::update_course(); + }, + 'post' +); + + +// admin privileges +// ----------------------------------------------------------------------------- + +// manage privileges page +// --- +Route::add('/admin/privileges', function () { Auth::allowRoles([1, 2, 3]); - $tree = proxy( - [\app\models\cms\Course_model::class, 'category_tree'], + Render::view('admin/skeleton', [ + 'title' => 'Διαχείριση Δικαιωμάτων Πρόσβασης', + 'action' => 'privileges', + ]); +}); + +// ajax: get all privileges (courses; with breadcrumbs) +// use proxy (cache results); send as json +// --- +Route::add('/admin/api/privileges', function () { + Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles + Render::json( proxy( + [\app\models\admin\Privilege_model::class, 'privileges'], [], CACHE_ROOT_TTL - ); - - $breadcrumbs = proxy( - [\app\models\cms\Course_model::class, 'breadcrumbs'], - [$tree], CACHE_ROOT_TTL - ); - // $breadcrumbs = Course_model::breadcrumbs($tree); - Render::json($breadcrumbs); -});
\ No newline at end of file + )); +}); + +// add privilege + +// update privilege + + + +// new lesson +// ----------------------------------------------------------------------------- +Route::add('/admin/new_lesson', function () { + Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles + Render::view('admin/skeleton', [ + 'title' => 'Νέο Μάθημα', + 'action' => 'new_lesson' + ]); +}); + diff --git a/public/app/views/admin/admin-menu.php b/public/app/views/admin/admin-menu.php index 813420d..d7e7b09 100644 --- a/public/app/views/admin/admin-menu.php +++ b/public/app/views/admin/admin-menu.php @@ -16,11 +16,11 @@ $admin_options = [ - 'new' => 'Νέο Μάθημα', + 'new_lesson' => 'Νέο Μάθημα', 'lessons' => 'Μαθήματα', 'categories' => 'Κατηγορίες', 'pages' => 'Σελίδες', - 'privileges' => 'Δικαιώματα', + 'privileges' => 'Πρόσβαση', 'users' => 'Χρήστες' ]; diff --git a/public/app/views/admin/categories.php b/public/app/views/admin/categories.php index e33d9b0..91acec1 100644 --- a/public/app/views/admin/categories.php +++ b/public/app/views/admin/categories.php @@ -1,9 +1,9 @@ <!-- title bar --> <div class="title-bar"> - <div>Διαχείριση Κατηγοριών</div> + <div><h5>Διαχείριση Κατηγοριών</h5></div> <div> <!-- Button trigger modal --> - <button type="button" class="btn btn-success pull-right" + <button type="button" class="btn pull-right" data-bs-toggle="modal" data-bs-target="#manageCategory" data-id="0"> <i class="fas fa-plus"></i> Νέα Κατηγορία </button> @@ -16,7 +16,7 @@ <div id="categories-tree"> - <table id="dt-categories" class="table table-responsive dt-table"> + <table id="dt-categories" class="table table-responsive dt-table" style="width:100%"> <thead> <th class="dt-breadcrumb">Κατηγορία</th> <th class="dt-actions"></th> @@ -48,25 +48,19 @@ <!-- modal-body --> <div class="modal-body"> - <!-- loader - <div class="modal-loader"> - <img src="/img/ajax-loader.gif"> - </div> - --> - <!-- form fields --> <div class="row form-group"> <label class="control-label col-sm-12" for="label">Όνομα κατηγορίας</label> <div class="col-sm-12"> - <input class="form-control" type="text" name="label" value="" required=""> + <input class="form-control form-control-sm" type="text" name="label" value="" required=""> </div> </div> <div class="row form-group"> <label class="control-label col-sm-12" for="parent_id">Γονική Κατηγορία</label> <div class="col-sm-12"> - <select class="form-control" id="parent_id" name="parent_id" required /></select> + <select class="form-control form-control-sm form-select form-select-sm" id="parent_id" name="parent_id" required></select> </div> </div> diff --git a/public/app/views/admin/new_lesson.php b/public/app/views/admin/new_lesson.php new file mode 100644 index 0000000..c48fc82 --- /dev/null +++ b/public/app/views/admin/new_lesson.php @@ -0,0 +1,144 @@ +<?php +// if no (lesson-)id is specified, then id=0 (new lesson) +if (!isset($id)) $id=0; +?> + +<!-- title bar --> +<div class="title-bar"> + <div><h5>Επεξεργασία Μαθήματος</h5></div> + <div> + <button type="button" class="btn pull-right" + data-toggle="modal" data-target="#editorModal" data-action="preview"> + <i class="fas fa-search"></i> Προεπισκόπηση + </button> + </div> +</div> + +<!-- manage --> +<div class="manage edit-post"> + <form> + <div class="row"> + + + <div class="col col-8"> + + <!-- id (hidden) --> + <input type="hidden" name="id" value="0"><!-- action = (0) ? 'new' : 'edit' --> + + <!-- + <div class="row form-group"> + <input type="date" name="date" value="" readonly=""> + </div> + --> + + <div class="row form-group"> + <label class="control-label col-sm-12" for="title">Τίτλος</label> + <div class="col-sm-12"> + <input class="form-control form-control-sm" type="text" name="title" value="" required=""> + </div> + </div> + + <div class="row form-group"> + <label class="control-label col-sm-12" for="category_id">Κατηγορία</label> + <div class="col-sm-12"> + <select class="form-control form-control-sm" id="category_id" name="category_id" required></select> + </div> + </div> + + <!-- Post body --> + <div class="row form-group"> + <label class="control-label col-sm-12" for="body">Κείμενο</label> + <div class="col-sm-12"> + <textarea class="form-control form-control-sm" type="text" name="body" value="" required=""></textarea> + </div> + </div> + + </div> + + <div class="col"> + + <div class="row form-group"> + <label class="control-label col-sm-12" for="status">Κατάσταση</label> + <div class="col-sm-12"> + <select class="form-control form-control-sm form-select form-select-sm" name="status" onchange="this.dataset.chosen = this.value;"> + <option value="0">Αδημοσίευτο</option> + <option value="one">ΔΗΜΟΣΙΕΥΜΕΝΟ</option> + </select> + </div> + </div> + + <div class="row form-group"> + <label class="control-label col-sm-12" for="privilege_id">Επίπεδο Πρόσβασης</label> + <div class="col-sm-12"> + <select class="form-control form-control-sm form-select form-select-sm" name="privilege_id"> + <option>one</option> + <option>two</option> + <option>three</option> + </select> + </div> + </div> + + <div class="row form-group"> + <label class="control-label col-sm-12" for="intro">Σύντομη Περιγραφή</label> + <div class="col-sm-12"> + <textarea class="form-control form-control-sm" type="text" name="intro" value=""></textarea> + </div> + </div> + + <div class="row form-group"> + <label class="control-label col-sm-12" for="media">Αρχεία</label> + <div class="col-sm-12 post-media"> + + <!-- Button trigger modal --> + <button type="button" class="btn btn-sm btn-success pull-right over-bar" + data-toggle="modal" data-target="#editorModal" data-action="upload_file"> + <i class="fas fa-plus"></i> Προσθήκη + </button> + + <ul id="files_list"> + </ul> + + </div> + </div> + + <?php if ($id != 0) : ?> + <div class="row form-group"> + <label class="control-label col-sm-12">Πληροφορίες</label> + <div class="col-sm-12" id="post-info"> + </div> + </div> + <?php endif; ?> + + </div> + + </div> + + <div class="row"> + + <div class="col"> + <hr/> + <!-- close | submit buttons --> + + <div class="form-actions row justify-content-md-center"> + + <div class="col-3"> + <button type="button" id="go-back" class="btn btn-light col-sm-12"> + Επιστροφή + </button> + </div> + + <div class="col-4"> + <button class="btn btn-primary col-sm-12" type="submit"> + Καταχώριση + </button> + </div> + + </div> + + </div> + + </form> + + </div> +</div><!-- /manage --> + diff --git a/public/app/views/admin/privileges.php b/public/app/views/admin/privileges.php new file mode 100644 index 0000000..587c363 --- /dev/null +++ b/public/app/views/admin/privileges.php @@ -0,0 +1,93 @@ + <!-- title bar --> + <div class="title-bar"> + <div><h5>Διαχείριση Επιπέδων Πρόσβασης</h5></div> + <div> + <!-- Button trigger modal --> + <button type="button" class="btn pull-right" + data-bs-toggle="modal" data-bs-target="#managePrivileges" data-id="0"> + <i class="fas fa-plus"></i> Νέο Επίπεδο + </button> + </div> +</div> + +<div class="manage"> + <div class="row"> + <div class="col-md-12"> + + <div id="categories-tree"> + + <table id="dt-privileges" class="table table-responsive dt-table" style="width:100%"> + <thead> + <th class="dt-id">Κωδικός</th> + <th class="dt-privilege">Επίπεδο Πρόσβασης</th> + <th class="dt-includes">Περιλαμβάνει</th> + <th class="dt-actions"></th> + </thead> + </table> + + </div> + + + </div> + </div> +</div><!-- /manage --> + + + +<!-- MODAL for new/edit category --> +<!-- NOTE: tabindex="-1" removed, ref:https://github.com/select2/select2-bootstrap-theme/issues/41 --> +<div class="modal fade" id="managePrivileges" aria-labelledby="myModalLabel" aria-hidden="true"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content"> + + <form method="post" action=""> + + <div class="modal-header"> + <h4 class="modal-title" id="myModalLabel">Modal title</h4> + <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> + </div><!-- /modal-header --> + + <!-- modal-body --> + <div class="modal-body"> + + <!-- form fields --> + + <div class="row form-group"> + <label class="control-label col-sm-12" for="label">Όνομα Επιπέδου Πρόσβασης</label> + <div class="col-sm-12"> + <input class="form-control form-control-sm" type="text" name="label" value="" required=""> + </div> + </div> + + <div class="row form-group"> + <label class="control-label col-sm-12" for="included_id">Περιλαμβάνει μέχρι και το Επίπεδο</label> + <div class="col-sm-12"> + <select class="form-control form-control-sm form-select form-select-sm" id="included_id" name="included_id" required></select> + </div> + </div> + + <div class="row form-group"> + <input type="hidden" name="id" value="0"><!-- action = (0) ? 'new' : 'edit' --> + </div> + + + </div><!-- /modal body --> + + <div class="modal-footer"> + <div class="row form-actions"> + + <div class="col"> + <button type="button" class="btn btn-default js-modal-close col-sm-12" data-bs-dismiss="modal">Κλείσιμο</button> + </div> + <div class="col"> + <button class="btn btn-success col-sm-12" type="submit">Καταχώριση</button> + </div> + + </div> + </div><!-- /modal-footer --> + + </form><!-- /form --> + + </div> + </div> +</div> diff --git a/public/assets/css/overides.css b/public/assets/css/overides.css index 172d24e..0709f4d 100644 --- a/public/assets/css/overides.css +++ b/public/assets/css/overides.css @@ -40,13 +40,13 @@ html, body { font-family: "Roboto Slab", serif; font-weight: 400; } .admin-container { font-size: .96em; } .admin-container .top-bar a:hover { background: #ddd; } -.admin-container .manage { padding: .5em .5em 1.5em .5em; } +.admin-container .manage { padding: 1em; } .admin-container .title-bar { display: flex; justify-content: space-between; align-items: center; - padding: 1em 8px 1em 16px; + padding: 1.5em 1em 1.5em 1em; } .admin-container .dt-table { font-size: 14px; } @@ -58,11 +58,48 @@ html, body { font-family: "Roboto Slab", serif; font-weight: 400; } } .admin-container .modal .form-group { padding: .35em 0;} -.admin-container .modal .form-control { padding: 1px 8px; border-radius: 4px; font-size: 15px; } +/*.admin-container .modal .form-control { padding: 1px 8px; border-radius: 4px; font-size: 15px; } */ .admin-container .table > :not(caption) > * > * { padding: .35rem .35rem; } .admin-container .table tbody tr:hover { background: #eee; } ul.select2-results__options li { font-size: 14px; padding: 4px 8px; } -.admin-container .modal-footer .form-actions { display: flex; }
\ No newline at end of file +.admin-container .modal-footer .form-actions { display: flex; } + +.admin-container .title-bar h5 { margin-bottom: 0; color: #333; } + +.admin-container table.dataTable { margin-top: 1em !important; margin-bottom: 1em !important;} + +.admin-container .title-bar .btn { border: 1px solid #7772; } +.admin-container .title-bar .btn:hover { background: #ddd; } + +.admin-container form label { padding: 8px 1em 2px 1em; } + +.admin-container .form-control { border-radius: 4px; } + +.admin-container select[data-chosen='one'] { + font-weight: 700; + color: #000; +} + +/* hack select2 caret styling + * (like bootstrap5 select caret) + * ----------------------------------------------------------------------------- + */ + +.select2-container--default .select2-selection--single .select2-selection__arrow b { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); + background-color: transparent; + background-size: contain; + border: none !important; + height: 16 !important; + width: 12px !important; + margin: auto !important; + top: 9px !important; + left: auto !important; + height: 14px; +} +.select2-container--default .select2-selection--single .select2-selection__arrow { width: 24px; } +.select2-container--default .select2-selection--single { height: 31px; } +
\ No newline at end of file diff --git a/public/assets/js/admin/categories.js b/public/assets/js/admin/categories.js index 0ff2b85..90eede3 100644 --- a/public/assets/js/admin/categories.js +++ b/public/assets/js/admin/categories.js @@ -119,7 +119,7 @@ $(document).ready(function() { function init_table() { // get all categories from server (ajax) - $.getJSON( "/admin/api/categories?exclude=0") + $.getJSON( "/admin/api/categories") .done(function( json ) { // then ... @@ -272,7 +272,7 @@ $(document).ready(function() { }; // select action url (add or update) - var request = '/admin/category?action=' + ((data.id == 0) ? 'add' : 'update'); + var request = '/admin/api/category/' + ((data.id == 0) ? 'add' : 'update'); // send POST request $.post(request, data) diff --git a/public/assets/js/admin/privileges.js b/public/assets/js/admin/privileges.js new file mode 100644 index 0000000..e4355c5 --- /dev/null +++ b/public/assets/js/admin/privileges.js @@ -0,0 +1,291 @@ +// Globals +// ----------------------------------------------------------------------------- +var privileges = []; +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 privilege_record(id) { + var record = 0; + privileges.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 = [ + '<button type="button" class="btn btn-sm btn-warning"', + 'data-bs-toggle="modal" data-bs-target="#managePrivileges"', + 'data-id="'+ id +'">', + '<i class="fas fa-pencil-alt"></i>', + '</button>' + ].join('\n'); + + return edit +' '+ del; +} + + + +$(document).ready(function() { + + // When document is ready + // ------------------------------------------------------------------------- + + + /** init selec2 element (used to specify parent-category) + * --- -- -- - - - + */ + $("#included_id").select2({ + placeholder: 'Περιλαμβάνει τα δικαιώματα της', + dropdownParent: $('#managePrivileges'), + 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/privileges") + .done(function( json ) { + // then ... + + // reset categories + privileges.length = 0; + + // construct (new) categories data + Object.keys(json).forEach( key => { + el = json[key]; + privileges.push({ + id: el.id, + label: el.label, + includes: ((el.includes == null) ? [] : el.includes), + included_id: ((el.included_id == null) ? 0 : el.included_id), + actions: create_actions_html(el.id) + }); + }); + + // sort by breadcrumb + // categories.sort( compare_breadcrumb ); + + // destroy previous datatable table instances + $('#dt-privileges').dataTable().fnClearTable(); + $('#dt-privileges').dataTable().fnDestroy(); + + // (re-)create categories datatable + table = $('#dt-privileges').DataTable({ + language: { url: '/libs/DataTables/localization/Greek.json' }, + data: privileges, + ordering: false, + columns: [ + { data: 'id' }, + { data: 'label' }, + { data: 'includes' }, + { 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 + */ + $('#managePrivileges').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 + // --- + $('#managePrivileges .modal-title').html( // modal title + (id) ? 'Ενημέρωση Επιπέδου Πρόσβασης' : 'Δημιουργία Επιπέδου Πρόσβασης' + ); + $('#managePrivileges form input[name=id]').val( id ); // category id (hidden) + $('#managePrivileges form input[name=label]').val( // category label + (id) ? privilege_record(id).label : "" + ); + prepare_included_element(id); // prepare <select> for parents + }) + + /** prepare_included_element() + * --- + * @param id (int) : id of selected privilege + * -> Get all posible included privileges + * -> call set_included_options() to render the options + */ + function prepare_included_element(id) { + var may_included = []; + + if (id) { // get all possible parents + + // TODO: + // specify forbiden privilege IDs for being included + + // filter privileges adn prepare possible included privileges + privileges.forEach( el => { + if (id != el.id) { + may_included.push({ + id: el.id, + label: el.label + }); + } + }); + console.log(may_included); + set_included_options(may_included, privilege_record(id).included_id); + + + } else { // new record; all categories are possible parrents + privileges.forEach( el => { + may_included.push({ + id: el.id, + label: el.label, + }); + }) + set_included_options(may_included, -1); + } + } + + /** set_included_options() + * -> create options for parents <select> + * -> choose selected parent + * @param may_included (array): array of possible included privileges + * @param selected (int): selected included privilege + */ + function set_included_options(may_included, selected) { + // sort parents by breadcrumb + // parents.sort( compare_breadcrumb ); + + // remove any olded options from select2 + $('#included_id option').each(function() { $(this).remove(); }); + + // first option is the root category + $('#included_id').append('<option value="0">— κανένα —</option>') + + // add all other parent options + may_included.forEach( i => { + $('#included_id').append(`<option value="${i.id}">${i.label}</option>`); + }); + + if (selected == -1) { // new category; remove any parent pre-selection + $('#included_id').val(0).trigger('change'); + + } else { // category exists; choose selected parent + $('#included_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/api/category/' + ((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 + }); + + }); + +}); diff --git a/public/cache/.gitkeep b/public/cache/.gitkeep deleted file mode 100755 index e69de29..0000000 --- a/public/cache/.gitkeep +++ /dev/null |
