summaryrefslogtreecommitdiff
path: root/public/app
diff options
context:
space:
mode:
Diffstat (limited to 'public/app')
-rw-r--r--public/app/config/init_routes.php12
-rw-r--r--public/app/controllers/Admin.php58
-rw-r--r--public/app/controllers/Auth.php68
-rw-r--r--public/app/extends/Classroom_user.php35
-rw-r--r--public/app/models/cms/Course_model.php219
-rw-r--r--public/app/routes/backend.php44
-rw-r--r--public/app/routes/frontend.php60
-rw-r--r--public/app/routes/user.php84
-rw-r--r--public/app/views/admin/admin-menu.php47
-rw-r--r--public/app/views/admin/categories.php97
-rw-r--r--public/app/views/admin/skeleton.php40
-rw-r--r--public/app/views/components/header_includes.php33
-rw-r--r--public/app/views/components/user-management.php35
-rw-r--r--public/app/views/error/404.php2
-rw-r--r--public/app/views/error/general.php2
-rw-r--r--public/app/views/welcome.php15
16 files changed, 724 insertions, 127 deletions
diff --git a/public/app/config/init_routes.php b/public/app/config/init_routes.php
new file mode 100644
index 0000000..22d6ec0
--- /dev/null
+++ b/public/app/config/init_routes.php
@@ -0,0 +1,12 @@
+<?php
+
+// Add Routes
+// -----------------------------------------------------------------------------
+
+require_once 'app/routes/api.php'; // API: =/api/{table}/{id};/api/*
+
+require_once 'app/routes/backend.php'; // Backend: =/admin/*
+
+require_once 'app/routes/user.php'; // User account management
+
+require_once 'app/routes/frontend.php'; // Frontend =/* (whatever)
diff --git a/public/app/controllers/Admin.php b/public/app/controllers/Admin.php
new file mode 100644
index 0000000..6f6858c
--- /dev/null
+++ b/public/app/controllers/Admin.php
@@ -0,0 +1,58 @@
+<?php
+namespace app\controllers;
+
+use Registry;
+use Render;
+
+// user classes and models
+use app\extends\Classroom_user;
+use app\extends\Classroom_manager;
+use app\models\admin\User_model;
+
+use app\extends\Send_mail;
+use app\extends\Mail_jet;
+
+
+/** class Auth
+ *
+ * handles user's Authentication and Authorizarion
+ *
+ */
+class Admin {
+
+ /** admin cateogories
+ *
+ */
+ public static function categories()
+ {
+ Render::view('admin/categories');
+ }
+
+
+ /** admin lessons
+ *
+ */
+ public static function lessons()
+ {
+
+ }
+
+
+ /** admin pages
+ *
+ */
+ public static function pages()
+ {
+
+ }
+
+ /** admin users
+ *
+ */
+ public static function users()
+ {
+
+ }
+
+
+} \ No newline at end of file
diff --git a/public/app/controllers/Auth.php b/public/app/controllers/Auth.php
index f215388..d7b0c3b 100644
--- a/public/app/controllers/Auth.php
+++ b/public/app/controllers/Auth.php
@@ -41,6 +41,7 @@ class Auth {
$user = (new Classroom_user())
->setID($record['id'])
->setUserName($record['email'])
+ ->setName($record['first_name'] .' '. $record['last_name'])
->setPassword($record['password'])
->setEnabled($record['active']);
@@ -67,7 +68,7 @@ class Auth {
// set cookie for connected user
setcookie(
'cluser',
- 'connected',
+ 'connected;'. $user->getName(),
time()+60*60*8, // 8 hours
'/'
);
@@ -138,6 +139,7 @@ class Auth {
$user = (new Classroom_user())
->setUserName($req->POST['email'])
+ ->setName($req->POST['name'] .' '. $req->POST['surname'])
->setPassword($password)
->setRoles([ READER ]) // Role: authorized reader
->setPrivileges([]); // none privilege until acount confirmation
@@ -197,19 +199,19 @@ class Auth {
}
-
-
-
public static function logout()
{
- $userManager = new UserManager();
+ $userManager = new Classroom_manager();
$userManager->logout();
+ // regeneration session ID (prevent session fixation)
+ session_regenerate_id();
+
// remove user-conected cookie
if (isset($_COOKIE['cluser'])) {
unset($_COOKIE['cluser']);
- setcookie('cluser', null, -1, '/');
+ setcookie('cluser', '', -1, '/');
return true;
} else {
return false;
@@ -218,34 +220,6 @@ class Auth {
- /** isGranted( ROLE )
- *
- * checks if the user is granted (some of) the specified role(s)
- * to access the source
- *
- * NOTE:
- * if no roles are specified then user is granted
- * (because every user is granted the 'no-role')
- *
- * @param $roles (array): array of roles to check (if any is granted)
- *
- */
- public static function isGranted($roles = [])
- {
- // no role required ? user is granted access
- if ($roles == []) return true;
-
- // else, UserManager knows if user isGranted
- $userManager = new UserManager();
- if ($userManager->isGranted($roles)) {
- return true;
-
- } else {
- return false;
- }
- }
-
-
/** hasPermition( PERMIT )
*
* checks if the user owns the specified permition
@@ -322,6 +296,32 @@ class Auth {
}
+ /** allowRoles
+ *
+ * method filters access for certain roles
+ * if user is not grented acces, a forbiden message is sent and app ends._
+ * otherwise the method returns true (app will continue)
+ *
+ * @param $allowed (array) : array of allowed roles
+ * @return true or die();
+ */
+ public static function allowRoles($allowed)
+ {
+ $manager = new Classroom_manager();
+ if ($manager->isGranted($allowed)) { // if valid, return true (continue)
+ return true;
+
+ } else { // no user, no access; die._
+ Render::view('error/general', [
+ 'title' => 'Forbidden',
+ 'message' => 'Access is forbidden'
+ ]);
+ die();
+ return false; // this line will never run
+ }
+ }
+
+
}
diff --git a/public/app/extends/Classroom_user.php b/public/app/extends/Classroom_user.php
index 1c26e73..c27c4bf 100644
--- a/public/app/extends/Classroom_user.php
+++ b/public/app/extends/Classroom_user.php
@@ -34,12 +34,19 @@ class Classroom_user extends User
*/
private $privileges = [];
+ /** user name
+ * @var string
+ */
+ private $name;
/** SETTERS AND GETTERS
- * for id and privileges attributes
+ * for id, name, privileges attributes
* -------------------------------------------------------------------------
*/
+ // id
+ // --- -- -- - - -
+
/** getID
* @return int
*/
@@ -59,8 +66,34 @@ class Classroom_user extends User
$this->id = $id;
return $this;
}
+
+
+ // name
+ // --- -- -- - - -
+
+ /** getName
+ * @return int
+ */
+ public function getName(): string
+ {
+ return $this->name;
+ }
+
+ /** setName()
+ *
+ * @param string : user's full name
+ *
+ * @return User
+ */
+ public function setName(string $name): self
+ {
+ $this->name = $name;
+ return $this;
+ }
+ // privileges
+ // --- -- -- - - -
/** getPrivileges
*
diff --git a/public/app/models/cms/Course_model.php b/public/app/models/cms/Course_model.php
new file mode 100644
index 0000000..4fb49c0
--- /dev/null
+++ b/public/app/models/cms/Course_model.php
@@ -0,0 +1,219 @@
+<?php
+namespace app\models\cms;
+
+use \Registry;
+
+
+class Course_model {
+
+ /** get all categories
+ *
+ * raw table data (simplest SELECT)
+ *
+ */
+ public static function get_categories()
+ {
+ return Registry::use('database')->runQuery(
+ "SELECT * FROM course",
+ []
+ );
+ }
+
+
+ /** constuct a category_tree
+ *
+ * returns a tree representation of the categories
+ *
+ * NOTE:
+ * category_tree() is an expensive method;
+ * it calls 2 other methods implementing recursive algorithms
+ * thus it uses many sources to run (particularly RAM).
+ * Caching the result is strogly recommended.
+ *
+ */
+ public static function category_tree()
+ {
+ $categories = self::get_categories(); // get all categories
+
+ $tree = self::to_tree($categories); // format to a tree
+
+ $tree_wParents = self::tree_parents($tree); // add parents section for each tree-node
+
+ return $tree_wParents;
+ }
+
+
+ /** to_tree
+ *
+ * constructs a tree from raw-table data;
+ * this is a private method and uses a recursive algorithm
+ *
+ * @param $dataset (array): flar array of records with id/parent-id pairs
+ * @return $root (array): id of root category
+ *
+ * (**) each node has 2 parts:
+ * .... .. rec : all record attributes/data as passed into $dataset
+ * .... .. childs : array of (children) nodes
+ */
+ private static function to_tree($dataset, $root = 0)
+ {
+ $return = [];
+
+ // loop data ; search for direct children of root
+ foreach($dataset as $key => $rec) {
+
+ $child = $rec['id'];
+ $parent = $rec['parent_id'];
+
+ if ($parent == $root) { // a direct child is found
+
+ unset($dataset[$key]); // remove item (no need to traverse again)
+
+ // Append the child into result array ; parse its children
+ $return[] = [
+ 'rec' => [
+ 'id' => $rec['id'],
+ 'label' => $rec['label'],
+ 'parent' => $rec['parent_id']
+ ],
+ 'childs' => self::to_tree($dataset, $child) // recursively
+ ];
+ }
+ }
+ return empty($return) ? [] : $return;
+ }
+
+
+ /** tree_parents
+ *
+ * adds a section to each tree node with all parents of each node
+ *
+ * @param $tree (array) : nodes array (each node has `rec` and `childs` sections )
+ * @param $parents (array); DO NOT SET IT (takes values automaticaly)
+ * @return array of nodes with an extra node[parents] section
+ *
+ */
+ private static function tree_parents($tree, $parents = [])
+ {
+ $tree_with_parents = [];
+
+ foreach($tree as $key => $node) {
+ // parents to be pushed for node's children
+ $push_parents = $parents; // parents so far
+ $push_parents[] = $node['rec']; // this record will be a new parent
+
+ $tree_with_parents[$key] = [
+ 'rec' => $node['rec'],
+ 'parents' => $parents,
+ 'childs' => ($node['childs'] == [])
+ ? []
+ : self::tree_parents($node['childs'], $push_parents)
+ ];
+ }
+
+ return $tree_with_parents;
+ }
+
+
+ /** all_breadcrumbs
+ * -------------------------------------------------------------------------
+ *
+ * returns an array of all breadcrumbs
+ * where array-key of each record is category[id]
+ *
+ * NOTE:
+ * ---
+ * Course_model::all_breadcrumbs returns an indexed super-array;
+ * each array item includes a banch of information: [
+ * breadcrumb,
+ * rec: [ id , title ],
+ * parents: [ [id, title] , ... ]
+ * childs: [ [id, title] , ... ],
+ * level
+ * ]
+ *
+ * Use Cases:
+ * ---
+ * as a super-array, the output can be used in many cases
+ * for example...
+ * into <select-option> form elements
+ * .. while selecting category for a post
+ * .. or editing a category
+ * or directry referring to category's parents/childs
+ *
+ * Arguments:
+ * ---
+ * @param $tree (array) : category tree (with childs and parents parts)
+ * @param $detimiter (string, optional) : string to split breadcrumb's path-nodes
+ * @param $exception (int, optional) : id of category to exclude (subcategories shall be excluded too)
+ * @param $l (int, not-pass) : depth level of the node; DO NOT SET (takes values automaticaly)
+ * @return array of breadcrumbs
+ * -------------------------------------------------------------------------
+ */
+ static public function breadcrumbs($tree, $delimiter = " / ", $exception = 0, $l = 0)
+ {
+ $all = []; // results array
+
+ foreach($tree as $node) { // loop through all nodes
+
+ if (intval($node['rec']['id']) != $exception) { // if node is not exception
+
+ // construct breadcrumb html of node
+ // --- -- -- - - -
+ $breadcrumb = "";
+ foreach($node['parents'] as $par) { // first: join path titles
+ $breadcrumb .= $par['label'] . $delimiter;
+ }
+ $breadcrumb .= $node['rec']['label']; // last: append title
+
+ // make a new super record
+ // --- -- -- - - -
+ $all[$node['rec']['id']] = [ // set record is as key
+ 'breadcrumb' => $breadcrumb, // add breadcrump to results
+ 'rec' => $node['rec'], // + node info
+ 'parents' => $node['parents'], // + parents array
+ 'childs' => self::first_level_childs($node), // + direct childs
+ 'level' => $l // + level
+ ];
+
+ // recursively traverse children nodes
+ // --- -- -- - - -
+ if (isset($node['childs']) && $node['childs'] != []) {
+ $child_breadcrumbs = self::breadcrumbs(
+ $node['childs'],
+ $delimiter,
+ $exception,
+ $l+1
+ );
+
+ $all = $all + $child_breadcrumbs; // concatenate arrays (keep array-keys)
+ }
+ }
+
+ }
+ return $all;
+
+ }
+
+ /** first_level_childs
+ * --- -- -- - - -
+ * used by all_breadcrumbs()
+ */
+ static private function first_level_childs($node)
+ {
+ $childs = [];
+ if ($node['childs'] == []) {
+ return [];
+ }
+ foreach($node['childs'] as $key => $kid) {
+ $childs[] = [
+ 'id' => $kid['rec']['id'],
+ 'label' => $kid['rec']['label']
+ ];
+ }
+ return $childs;
+ }
+
+
+
+}
diff --git a/public/app/routes/backend.php b/public/app/routes/backend.php
index 9b90cf1..700fa14 100644
--- a/public/app/routes/backend.php
+++ b/public/app/routes/backend.php
@@ -1,9 +1,41 @@
<?php
-Route::add('/admin/info', // generaly you need to hide phpinfo()
- function() { // so, remove this route on production
- // Authenticate::session(); // or require authentication
- phpinfo(); },
- 'get'
-);
+use app\controllers\Auth;
+use app\models\cms\Course_model;
+// admin lessons
+// ---
+Route::add('/admin/lessons', function () {
+ Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles
+ Render::view('admin/skeleton', [
+ 'title' => 'Διαχείριση Μαθημάτων',
+ 'action' => 'lessons',
+ ]);
+});
+
+
+// admin cateogies
+// ---
+Route::add('/admin/categories', function () {
+ Auth::allowRoles([1, 2, 3]);
+ Render::view('admin/skeleton', [
+ 'title' => 'Διαχείριση Κατηγοριών',
+ 'action' => 'categories',
+ ]);
+});
+
+
+Route::add('/admin/api/categories', function () {
+ Auth::allowRoles([1, 2, 3]);
+ $tree = proxy(
+ [\app\models\cms\Course_model::class, 'category_tree'],
+ [], 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
diff --git a/public/app/routes/frontend.php b/public/app/routes/frontend.php
index 56db23a..dde0fcd 100644
--- a/public/app/routes/frontend.php
+++ b/public/app/routes/frontend.php
@@ -1,14 +1,18 @@
<?php
-use app\controllers\Resolve;
-use app\controllers\Product;
use app\controllers\Auth;
use app\controllers\Classroom_user;
+use app\models\cms\Course_model;
// Home/Welcome
// ---
Route::add('/', function() { // echo 'Welcome!'; });
- Render::view('welcome');
+ Render::view('welcome', [ // cache categories (while retrieving)
+ 'categories' => proxy(
+ [\app\models\cms\Course_model::class, 'category_tree'],
+ [], CACHE_ROOT_TTL
+ )
+ ]);
// header('Location: /some/default/url', true, 302);
});
@@ -38,56 +42,6 @@ Route::notFound( function() {
// [..] order
-Route::add('/login', function() { Render::view('user/login'); });
-Route::add('/registration', function() { Render::view('user/registration'); });
-
-
-Route::add('/account/check-login', function() {
- $response = Auth::login();
- Render::json(['status' => $response]);
- },
- 'post'
-);
-
-// user sends a registration form;
-Route::add('/account/register', function() {
- $response = Auth::register();
- Render::json($response);
- },
- 'post'
-);
-
-// user requests activation
-Route::add('/account/activate', function() { Auth::activate(); } );
-
-// user profile
-Route::add('/account/profile', function() {
- $user = Auth::is_connected();
- if ($user === false) {
- Render::view('error/general',
- [
- 'title' => 'Nope!',
- 'message' => "<h2>No profile</h2>User is not connected"
- ]
- );
-
- } else {
- print_r($user);
- }
- }
-);
-
-// test connection
-// NOTE: this is only for testing purposes
-if (!PRODUCTION) {
- Route::add('/check/connection', function() { Auth::is_connected(); });
-}
-
-Route::add('/account/reset_password', function() { Auth::reset_password(); } );
-
-
-
-
// Resolve urls
// --- -- -- - - -
diff --git a/public/app/routes/user.php b/public/app/routes/user.php
new file mode 100644
index 0000000..d419a5b
--- /dev/null
+++ b/public/app/routes/user.php
@@ -0,0 +1,84 @@
+<?php
+
+use app\controllers\Auth;
+use app\controllers\Classroom_user;
+
+/** User Connection Management Routes
+ * -----------------------------------------------------------------------------
+ */
+
+// common requests (GET method)
+// --- -- -- - - -
+
+// request login ... -> sends to POST:/account/check-login
+Route::add('/login', function() { Render::view('user/login'); });
+
+// request registration ... -> sends to POST:/account/register
+Route::add('/registration', function() { Render::view('user/registration'); });
+
+// request logout
+Route::add('/logout', function() {
+ Auth::logout();
+ header('Location: /'); die();
+});
+
+// request activation
+Route::add('/account/activate', function() { Auth::activate(); } );
+
+// request password reset
+Route::add('/account/reset_password', function() { Auth::reset_password(); } );
+
+
+
+// Replies to common requests (POST method)
+// --- -- -- - - -
+
+// user sends login form
+Route::add('/account/check-login', function() {
+ $response = Auth::login();
+ Render::json(['status' => $response]);
+ },
+ 'post'
+);
+
+// user sends a registration form
+Route::add('/account/register', function() {
+ $response = Auth::register();
+ Render::json($response);
+ },
+ 'post'
+);
+
+
+// Account Management
+// --- -- -- - - -
+
+// user profile
+Route::add('/account/profile', function() {
+ $user = Auth::is_connected();
+ if ($user === false) {
+ Render::view('error/general',
+ [
+ 'title' => 'Nope!',
+ 'message' => "<h2>No profile</h2>User is not connected"
+ ]
+ );
+
+ } else {
+ print_r($user);
+ }
+ }
+);
+
+
+// temporary (on development)
+// --- -- -- - --
+// NOTE: these is only for testing purposes
+
+// test connection
+if (!PRODUCTION) {
+ Route::add('/check/connection', function() { Auth::is_connected(); });
+}
+
+
+
diff --git a/public/app/views/admin/admin-menu.php b/public/app/views/admin/admin-menu.php
new file mode 100644
index 0000000..813420d
--- /dev/null
+++ b/public/app/views/admin/admin-menu.php
@@ -0,0 +1,47 @@
+<?php
+/** admin panel
+ * -----------------------------------------------------------------------------
+ *
+ * imported variables:
+ * ---
+ * @param $action (string) : array of articles
+ *
+ * example call:
+ * ---
+ * Render::template("sections/admin_panel.php",[
+ * 'action' => 'posts',
+ * ])
+ * -----------------------------------------------------------------------------
+ */
+
+
+$admin_options = [
+ 'new' => 'Νέο Μάθημα',
+ 'lessons' => 'Μαθήματα',
+ 'categories' => 'Κατηγορίες',
+ 'pages' => 'Σελίδες',
+ 'privileges' => 'Δικαιώματα',
+ 'users' => 'Χρήστες'
+];
+
+?>
+
+<div class="top-bar">
+
+ <span class="btn btn-warning">Admin</span>
+
+ <?php foreach($admin_options as $opt => $label) : ?>
+
+ <?php if ($opt == $action) : ?>
+ <span class="btn btn-primary selected"><?=$label?></span>
+
+ <?php else : ?>
+ <a href="/admin/<?= $opt ?>" class="btn"><?= $label ?></a>
+
+ <?php endif; ?>
+
+ <?php endforeach ?>
+
+ <a href="/logout" class="btn">Logout</a>
+
+</div> \ No newline at end of file
diff --git a/public/app/views/admin/categories.php b/public/app/views/admin/categories.php
new file mode 100644
index 0000000..e33d9b0
--- /dev/null
+++ b/public/app/views/admin/categories.php
@@ -0,0 +1,97 @@
+ <!-- title bar -->
+ <div class="title-bar">
+ <div>Διαχείριση Κατηγοριών</div>
+ <div>
+ <!-- Button trigger modal -->
+ <button type="button" class="btn btn-success pull-right"
+ data-bs-toggle="modal" data-bs-target="#manageCategory" data-id="0">
+ <i class="fas fa-plus"></i> &nbsp; Νέα Κατηγορία
+ </button>
+ </div>
+</div>
+
+<div class="manage">
+ <div class="row">
+ <div class="col-md-12">
+
+ <div id="categories-tree">
+
+ <table id="dt-categories" class="table table-responsive dt-table">
+ <thead>
+ <th class="dt-breadcrumb">Κατηγορία</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="manageCategory" 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">
+
+ <!-- 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="">
+ </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>
+ </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">
+ <div class="form-actions">
+ <div class="col-xs-4">
+ <button type="button" class="btn btn-default js-modal-close col-sm-12" data-bs-dismiss="modal">Κλείσιμο</button>
+ </div>
+ <div class="col-xs-8">
+ <button class="btn btn-success col-sm-12" type="submit">Καταχώριση</button>
+ </div>
+ </div>
+ </div>
+ </div><!-- /modal-footer -->
+
+ </form><!-- /form -->
+
+ </div>
+ </div>
+</div>
diff --git a/public/app/views/admin/skeleton.php b/public/app/views/admin/skeleton.php
index a9c2dcf..fea346f 100644
--- a/public/app/views/admin/skeleton.php
+++ b/public/app/views/admin/skeleton.php
@@ -3,35 +3,31 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>ΣΚΛΑΒΕΝΙΤΗΣ - <?=$page['title']?></title>
+ <title>Classroom - <?=$title?></title>
- <!-- styling assets -->
-
- <link rel="preconnect" href="https://fonts.googleapis.com">
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
- <link href="https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@300;400;500;700&display=swap" rel="stylesheet">
-
- <!-- script assets -->
+ <?php // header includes
+ ////////////////////////////////////////////////////////////////////////
+ Render::view('components/header_includes', ['administration' => true]);
+ ?>
</head>
<body>
- <div class="admin-container">
-
- <div class="menu">
-
- </div>
-
- <div class="workspace">
-
- </div>
-
- <div class="options">
-
- </div>
-
+ <div class="classroom admin-container">
+
+ <?php
+ Render::view('admin/admin-menu',[
+ 'action' => $action
+ ])
+ ?>
+
+ <?php
+ Render::view("admin/{$action}");
+ ?>
</div>
+ <script src="/assets/js/admin/<?= $action ?>.js"></script>
+
</body>
</html><?php ob_flush(); ?>
diff --git a/public/app/views/components/header_includes.php b/public/app/views/components/header_includes.php
index 4ee6904..e5e51cd 100644
--- a/public/app/views/components/header_includes.php
+++ b/public/app/views/components/header_includes.php
@@ -1,3 +1,8 @@
+<?php
+ if (!isset($administration)) {
+ $administration = false;
+ }
+?>
<!-- fonts (CDN) -->
<link rel="preconnect" href="https://fonts.googleapis.com">
@@ -10,14 +15,42 @@
<!-- bootstap (CDN) -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-aFq/bzH65dt+w6FI2ooMVUpc+21e0SRygnTpmBvdBgSdnuTN7QbdgL+OapgHtvPp" crossorigin="anonymous">
+<?php if ($administration) : ?>
+ <!-- datatables css -->
+ <link href="https://cdn.datatables.net/v/bs5/jszip-2.5.0/dt-1.13.4/b-2.3.6/b-colvis-2.3.6/b-html5-2.3.6/b-print-2.3.6/cr-1.6.2/date-1.4.0/fc-4.2.2/fh-3.3.2/kt-2.8.2/r-2.4.1/rr-1.3.3/sc-2.1.1/sl-1.6.2/sr-1.2.2/datatables.min.css" rel="stylesheet"/>
+
+ <!-- select2 css -->
+ <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
+<?php endif ?>
+
+
<!-- main css -->
<link href="/assets/css/class.css" rel="stylesheet">
<!-- overides -->
<link href="/assets/css/overides.css" rel="stylesheet">
+
+
<!-- bootstrap javascript (CDN) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha2/dist/js/bootstrap.bundle.min.js" integrity="sha384-qKXV1j0HvMUeCBQ+QVp7JcfGl760yU08IQ+GpUo5hlbpg51QRiuqHAJz8+BrxE/N" crossorigin="anonymous"></script>
<!-- jQuery (CDN) -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.4/jquery.min.js" integrity="sha512-pumBsjNRGGqkPzKHndZMaAG+bir374sORyzM3uulLV14lN5LyykqNk8eEeUlUkB3U0M4FApyaHraT65ihJhDpQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+
+<!-- basic cookie handling (vanilla js) -->
+<script src="/assets/js/cookie.js"></script>
+
+
+<?php if ($administration) : ?>
+ <!-- datatables js -->
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/pdfmake.min.js"></script>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.36/vfs_fonts.js"></script>
+ <script src="https://cdn.datatables.net/v/bs5/jszip-2.5.0/dt-1.13.4/b-2.3.6/b-colvis-2.3.6/b-html5-2.3.6/b-print-2.3.6/cr-1.6.2/date-1.4.0/fc-4.2.2/fh-3.3.2/kt-2.8.2/r-2.4.1/rr-1.3.3/sc-2.1.1/sl-1.6.2/sr-1.2.2/datatables.min.js"></script>
+
+ <!-- select2 js -->
+ <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
+<?php endif ?>
+
+
+
diff --git a/public/app/views/components/user-management.php b/public/app/views/components/user-management.php
index 02a439e..9f95af8 100644
--- a/public/app/views/components/user-management.php
+++ b/public/app/views/components/user-management.php
@@ -18,12 +18,13 @@
<div class="dropdown js-subscriber">
<button type="button" class="btn btn-default dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
+ <i class="fa fa-regular fa-user"></i>
Διαχείριση Λογαριασμού <span class="caret"></span>
</button>
<ul class="dropdown-menu">
- <li><a class="dropdown-item" href="/profile">Διαχείριση Προφίλ</a></li>
- <li><a class="dropdown-item" href="/courses">Ύλη μαθημάτων</a></li>
- <li><a class="dropdown-item" href="/payments">Πληρωμές</a></li>
+ <li><a class="dropdown-item" href="/account/profile">Διαχείριση Προφίλ</a></li>
+ <li><a class="dropdown-item" href="/account/courses">Ύλη μαθημάτων</a></li>
+ <li><a class="dropdown-item" href="/account/payments">Πληρωμές</a></li>
<li><hr class="dropdown-divider"></li>
@@ -35,8 +36,30 @@
<script>
- // default: hide subscriber's menu
- [].forEach.call(document.querySelectorAll('.js-subscriber'), function (el) {
+ // if user is connected hide anonymous user menu and show connected user's content
+ if (cookieExists('cluser') && (readCookie('cluser').includes('connected'))) {
+ [].forEach.call(document.querySelectorAll('.js-visitor'), function (el) {
+ el.style.display = 'none';
+ });
+ [].forEach.call(document.querySelectorAll('.js-subscriber'), function (el) {
+ el.style.display = 'unset';
+ });
+
+ // also extract user's full name to personalize messages
+ let connection = unescape(readCookie('cluser')).split(';');
+ connection.shift(); // remove 1st item (="connection")
+ let name = connection.join(' '); console.log(name);
+ var node = document.querySelectorAll('.js-subscriber button')[0];
+ node.innerHTML = `<i class="fa fa-regular fa-user"></i> ${name} <span class="caret"></span>`;
+
+
+ } else { // else ... do the opposite
+ [].forEach.call(document.querySelectorAll('.js-subscriber'), function (el) {
el.style.display = 'none';
- });
+ });
+ [].forEach.call(document.querySelectorAll('.js-visitor'), function (el) {
+ el.style.display = 'unset';
+ });
+ }
+
</script>
diff --git a/public/app/views/error/404.php b/public/app/views/error/404.php
index 2b67e8d..89c35cc 100644
--- a/public/app/views/error/404.php
+++ b/public/app/views/error/404.php
@@ -22,7 +22,7 @@
.container { display: flex; height: 100vh; align-items:center; }
.content { position: relative;
max-width:320px; width: 100%;
- margin: auto auto; padding: 1.5em;
+ margin: auto auto; padding: 1.5em 1.5em 3em 1.5em;
text-align: center; justify-center: center;
opacity: .33;
}
diff --git a/public/app/views/error/general.php b/public/app/views/error/general.php
index 257e68d..74566a4 100644
--- a/public/app/views/error/general.php
+++ b/public/app/views/error/general.php
@@ -34,7 +34,7 @@
.container { display: flex; height: 100vh; align-items:center; }
.content { position: relative;
max-width: 480px; width: 100%;
- margin: auto auto; padding: 1.5em;
+ margin: auto auto; padding: 1.5em 1.5em 3em 1.5em;
text-align: center; justify-center: center;
opacity: .33;
font-size: .87em
diff --git a/public/app/views/welcome.php b/public/app/views/welcome.php
index de00645..ded2294 100644
--- a/public/app/views/welcome.php
+++ b/public/app/views/welcome.php
@@ -17,12 +17,21 @@
Render::view('components/top-bar');
?>
- <?php print_r($_SESSION); ?>
+ <pre>
+ <?php print_r($categories); ?>
+ </pre>
+
+ <!-- TESTING STRINGS (while developing only) -->
+ <?php /* --- print_r($_SESSION); ?>
<?php print_r($_COOKIE); ?>
<?php
- if (isset($_SESSION)) echo 'session seted';
+ if (isset($_SESSION)) echo '; session seted ; ';
?>
- <?=var_dump($_SESSION[UserTokenInterface::DEFAULT_PREFIX_KEY])?>
+ <?=
+ isset($_SESSION[UserTokenInterface::DEFAULT_PREFIX_KEY])
+ ? var_dump($_SESSION[UserTokenInterface::DEFAULT_PREFIX_KEY])
+ : 'none!'
+ --- */ ?>
</body>
</html> \ No newline at end of file