diff options
Diffstat (limited to 'public/app')
21 files changed, 604 insertions, 1155 deletions
diff --git a/public/app/config/setup_application.php b/public/app/config/setup_application.php index 88dc176..4eb7a55 100644 --- a/public/app/config/setup_application.php +++ b/public/app/config/setup_application.php @@ -69,11 +69,12 @@ define('USER_ACCESS_TYPE', [ ]); - -// ERRORS AND ERROR MESSAGES /////////////////////////////////////////////////// +// MESSAGES //////////////////////////////////////////////////////////////////// // ----------------------------------------------------------------------------- +// Error Mesagges, Warnings and other Common Mesages define('EMPTY_REQUIRED_FIELDS', 'Δεν έχουν συμπληρωθεί όλα τα υποχρεωτικά πεδία'); +define('TICKET_EXPIRED', 'Η φόρμα που συμπληρώσατε φαίνεται να έχει λήξη. Ανανεώστε τη και προσπαθήστε πάλι.'); diff --git a/public/app/controllers/Auth.php b/public/app/controllers/Auth.php index e2fe989..9f440ed 100644 --- a/public/app/controllers/Auth.php +++ b/public/app/controllers/Auth.php @@ -136,7 +136,7 @@ class Auth { * setups and renders the form for a certain invitation * * NOTE: - * after form is submited, client calls Auth::activate() + * after form is submited, client shall call Auth::activate() * * @param $id (string|MD5) : invitation code * @@ -144,15 +144,13 @@ class Auth { public static function invitation($id) { // get user from invitation number - $user_array = Registry::use('database')->query( - "SELECT * FROM user WHERE invitation = :id", - ['id' => $id] - )->getFirst(); - if ($user_array == false) { + $user_array = Access_model::getUserByInvitation($id); + + if ($user_array == false) { // no invitation ? serve error then die; Render::view('error/404', ['moto' => 'Δεν βρέθηκε η πρόσκληση']); die(); } - $user = json_decode( json_encode($user_array, JSON_UNESCAPED_UNICODE)); // user in json format + $user = json_decode(json_encode($user_array, JSON_UNESCAPED_UNICODE)); // format form_setup to a json array $form_setup = json_decode(json_encode(REGISTRATION_FORM, JSON_UNESCAPED_UNICODE)); @@ -342,6 +340,8 @@ class Auth { public static function in_admin_group() { + if (!self::is_connected()) return false; + $manager = new App_manager(); return ($manager->isGranted([1, 2, 3])); } diff --git a/public/app/controllers/Office.php b/public/app/controllers/Office.php index 800247e..9ff4e14 100644 --- a/public/app/controllers/Office.php +++ b/public/app/controllers/Office.php @@ -6,7 +6,7 @@ use Registry; use Render; use app\controllers\Auth; use app\extends\App_manager; -use app\models\Cms_model; +use app\models\Content_model; use app\extends\Cache_service; /** Office class @@ -112,10 +112,13 @@ class Office { - ## PETITIONS - ## ------------------------------------------------------------------------- - ## secretarial support / teachers' requests and applications + ## ------------------------------------------------------------------------- + ## + ## PETITION FORMS + ## secretarial support / serve forms for teachers' requests and applications + ## + ## ------------------------------------------------------------------------- /** request any (empty/new) petition form @@ -200,7 +203,7 @@ class Office { ]); // #5: create ticket; then render the view ----------------------------- - $ticket = self::create_ticket($ticket); // save ticket + $ticket = self::create_ticket(); // save ticket Render::view('templates/application', [ 'form' => $form, 'applier' => (($userData['prefix'] == 'η') ? 'Η Αιτούσα' : 'Ο Αιτών'), @@ -263,12 +266,55 @@ class Office { ## ------------------------------------------------------------------------- ## + ## PETITION SUBMITS + ## handle submits of forms + ## + ## ------------------------------------------------------------------------- + + + /** add_petition + * + * handle an add petition request (petition form is submited) + * + * @param void; all params are readed from POST, Auth and SESSION + * @return int new petition-id + */ + public static function add_petition() + { + $post = Registry::get('REQUEST')->POST; + + + if (self::remove_ticket($post['ticket'])) { // check ticket + remove + + $manager = new App_manager(); + + $new_id = Content_model::add_petition([ + 'user_id' => $manager->getUserToken()->getUser()->getID(), + 'type_id' => $post['type_id'], + 'subject' => $post['subject'], + 'signature' => $post['ticket'], + 'form_structure' => serialize($post) + ]); + + Render::json([ + 'success' => true, + 'id' => $new_id + ]); + + } else { + Render::json(['success' => false, 'error' => TICKET_EXPIRED]); + } + } + + + + ## ------------------------------------------------------------------------- + ## ## TICKET METHODS (create, remove) ## tickets eliminate CSRF attacks ## ## ------------------------------------------------------------------------- - /** create_ticket * * creates a tickef and saves it into session @@ -278,24 +324,29 @@ class Office { private static function create_ticket() { // create ticket - $tick = md5( time() . Auth::user_data() . rand(1,65536) ); + $tick = md5( time() . json_encode(Auth::user_data()) . rand(1,65536) ); // then save to session if (isset($_SESSION['tickets'])) { $tickets = explode(',', $_SESSION['tickets']); - $tickets[] = $tick; + + if (count($tickets) > 99) { // if more than 99 tickets + array_shift($tickets); // remove the older + } + $tickets[] = $tick; // add new ticket to the tickets list $_SESSION['tickets'] = implode(',', $tickets); } else { $_SESSION['tickets'] = $tick; } - return $tick; + return $tick; // return the xreated ticket } + /** remove_ticker * * removes a ticket and return true; - * if ticket not exists return fase; + * NOTE: if ticket not exists return false; * * @param string $t : ticket (MD5) * @return boolean diff --git a/public/app/models/Access_model.php b/public/app/models/Access_model.php index 023d361..844ff6b 100644 --- a/public/app/models/Access_model.php +++ b/public/app/models/Access_model.php @@ -33,6 +33,19 @@ class Access_model } + /** getUserByInvitation + * + * @param string $invitation + */ + public static function getUserByInvitation($invitation) + { + return Registry::use('database')->query( + "SELECT * FROM user WHERE invitation = :invitation", + ['invitation' => $invitation] + )->getFirst(); + } + + /** create user * * creates user record; @@ -156,24 +169,6 @@ class Access_model ## Set permission methods ## ------------------------------------------------------------------------- - - /** set_user_privileges - * - * @param $privileges (array) - */ - public static function set_user_privileges($user, $privileges) - { - $db = Registry::use('database'); // database connection - foreach($privileges as $pri) { // pri = privilege id - $db->runQuery( - "INSERT INTO user_privilege (user_id, privilege_id) VALUES (:user, :pri)", - [ ':user' => $user, ":pri" => $pri ] - ); - } - return true; - } - - /** set_user_role * * user, role are (int) IDs @@ -190,24 +185,4 @@ class Access_model } - ## List methods - ## ------------------------------------------------------------------------- - - - /** privileges - * --- - * get all privileges (as a list) - * used by cacher; speeds up seveal things - * - * @param void - * @return privileges (array) - */ - public static function privileges() - { - return Registry::use('database')->runQuery( - "SELECT * FROM privilege",[] - ); - } - - } diff --git a/public/app/models/Content_model.php b/public/app/models/Content_model.php new file mode 100644 index 0000000..ea19165 --- /dev/null +++ b/public/app/models/Content_model.php @@ -0,0 +1,101 @@ +<?php +namespace app\models; + +use \Registry; + + +class Content_model { + + ## P E T I T I O N S + ## ------------------------------------------------------------------------- + + /** add petition + * + * add petition record to the database + * + * @param array $data + * @return int new petition-ID + */ + public static function add_petition($data) + { + return Registry::use('database')->query( + "INSERT INTO petition + (user_id, `type_id`, `subject`, `signature`, `form_structure`) + VALUES (:user_id, :type_id, :subject, :signature, :form_structure)", + [ + ':user_id' => $data['user_id'], + ':type_id' => $data['type_id'], + ':subject' => $data['subject'], + ':signature' => $data['signature'], + ':form_structure' => $data['form_structure'] + ] + )->lastInsertID(); + } + + + /** set protocol + * + * @param int $pid: petition ID + * @param string $protocol: official pritocol number (full string) + */ + public static function set_protocol($pid, $protocol) + { + Registry::use('database')->runQuery( + "UPDATE petition SET protocol = :protocol WHERE id = :pid", + [ + ':protocol' => $protocol, + ':pid' => $pid + ] + ); + return true; + } + + + /** user petitions + * + * get all petitions of a user + * + * @param int $uid: user id + * @return array petition records + */ + public static function user_petitions($uid) + { + return Registry::use('database')->runQuery( + "SELECT * FROM petition WHERE user_id = :uid", + [ ':uid' => $uid ] + ); + } + + + /** all petitions + * + * get all petitions of a user + * + * @param void + * @return array petition records + */ + public static function all_petitions() + { + return Registry::use('database')->runQuery( + "SELECT * FROM petition", + [] + ); + } + + + + ## F I L E S + ## ------------------------------------------------------------------------- + + /** files + * return all files + * @param void + * @return array + */ + public static function files() + { + return Registry::use('database')->runQuery("SELECT * from media", []); + } + + +} diff --git a/public/app/models/Office_model.php b/public/app/models/Office_model.php deleted file mode 100644 index fad11b8..0000000 --- a/public/app/models/Office_model.php +++ /dev/null @@ -1,314 +0,0 @@ -<?php -namespace app\models; - -use \Registry; - - -class Cms_model { - - /** COURSES - * ------------------------------------------------------------------------- - */ - - /** get all categories - * - * raw table data (simplest SELECT) - * - */ - public static function get_categories() - { - return Registry::use('database')->runQuery( - "SELECT * FROM course ORDER BY label", - [] - ); - } - - /** courses struct - * - * a super array with almost any info needed about courses - * - * @return (array) ['tree' => ..., 'breadcrumbs' => ... ] - */ - public static function courses_struct() - { - $tree = self::category_tree(); - return [ - 'tree' => $tree, - 'breadcrumbs' => self::breadcrumbs($tree) - ]; - } - - - /** 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'], - 'order' => $rec['order'], - '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: - * --- - * Cms_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; - } - - - - - /** LESSONS - * ------------------------------------------------------------------------- - */ - - - /** lessons of course - * - * @param $id (int) : course_id - */ - public static function lessons_of_course($id) - { - // TODO: order results in some way - - return Registry::use('database')->runQuery( - "SELECT lesson.*, lesson_privilege.privilege_id FROM lesson - LEFT JOIN lesson_privilege ON lesson_privilege.lesson_id = lesson.id - WHERE lesson.status = 1 AND lesson.course_id = :id - ORDER BY lesson_privilege.privilege_id ASC", - [':id' => $id] - ); - } - - /** lesson - * - * @param $id (int) : lesson id - */ - public static function lesson($id) - { - // TODO: order results in some way - - return Registry::use('database')->query( - "SELECT lesson.*, lesson_privilege.privilege_id FROM lesson - LEFT JOIN lesson_privilege ON lesson_privilege.lesson_id = lesson.id - WHERE lesson.status = 1 AND lesson.id = :id", - [':id' => $id] - )->getFirst(); - } - - - - /** files - * return all files - * @param void - * @return array - */ - public static function files() - { - return Registry::use('database')->runQuery("SELECT * from media", []); - } - - - /** pages - * - * return all pages as array; - * array key of each item shall be the page-id - * - * @param void - * @return array - */ - public static function pages() - { - $result = []; - $pages = Registry::use('database')->runQuery("SELECT * FROM page", []); - foreach($pages as $key => $page) { - $result[ $page['id'] ] = [ - 'title' => $page['title'], - 'body' => $page['body'], - 'status' => $page['status'] - ]; - } - // print_r($result); die(); - return $result; - } - -} diff --git a/public/app/models/_info.md b/public/app/models/_info.md index ac6d334..9f02061 100644 --- a/public/app/models/_info.md +++ b/public/app/models/_info.md @@ -3,68 +3,72 @@ ## user fields; insert / update sql queries -INSERT INTO user -( id, - prefix, - first_name, - last_name, - email, - father_name, - registration_number, - sector_id, - specialty, - belonging_school, - working_shcool, - position_type_id, - phone, - password, - expiration, - otp, - otp_expiration, - activation, - creation, -active) VALUES (:id, - :prefix, - :first_name, - :last_name, - :email, - :father_name, - :registration_number, - :sector_id, - :specialty, - :belonging_school, - :working_shcool, - :position_type_id, - :phone, - :password, - :expiration, - :otp, - :otp_expiration, - :activation, - :creation, -:active ) - - -UPDATE user -SET prefix = :prefix, -first_name = :first_name, -last_name = :last_name, -email = :email, -father_name = :father_name, -registration_number = :registration_number, -sector_id = :sector_id, -specialty = :specialty, -belonging_school = :belonging_school, -working_shcool = :working_shcool, -position_type_id = :position_type_id, -phone = :phone, -password = :password, -expiration = :expiration, -otp = :otp, -otp_expiration = :otp_expiration, -activation = :activation, -creation = :creation, -active = :active, +Insert user: + + INSERT INTO user + ( id, + prefix, + first_name, + last_name, + email, + father_name, + registration_number, + sector_id, + specialty, + belonging_school, + working_shcool, + position_type_id, + phone, + password, + expiration, + otp, + otp_expiration, + activation, + creation, + active) VALUES (:id, + :prefix, + :first_name, + :last_name, + :email, + :father_name, + :registration_number, + :sector_id, + :specialty, + :belonging_school, + :working_shcool, + :position_type_id, + :phone, + :password, + :expiration, + :otp, + :otp_expiration, + :activation, + :creation, + :active ) + + +Update user + + UPDATE user + SET prefix = :prefix, + first_name = :first_name, + last_name = :last_name, + email = :email, + father_name = :father_name, + registration_number = :registration_number, + sector_id = :sector_id, + specialty = :specialty, + belonging_school = :belonging_school, + working_shcool = :working_shcool, + position_type_id = :position_type_id, + phone = :phone, + password = :password, + expiration = :expiration, + otp = :otp, + otp_expiration = :otp_expiration, + activation = :activation, + creation = :creation, + active = :active, ## record_types @@ -158,16 +162,122 @@ call_user_func(array($myobject, 'say_hello')); \ controllers [ ] App - [ ] Auth + [*] Auth \ extends [ ] Cache_service [*] App_manager [*] App_user [ ] SendMail_service - [ ] Form_builder + [*] Form_builder \ models [ ] Access_model - [ ] History_model
\ No newline at end of file + [ ] History_model + + + +# DataBase Structure + + + + SET NAMES utf8; + SET time_zone = '+00:00'; + SET foreign_key_checks = 0; + SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; + + SET NAMES utf8mb4; + + DROP TABLE IF EXISTS `history`; + CREATE TABLE `history` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `type` smallint(6) NOT NULL, + `message` varchar(140) COLLATE utf8mb4_unicode_ci NOT NULL, + `note` text COLLATE utf8mb4_unicode_ci, + `ip` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `user_id` (`user_id`), + CONSTRAINT `history_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + + DROP TABLE IF EXISTS `media`; + CREATE TABLE `media` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `title` varchar(256) COLLATE utf8mb4_unicode_ci NOT NULL, + `user_id` int(11) NOT NULL, + `path` varchar(512) COLLATE utf8mb4_unicode_ci NOT NULL, + `type` varchar(512) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'media-type', + PRIMARY KEY (`id`), + KEY `user_id` (`user_id`), + CONSTRAINT `media_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + + DROP TABLE IF EXISTS `petition`; + CREATE TABLE `petition` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `type_id` smallint(6) NOT NULL, + `form_structure` text COLLATE utf8mb4_unicode_ci NOT NULL, + `protocol` int(11) DEFAULT NULL, + `signature` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL, + `record_date` date DEFAULT NULL, + `creation_date` datetime DEFAULT CURRENT_TIMESTAMP, + `update_date` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `signature` (`signature`), + KEY `user_id` (`user_id`), + CONSTRAINT `petition_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + + DROP TABLE IF EXISTS `petition_media`; + CREATE TABLE `petition_media` ( + `petition_id` bigint(20) NOT NULL, + `media_id` bigint(20) NOT NULL, + KEY `petition_id` (`petition_id`), + KEY `media_id` (`media_id`), + CONSTRAINT `petition_media_ibfk_1` FOREIGN KEY (`petition_id`) REFERENCES `petition` (`id`), + CONSTRAINT `petition_media_ibfk_2` FOREIGN KEY (`media_id`) REFERENCES `media` (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + + DROP TABLE IF EXISTS `role`; + CREATE TABLE `role` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `alias` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL, + `label` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + + DROP TABLE IF EXISTS `user`; + CREATE TABLE `user` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `prefix` varchar(16) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `first_name` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL, + `last_name` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL, + `email` varchar(48) COLLATE utf8mb4_unicode_ci NOT NULL, + `father_name` varchar(48) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `registration_number` bigint(20) DEFAULT NULL COMMENT 'AM', + `sector` varchar(48) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'sector_id + speciality', + `belonging_school` varchar(96) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `position` varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'chief, permanent, deputy etc', + `phone` varchar(16) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `password` varchar(160) COLLATE utf8mb4_unicode_ci DEFAULT NULL, + `role_id` int(11) DEFAULT NULL, + `expiration` datetime DEFAULT NULL COMMENT 'account expiration datetime', + `otp` varchar(16) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'one time password for reset password', + `otp_expiration` datetime DEFAULT NULL, + `invitation` varchar(160) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'invitation code', + `creation_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'creation datetime', + `update_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `active` smallint(6) NOT NULL DEFAULT '0' COMMENT 'account status flag; 1=active 0=inactive', + PRIMARY KEY (`id`), + KEY `role_id` (`role_id`), + CONSTRAINT `user_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`) ON DELETE NO ACTION + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + diff --git a/public/app/routes/frontend.php b/public/app/routes/frontend.php index 14152c1..adfe936 100644 --- a/public/app/routes/frontend.php +++ b/public/app/routes/frontend.php @@ -13,6 +13,12 @@ use app\extends\Cache_service; Route::add('/', function() { Render::view('user/login'); }); + +// invitation +//////////////////////////////////////////////////////////////////////////////// + +// request invitation (for account activation) +// --- -- -- - - - Route::add('/invitation/([0-9]*)', function($id) { if ($id == "" || $id == "0") { Render::view('error/404'); } else { @@ -20,15 +26,16 @@ Route::add('/invitation/([0-9]*)', function($id) { } }); -// new petition -Route::add('/petition/([0-9a-z\-_]*)', function($tag) { - Office::request_petition($tag); -}); +// request activation (submit invitation; POST:form is sent) +// --- -- -- - - - +Route::add('/account/activate', function() { Auth::activate(); }, 'post'); -// existing petition -Route::add('/petition/([0-9a-z\-_]*)/([0-9a-f]*)', function($tag) { - Office::filter_request_petition($tag, $id); -}); +// DEPRICATED: user sends a registration form +// --- -- -- - - - +# Route::add('/account/register', function() { +# $response = Auth::register(); +# Render::json($response); +# },'post'); @@ -42,141 +49,102 @@ Route::notFound( function() { // 404 error page -// Common content -//////////////////////////////////////////////////////////////////////////////// - - -Route::add('/course/([0-9]*)', // request course by course-id - function($id) { Cms::course($id); } -); - -Route::add('/lesson/([0-9]*)', // request lesson by lesson-id - function($id) { Cms::lesson($id); } -); - -Route::add('/page/([0-9]*)', // request lesson by lesson-id - function($id) { Cms::page($id); } -); - -Route::add('/serve/file/([0-9a-zA-Z-_\.\/]*)', // serve file by path - function ($path) { Cms::serve_file($path); } // (also ?type= is sent) -); - - - - -// Account -//////////////////////////////////////////////////////////////////////////////// - -// [ok] login -// [ok] register -// [ok] activate -// [..] ask-reset -// [..] reset -// [..] profile -// [..] edit-profile -// [..] subscriptions -// [..] payments -// [..] pay -// [..] order - - - - -/** URL-format Proposals and common Route regex solutions +/** Examples of real-world route formats + * + * URL-format Proposals and common Route regex solutions * ----------------------------------------------------------------------------- * * Page (almost-static content): * /about/{url} -# Route::add('/about/([0-9a-zA-Z-_\/]*)', function($url) { Page::fromUrl($url); }); + # Route::add('/about/([0-9a-zA-Z-_\/]*)', function($url) { Page::fromUrl($url); }); * * Product: * /{level-1}/{level-2}/{level-3}/{friendly-url}-{id} -# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)-([0-9]*)', -# function($category, $subcategory, $group, $label, $id) { -# Product::fromID([$$category, $subcategory, $group, $label], $id); -# } -# ); + # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)-([0-9]*)', + # function($category, $subcategory, $group, $label, $id) { + # Product::fromID([$$category, $subcategory, $group, $label], $id); + # } + # ); * * Category * /{category}/[ {subcategory}[ /{group}]] -# Route::add('/([0-9a-zA-Z-_]*)', function($a) { Category::url([$a]); }; -# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b) { Category::url([$a, $b]); }); -# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b, $c) { Category::url([$a, $b, $c]); }); + # Route::add('/([0-9a-zA-Z-_]*)', function($a) { Category::url([$a]); }; + # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b) { Category::url([$a, $b]); }); + # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b, $c) { Category::url([$a, $b, $c]); }); * * othet routes used in some user-cases - -# Route::add('/lesson/([0-9a-f]*)/([0-9a-zA-Z-_]*)', -# function($ticket, $lesson) { Lesson::show([$lesson, $ticket]); } -# ); -# -# Route::add('/media/([0-9a-f]*)/([0-9a-zA-Z-_]*)/([0-9]*)/', -# function($ticket, $type, $id) { Media::serve([$type, $id, $ticket]); } -# ); + * + # Route::add('/lesson/([0-9a-f]*)/([0-9a-zA-Z-_]*)', + # function($ticket, $lesson) { Lesson::show([$lesson, $ticket]); } + # ); + # + # Route::add('/media/([0-9a-f]*)/([0-9a-zA-Z-_]*)/([0-9]*)/', + # function($ticket, $type, $id) { Media::serve([$type, $id, $ticket]); } + # ); * * 4-th level paths belong to products -# Route::add('/about/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', -# function($a, $b, $c) { Page::show([$a, $b, $c]); } -# ); + # Route::add('/about/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', + # function($a, $b, $c) { Page::show([$a, $b, $c]); } + # ); * * * OTHER EXAMPLES (use it for brainsrtorming) * ----------------------------------------------------------------------------- * * -# // Typical Use -# // --- -# Route::add('/art', function() { Art::blah(); }); -# Route::add('/art/db', function() { Art::fromDatabase(); }); -# Route::add('/art/([0-9]*)', function($id) { Art::getInfo($id); }); + # // Typical Use + # // --- + # Route::add('/art', function() { Art::blah(); }); + # Route::add('/art/db', function() { Art::fromDatabase(); }); + # Route::add('/art/([0-9]*)', function($id) { Art::getInfo($id); }); * * Get-Post route example -# Route::add('/contact-form', function() { -# echo '<form method="post"><input type="text" name="test" /><input type="submit" value="send" /></form>'; -# }, 'get'); - - Route::add('/contact-form', function() { - echo 'Hey! The form has been sent:<br/>'; print_r($_POST); - }, 'post'); + # Route::add('/contact-form', function() { + # echo '<form method="post"><input type="text" name="test" /><input type="submit" value="send" /></form>'; + # }, 'get'); + + Route::add('/contact-form', function() { + echo 'Hey! The form has been sent:<br/>'; print_r($_POST); + }, 'post'); * * Accept number as parameter -# Route::add('/foo/([0-9]*)/bar', function($var1) { -# // echo $var1.' is a number!'; - echo "{$var1} is a number!"; -# }); + # Route::add('/foo/([0-9]*)/bar', function($var1) { + # // echo $var1.' is a number!'; + echo "{$var1} is a number!"; + # }); * * About pages -# Route::add('/about/([0-9a-zA-Z-_]*)', function($page) { -# InfoPage::render('about/'.page); -# }); + # Route::add('/about/([0-9a-zA-Z-_]*)', function($page) { + # InfoPage::render('about/'.page); + # }); * * handle a request like: /foo/123/bar/3254-lefki-zaxari-marata-1kg * where first-numeric-part of last-uri-section (3254) is the product number -# Route::add('/foo/([0-9]*)/bar/([0-9]*)-([0-9a-zA-Z-_]*)', function($num, $id, $name) { -# echo $num .' is some nomber, id = '. $id .' and label = '. $name; -# }); + # Route::add('/foo/([0-9]*)/bar/([0-9]*)-([0-9a-zA-Z-_]*)', function($num, $id, $name) { + # echo $num .' is some nomber, id = '. $id .' and label = '. $name; + # }); * * handle a request like: /zaxares-glykantika/lefki-zaxari-year-2022-45678 * where last-numeric-part of last-uri-section (45678) is the product number -# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)-([0-9]*)', -# function($category, $subcategory, $group, $label, $id) { -# Shop::product([$$category, $subcategory, $group, $label], $id); -# }); + # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)-([0-9]*)', + # function($category, $subcategory, $group, $label, $id) { + # Shop::product([$$category, $subcategory, $group, $label], $id); + # }); * * last chance to resolve (some friendly url) -# Route::add('/([0-9a-zA-Z-_]*)', function($a) { Resolve::uri([$a]); }); -# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b) { Resolve::uri([$a, $b]); }); -# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b, $c) { Resolve::uri([$a, $b, $c]); }); + # Route::add('/([0-9a-zA-Z-_]*)', function($a) { Resolve::uri([$a]); }); + # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b) { Resolve::uri([$a, $b]); }); + # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b, $c) { Resolve::uri([$a, $b, $c]); }); * * * Product page * handle a request like: /pantopoleio/zaxares/lefki-zaxari/lefki-zaxari-year-2022-45678 * where last-numeric-part of last-uri-section (45678) is the product number -# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)-([0-9]*)', -# function($category, $subcategory, $group, $label, $id) { -# Shop::product([$$category, $subcategory, $group, $label], $id); -# }); + # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)-([0-9]*)', + # function($category, $subcategory, $group, $label, $id) { + # Shop::product([$$category, $subcategory, $group, $label], $id); + # }); * * ------------------------------------------------------------------------------ - */ +*/ diff --git a/public/app/routes/user.php b/public/app/routes/user.php index 26483f4..12ca7d2 100644 --- a/public/app/routes/user.php +++ b/public/app/routes/user.php @@ -2,6 +2,7 @@ use app\controllers\Auth; use app\controllers\Classroom_user; +use app\controllers\Office; /** User Connection Management Routes @@ -25,28 +26,12 @@ Route::add('/logout', function() { header('Location: /'); die(); }); -// request activation (from invitation page; POST:form is sent) -Route::add('/account/activate', function() { Auth::activate(); }, 'post'); + // request password reset Route::add('/account/reset_password', function() { Auth::reset_password(); } ); -// invite some users -Route::add('/invite', function() { - Auth::allowRoles([1, 2, 3]); - Render::view('admin/invite'); -}); - -Route::add('/panel', function() { - Render::view('user/panel'); - // Render::json([ - // 'connected' => Auth::is_connected(), - // 'user' => Auth::user_data(), - // ]); -}); - - // Replies to common requests (POST method) // --- -- -- - - - @@ -58,36 +43,105 @@ Route::add('/account/check-login', function() { 'post' ); -// user sends a registration form -Route::add('/account/register', function() { - $response = Auth::register(); - Render::json($response); -},'post'); -// Account Management -// --- -- -- - - - +/* DEPRICATED: + // 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" + ] + ); -// 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 { - Render::json(['success' => true, 'status' => 'user is connected']); + } else { + Render::json(['success' => true, 'status' => 'user is connected']); + } } - } -); + ); +--- */ + + +// routes for connected users +//////////////////////////////////////////////////////////////////////////////// + +if (Auth::is_connected()) { + + // serve content + // ------------------------------------------------------------------------- + + // control panel + // --- -- -- - - - + Route::add('/panel', function() { + Render::view('user/panel',[ + 'is_admin' => Auth::in_admin_group(), + 'content' => 'info', + 'user' => json_decode(json_encode( + Auth::user_data(), JSON_UNESCAPED_UNICODE + )) + ]); + }); + + // file of petitions + // --- -- -- - - - + Route::add('/user/petitions', function() { + Render::view('admin/invite'); + }); + + // request New petition form + // --- -- -- - - - + Route::add('/petition/([0-9a-z\-_]*)', function($tag) { + Office::request_petition($tag); + }); + + // request existing petition + // --- -- -- - - - + Route::add('/petition/signature/([0-9a-f]*)', function($signature) { + Office::filter_request_petition($signature); + }); + + + // CRUD content + // ------------------------------------------------------------------------- + + // add petition + // --- -- -- - - - + Route::add('/petition/new', function() { + Office::add_petition(); + }, 'post'); + + +} + + + +// routes for administrators +//////////////////////////////////////////////////////////////////////////////// + +if (Auth::in_admin_group()) { + + // administer petitions + // --- -- -- - - - + Route::add('/admin/petitions', function() { + Render::view('user/panel'); + }); + + // invite user(s) + // --- -- -- - - - + Route::add('/admin/invite', function() { + Render::view('admin/invite'); + }); +} // temporary (on development) -// --- -- -- - -- +//////////////////////////////////////////////////////////////////////////////// // NOTE: these is only for testing purposes // test connection diff --git a/public/app/views/components/breadcrumbs.php b/public/app/views/components/breadcrumbs.php deleted file mode 100644 index 59c0fca..0000000 --- a/public/app/views/components/breadcrumbs.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -/** breadcrumbs - * ----------------------------------------------------------------------------- - * - * imported variables - * --- - * @param $id : category_id of last level - * @param $label : category title of last level - * @param $parents : array of parent nodes - * ----------------------------------------------------------------------------- - */ - -?> -<div class="breadcrumb"> - <!-- home --> - <a href="/">Classroom</a> - - <!-- parent nodes --> - <?php if ($id != 0) : ?> - <?php foreach($parents as $node) : ?> - <i class="fas fa-angle-right"></i> <a href="/course/<?=$node['id']?>"><?=$node['label']?></a> - <?php endforeach; ?> - <?php endif; ?> - - <!-- last (current) node --> - <?php if ($id != 0) : ?> - <i class="fas fa-angle-right"></i> <a href="/course/<?=$id?>"><?=$label?></a> - <?php endif; ?> - -</div>
\ No newline at end of file diff --git a/public/app/views/components/courses_menu.php b/public/app/views/components/courses_menu.php deleted file mode 100644 index 6539f8c..0000000 --- a/public/app/views/components/courses_menu.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php -/** Categories Menu - * ----------------------------------------------------------------------------- - * sits in the (left) sidebar - * - * imported variables - * --- - * @param $categories (array) : the categories tree - * @param $open_path (array) : 'id's array of selected categories - * - * example call: - * (draw the categories-menu and set open the categories with ids 1 and 2) - * --- - * Render::template("section/categories_menu.php",[ - * 'categories' => $category_tree, - * 'open_path' => [1 ,2] - * ]); - * - * ----------------------------------------------------------------------------- - */ - -/** tree_ul - * creates (recursively) a nested ul-li tree of categories - * --- -- -- - - - - * @param $tree (array) : categories array formated as tree - * @param $open_nodes (array) : array of categor ids that shall be marked open/selected - * @return $html (string) - */ -function tree_li($tree, $open_nodes = [], $l = 0) -{ - $html = ""; - - foreach($tree as $node) { - - // if has childs ... - // write li ; traverse children recursively - if ((isset($node['childs'])) && ( $node['childs']!= [])) { - - if (in_array(intval($node['rec']['id']), $open_nodes)) { - $inner_class = "inner show"; - $sign = "–"; - $a_class = "has-childs selected"; - - } else { - $inner_class = "inner"; - $sign = "+"; - $a_class = "has-childs"; - } - - $html .= "<li> - <a href='/course/{$node['rec']['id']}' class='{$a_class}'> - <span class='label'>{$node['rec']['label']}</span> - <span class='toggler'>{$sign}</span> - </a> - <ul class='{$inner_class}'>" - . tree_li($node['childs'], $open_nodes, $l+1) - ."</ul> - </li>"; - - - } else { // else just write the li - - if (in_array(intval($node['rec']['id']), $open_nodes)) { - $u_in = "<u>"; - $u_out = "</u>"; - $a_class = "selected"; - - } else { - $u_in = ""; - $u_out = ""; - $a_class = ""; - - } - - $html .= "<li> - <a href='/course/{$node['rec']['id']}' class='{$a_class}'> - <span class='label'>{$node['rec']['label']}</span> - </a> - </li>"; - } - } - - return $html; - -} - - -// draw the menu (hidden on XS screens) -// ----------------------------------------------------------------------------- -echo "<h3>Διαθέσιμη ύλη</h3>"; -echo "<ul class='hidden-xs side-bar'>". tree_li($categories, $open_path) ."</ul>"; - - - -// TODO: -// draw menu for XS screens (for example, just the 1st-level categories) -// (maybe in an accordion so it won;t take too much area on small screens) diff --git a/public/app/views/components/footer.php b/public/app/views/components/footer.php deleted file mode 100644 index 7cd4a5a..0000000 --- a/public/app/views/components/footer.php +++ /dev/null @@ -1,240 +0,0 @@ -<?php - -use app\extends\Cache_service; - - -/** DESIGNERS - * ----------------------------------------------------------------------------- - * - * structures that combine several design information - * in a json structrure and parses inta a quite complicated view; - * - * co-operate with pages - * - * can be used to rended menus, sections like header or footer etc; - * - * TODO: - * + embed it as a core \Render method - * + dynamic designers - * + recursive designers - * - * Here we implement a simplified version of the consept - * where entities shall always be `pages` - * - * - * PARAMETRES - * --- -- -- - - - - * - * primary properties of designer structure are 2 properties - * - * @var class (string): container class name - * @var struct (json array): representatoion of the "to-be-designed" structure - * - * TODO: support more complx `class` strings ex. `.container>#footer>row` - * - * - * Each sub-structure has 2-5 properties: - * - * @var title (string) : title of the sub-section - * @var entity (string) : type of entity (ex: page/lesson/etc; TODO: method of CMS_model?) - * @var list (array) : list of entity id(s) - * @var template (string) : template that is used to draw the listed pages' info - * @var width (string) : class that relates to sub-structure's width - * - * NOTE: - * designer parsing and rendering can be a quite expensive proccess - * thus it is strongly recommented to use cached entities - * - * - * Example structure: - { - "class" : "row", # container class - "struct" : [ - { # block 1 - "title" : "", - "entity" : "page", - "list" : [2, 1, 3], # pages to be listed - "template" : "list", # list page titles with link to the pages - "width" : "col-md-4" - }, - { - "template" : "null", # list nothing - "width" : "col-md-3" - }, - { - "entity" : "page", - "list" : [4], # list content of page 4; - "template" : "content", # set title to page-title - "width" : "col-md-5" - } - - TODO: (wish) - ,{ - "template": "struct", - "struct" : [ - { - title, entity, list, template, width - }, - ... - ] - } - ] - } - * - * brainstormin: (TODO:) - * use some document-describe stucture like the one on the pdfmake js-library - * ----------------------------------------------------------------------------- - */ - - -/** check imported variables / data - * ----------------------------------------------------------------------------- - */ -if (!isset($designer)) { - - // default designer (and first case-study) - $designer = '{ - "class" : "row", - "struct" : [ - { - "title" : "Πληροφορίες", - "entity" : "page", - "list" : [2, 1, 3, 4], - "template" : "list", - "width" : "col-md-4 no-list-mark" - }, - { - "entity" : "page", - "list" : [6], - "template" : "content", - "width" : "col-md-3 no-list-mark" - }, - { - "entity" : "page", - "list" : [5], - "template" : "content", - "width" : "col-md-5 no-list-mark" - } - ] - }'; -} - -// $entity list shall be passed -// entity link url shall be passed - - -/** templating functions - * ----------------------------------------------------------------------------- - */ - -/** List template - * --- -- -- - - - - * - * lists entity titles with links - * in a `ul>li` html-structure - * - * @param $title - * @param $list - * @param $container - */ -function list_template($title, $list, $container, $entity) { - - $result = '<div class="'. $container .'"> - <h4>'. $title .'</h4> - <ul>'; - - foreach($list as $id) { - - if ($entity[$id]['status'] == 1) { // if entity is published - $result .= ' - <li> - <a href="/page/'. $id . '"> - ' . $entity[$id]['title'] .' - </a> - </li>'; - } - - } - return $result . '</ul></div>'; -} - -/** content_template - * - * lists whole title and content of entity - * - * @param $list - * @param $container - */ -function content_template($list, $container, $entity) { - - $parsedown = new Parsedown(); - - $result = '<div class="'. $container .'"><ul>'; - - foreach($list as $id) { - - if ($entity[$id]['status'] == 1) { // if entity is published - - $result .= ' - <li> - <h4>'. $entity[$id]['title'] .'</h4> - <div>'. $parsedown->text($entity[$id]['body']) .'</div> - </li>'; - } - - } - return $result .'</ul></div>'; -} - - -/** ready to start the proccessing - * ----------------------------------------------------------------------------- - */ - -// decode ... -$parse = json_decode($designer); - -/** then start parse-proccessing ... - * ----------------------------------------------------------------------------- - */ -?> - - - -<div class="<?=$parse->class?>"> - - <?php - foreach( $parse->struct as $section ) { - - switch ($section->template) { - - case 'list': - echo list_template( - $section->title, - $section->list, - $section->width, - $entity - ); - break; - - case 'content': - echo content_template( - $section->list, - $section->width, - $entity - ); - break; - - default: // ex. 'null' - - echo '<div class="'. $section->width .'"> - <h4>'. $section->title.'</h4> - </div>'; - } - - } - ?> - -</div> - - diff --git a/public/app/views/components/info.php b/public/app/views/components/info.php new file mode 100644 index 0000000..02c13e9 --- /dev/null +++ b/public/app/views/components/info.php @@ -0,0 +1,28 @@ +<?php +/** Menu of words (for logged-in user) + * ----------------------------------------------------------------------------- + * + * imported: + * @var stdClass $user (mandatory) + * @var boolen $is_admin (mandatory) + */ +?> +<div class="info"> + <p> </p> + <p> + <b><?=$user->first_name?> <?=$user->last_name?></b> + <?php if ($is_admin) : ?> + (Administrator) + <?php endif; ?> + </p> + + <p><b><?=$user->position?></b></p> + <p><b><?=$user->sector?></b></p> + + <p>AM: <b><?=$user->registration_number?></b></p> + + <p>Email: <b><?=$user->email?></b></p> + <p>Tηλέφωνο: <b><?=$user->phone?></b></p> + +</div> + diff --git a/public/app/views/components/lessons_list.php b/public/app/views/components/lessons_list.php deleted file mode 100644 index a778d59..0000000 --- a/public/app/views/components/lessons_list.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php -/** lessons list - * ----------------------------------------------------------------------------- - * - * imported variables: - * --- - * @param $lessons : array of lessons - * @param $fieldset : array of optional fields to show [category, intro, date] - * - * example call: - * --- - * Render::template("sections/articles_list.php",[ - * 'articles' => $category_tree, - * 'fieldset' => ['date', 'intro'] - * ]) - * ----------------------------------------------------------------------------- - */ -?> - - -<?php foreach($lessons as $post) : ?> - - <!-- <div class="col-xl-4 col-lg-6"> --> - <div class="post-card"> - - <?php if (in_array('date', $fieldset)) : ?> - <?=$post['date']?> - <?php endif; ?> - - <div class="post-card--content"> - - <h3> - <a href="/lesson/<?=$post['id']?>"><?=$post['title']?></a> - </h3> - - <?php if (in_array('level', $fieldset)) : ?> - <p class="getegory">(επίπεδο πρόσβασης <?=$post['privilege_id']?>)</p> - <?php endif; ?> - - <?php if (in_array('category', $fieldset)) : ?> - <p class="category"><?=$post['course_id']?></p> - <?php endif; ?> - - <?php if (in_array('intro', $fieldset) && $post['intro']) : ?> - <p class="intro"><?=$post['intro']?></p> - <?php endif; ?> - - </div> - - </div> - <!-- </div> --> - -<?php endforeach; ?> - diff --git a/public/app/views/components/menu.php b/public/app/views/components/menu.php index 60ad395..524547c 100644 --- a/public/app/views/components/menu.php +++ b/public/app/views/components/menu.php @@ -1,17 +1,31 @@ +<?php +/** Menu of words (for logged-in user) + * ----------------------------------------------------------------------------- + * + * imported: + * @var boolen $is_admin (mandatory) + */ +?> <ul class="list-group"> <li class="list-group-item"><a href="/petition/application">Νέα Αίτηση</a></li> <li class="list-group-item"><a href="/petition/penalty">Νέo Πρακτικό Πειθαρχικής Υπόθεσης</a></li> - <li class="list-group-item separator">Αρχείο</li> - <li class="list-group-item"><a href="/account/petitions">Πρακτικά και οι αιτήσεις</a></li> + + <li class="list-group-item separator">To αρχείο σας</li> + <li class="list-group-item"><a href="/user/petitions">Πρακτικά και αιτήσεις</a></li> + <li class="list-group-item separator">Προφίλ</li> - <li class="list-group-item"><a href="/account/update">Ενημέρωση των στοιχείων σας</a></li> - <li class="list-group-item"><a href="/account/new-password">Αλλαγή password</a></li> + <li class="list-group-item"><a href="/user/update">Ενημέρωση στοιχείων</a></li> + <li class="list-group-item"><a href="/user/new-password">Αλλαγή password</a></li> + + <?php if ($is_admin) : ?> <li class="list-group-item separator">Διαχείριση</li> - <li class="list-group-item"><a href="/account/update">Κατάσταση πρακτικών & αιτήσεων</a></li> - <li class="list-group-item"><a href="/account/update">Αποστολή προσκλήσεων</a></li> + <li class="list-group-item"><a href="/admin/petitions">Κατάσταση πρακτικών & αιτήσεων</a></li> + <li class="list-group-item"><a href="/admin/invite">Αποστολή προσκλήσεων</a></li> + <?php endif; ?> + <li class="list-group-item separator"></li> + <li class="list-group-item"><a href="/logout">Αποσύνδεση</a></li> </ul> - diff --git a/public/app/views/components/subcategories.php b/public/app/views/components/subcategories.php deleted file mode 100644 index 5c05a94..0000000 --- a/public/app/views/components/subcategories.php +++ /dev/null @@ -1,19 +0,0 @@ -<!-- Sub-Categories --> - -<?php if ($breadcrumbs[ $id ]['childs'] != []) : ?> - - <h5>Υποκεφάλαια</h5> - - <div class="category-childs"> - - <?php foreach($breadcrumbs[ $id ]['childs'] as $key => $child) : ?> - - <a href="/course/<?=$child['id']?>" class="btn btn-light"> - <?=$child['label']?> - </a> - - <?php endforeach; ?> - - </div> - -<?php endif; ?>
\ No newline at end of file diff --git a/public/app/views/components/top_bar.php b/public/app/views/components/top_bar.php deleted file mode 100644 index eaffe76..0000000 --- a/public/app/views/components/top_bar.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php -/** top bar - * ----------------------------------------------------------------------------- - * - * rendrers breadcrumbs and user menu - * - * imported variables - * --- - * @param $id : category_id of last level - * @param $label : category title of last level - * @param $parents : array of parent nodes - * ----------------------------------------------------------------------------- - */ - -// initialize variables needed if not passed -// (needed while requiring breadcrumbs) -if (!isset($id)) { - $id = 0; - $label = ""; - $parents = []; -} - -?> -<div class="top-bar"> - - <?php // breadcrumbs - //////////////////////////////////////////////////////////////////////// - Render::view("components/breadcrumbs", [ - 'id' => $id, - 'label' => $label, - 'parents' => $parents - ]); - ?> - - <?php // User management drop-down - //////////////////////////////////////////////////////////////////////// - Render::view('components/user-management'); - ?> - -</div><!-- /top-bar -->
\ No newline at end of file diff --git a/public/app/views/components/user-management.php b/public/app/views/components/user-management.php deleted file mode 100644 index 636f2ff..0000000 --- a/public/app/views/components/user-management.php +++ /dev/null @@ -1,65 +0,0 @@ -<div class="user"> - - <div class="dropdown js-visitor"> - <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="/login">Είσοδος</a></li> - - <li><hr class="dropdown-divider"></li> - - <li><a class="dropdown-item" href="/registration">Εγγραφή</a></li> - <li><a class="dropdown-item disabled" href="/reset-password">Επαναφορά password</a></li> - </ul> - </div> - - <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="/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> - - <li><a class="dropdown-item" href="/logout">Έξοδος</a></li> - </ul> - </div> - -</div> - - -<script> - // 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/js/pdf-designer/application.php b/public/app/views/js/pdf-designer/application.php index 1d77c67..7441094 100644 --- a/public/app/views/js/pdf-designer/application.php +++ b/public/app/views/js/pdf-designer/application.php @@ -11,6 +11,11 @@ function designer(data, defines) { var elDate = d.toLocaleDateString('el-GR', options); var year = d.getFullYear().toString(); + // var tick_parts = defines.ticket.match(/.{1,4}/g) ?? []; + // var easyread_ticket = tick_parts.join('-'); + + + // get labels from id-specified objects let petition = 'Αίτηση'; @@ -104,7 +109,7 @@ function designer(data, defines) { footer: { text: [ 'Αριθμός πρωτοκόλου: A124-2501-4568-7 / 2023-12-15', - '\ndocument signature: ' + defines.ticket + '\ndocument signature: ' + defines.ticket ], style: 'signature' diff --git a/public/app/views/js/submit/application-form.php b/public/app/views/js/submit/application-form.php index ed77c1f..2480d67 100644 --- a/public/app/views/js/submit/application-form.php +++ b/public/app/views/js/submit/application-form.php @@ -3,6 +3,7 @@ return { // select content data subject: $('input[name=subject]').val(), date: $('input[name=date]').val(), + type_id: 1, // 1 = application document first_name: $('input[name=first_name]').val(), last_name: $('input[name=last_name]').val(), father_name: $('input[name=father_name]').val(), @@ -14,7 +15,7 @@ sector: selected_text($('select[name=sector]')), position: selected_text($('select[name=position]')), request: $('textarea[name=request]').val(), - now: Math.floor(Date.now() / 1000), + now: Math.floor(Date.now() / 1000), // client timestamp ticket: ref.ticket }; } @@ -28,30 +29,22 @@ $('.content-form form').submit( event => { event.preventDefault(); - if (false) { - alert('Τα δυο passrods δεν ταιριάζουν!'); + // select action url (add or update) + var request = '/petition/new'; - } else { + // send POST request + $.post(request, postObject()) + .done(function( data ) { + console.log(data); - var data = postObject(); + if (data.success) { // ok ? redirect to panel + window.location.href = '/panel'; - var form_data = { // prepare data to post - subject: $('input[name=of_department]').val(), - content: JSON.stringify(data), - on_date: $('input[name=date]').val(), - user_id: $('input[name=id]').val() + } else { // error ? alert! + alert(data.error); } - // select action url (add or update) - // var request = '/account/register'; - console.log(data); - - // send POST request - // $.post(request, form_data) - // .done(function( data ) { - // $('.classroom .content-form').html(data.message) - // }); - } + }); }); diff --git a/public/app/views/user/panel.php b/public/app/views/user/panel.php index 6888a7a..01a3777 100644 --- a/public/app/views/user/panel.php +++ b/public/app/views/user/panel.php @@ -23,13 +23,21 @@ <div class="col-xs-12 col-sm-3 info"> <?php // menu - //////////////////////////////////////////////////////////////////// - Render::view('components/menu'); + ////////////////////////////////////////////////////////////////// + Render::view('components/menu', ['is_admin' => $is_admin]); ?> </div> <div class="col-xs-12 col-sm-9"> + <?php // content sub-section + ////////////////////////////////////////////////////////////////// + Render::view('components/'.$content, [ + 'is_admin' => $is_admin, + 'user' => $user + ]); + ?> + <!-- content ** petitions datatable * change password -> link out (?) |
