summaryrefslogtreecommitdiff
path: root/public/app
diff options
context:
space:
mode:
Diffstat (limited to 'public/app')
-rw-r--r--public/app/controllers/admin/Course_admin.php267
-rw-r--r--public/app/controllers/cms/Course.php38
-rw-r--r--public/app/extends/Cache_service.php33
-rw-r--r--public/app/models/cms/Course_model.php22
-rw-r--r--public/app/routes/backend.php85
-rw-r--r--public/app/routes/frontend.php8
-rw-r--r--public/app/views/admin/admin-menu.php2
-rw-r--r--public/app/views/admin/edit_page.php139
-rw-r--r--public/app/views/admin/pages.php109
-rw-r--r--public/app/views/components/footer.php240
-rw-r--r--public/app/views/components/lessons_list.php49
-rw-r--r--public/app/views/error/general.php3
-rw-r--r--public/app/views/templates/course.php11
-rw-r--r--public/app/views/templates/lesson.php10
-rw-r--r--public/app/views/templates/page.php64
-rw-r--r--public/app/views/welcome.php11
16 files changed, 1006 insertions, 85 deletions
diff --git a/public/app/controllers/admin/Course_admin.php b/public/app/controllers/admin/Course_admin.php
index 72ddc79..f68ead2 100644
--- a/public/app/controllers/admin/Course_admin.php
+++ b/public/app/controllers/admin/Course_admin.php
@@ -168,11 +168,12 @@ class Course_admin {
);
if (isset($post['media'])) {
- // update media's privileges
+ // update media's privileges; NOTE: media table
self::update_medias_privileges($post['media'], $post['privilege_id']);
- // set lesson's media files
- self::create_medias_for_lesson($post['media'], $id, $post['privilege_id']);
+ // set lesson's media files; NOTE: lesson_media table
+ // ERROR: self::create_medias_for_lesson($post['media'], $id, $post['privilege_id']);
+ self::create_medias_for_lesson($post['media'], $id);
}
return true;
@@ -226,41 +227,13 @@ class Course_admin {
if (isset($post['media'])) {
// update lesson's media files
- self::create_medias_for_lesson($post['media'], $post['id'], $post['privilege_id']);
+ // ERROR: self::create_medias_for_lesson($post['media'], $post['id'], $post['privilege_id']);
+ self::create_medias_for_lesson($post['media'], $post['id']);
}
return true;
}
- /** update medias privileges
- *
- * @param $medias (array) : array of media id(s)
- * @param $privilege (int) : privilege id
- * @return true (always)
- */
- private static function update_medias_privileges($medias, $privilege)
- {
- // create WHERE IN (LIST) holders and params for prepare statement
- $params = [ ':privilege' => $privilege];
- $holders = [];
- foreach($medias as $key => $media) {
- $params[':id'.$key] = $media;
- $holders[] = ':id'.$key;
- }
- $list = '('. implode(',', $holders) .')';
-
- // print_r(['params' => $params, 'list' => $list]); die();
-
- Registry::use('database')->runQuery(
- "UPDATE media SET privilege_id = :privilege
- WHERE id IN {$list}",
- $params
- );
-
- return true;
- }
-
-
## -------------------------------------------------------------------------
##
@@ -271,6 +244,7 @@ class Course_admin {
/** files
* echo all files
+ *
* @return (array)
*/
public static function files()
@@ -434,11 +408,12 @@ class Course_admin {
}
- /** create media for post
+ /** create media for lesson
+ *
+ * links lesson to each media-file of the media `id`s array
*
- * links post to each media-file of the media `id`s array
* @param $media (array): a list of media-file `id`s
- * @param $post_id (int)
+ * @param $lesson_id (int)
*/
private static function create_medias_for_lesson($medias, $lesson_id)
{
@@ -449,6 +424,22 @@ class Course_admin {
}
+ /** create media for page
+ *
+ * links page to each media-file of the media `id`s array
+ *
+ * @param $media (array): a list of media-file `id`s
+ * @param $page_id (int)
+ */
+ private static function create_medias_for_page($medias, $page_id)
+ {
+ foreach($medias as $key => $medi) {
+ self::link_media_to_page($medi, $page_id); // link to page
+ }
+ return true;
+ }
+
+
/** link one media-file to a specific post
*
* NOTE:
@@ -471,5 +462,209 @@ class Course_admin {
return true;
}
+ /** link one media-file to a specific page
+ *
+ * NOTE:
+ * the method does not check if media is linked already
+ * so be sure that the pair of (media_id, page_id) not exist
+ *
+ * @param $media_id (int)
+ * @param $page_id (int)
+ */
+ private static function link_media_to_page( $media_id, $page_id )
+ {
+ Registry::use('database')->runQuery(
+ "INSERT INTO page_media (page_id, media_id)
+ VALUES (:page, :media)",
+ [
+ 'page' => $page_id,
+ 'media' => $media_id,
+ ]
+ );
+ return true;
+ }
+
+
+ /** update medias privileges
+ *
+ * UPDATE media SET privige WHERE IN {list}
+ *
+ * @param $medias (array) : array of media id(s)
+ * @param $privilege (int) : privilege id
+ * @return true (always)
+ */
+ private static function update_medias_privileges($medias, $privilege)
+ {
+ // create WHERE IN (LIST) holders and params for prepare statement
+ $params = [ ':privilege' => $privilege];
+ $holders = [];
+ foreach($medias as $key => $media) {
+ $params[':id'.$key] = $media;
+ $holders[] = ':id'.$key;
+ }
+ $list = '('. implode(',', $holders) .')';
+
+ // print_r(['params' => $params, 'list' => $list]); die();
+
+ Registry::use('database')->runQuery(
+ "UPDATE media SET privilege_id = :privilege
+ WHERE id IN {$list}",
+ $params
+ );
+
+ return true;
+ }
+
+
+
+
+
+
+ ## -------------------------------------------------------------------------
+ ##
+ ## PAGE METHODS
+ ##
+ ## -------------------------------------------------------------------------
+
+
+ /** all pages
+ *
+ */
+ public static function all_pages()
+ {
+ Render::json(Registry::use('database')->runQuery(
+ "SELECT * FROM page", []
+ ));
+ }
+
+
+ /** get_page
+ *
+ * @param $id (int) : page's id
+ */
+ public static function get_page($id)
+ {
+ // get (first) page with id = $id; render as json
+ Render::json(Registry::use('database')->query(
+ "SELECT page.*,
+ ( SELECT
+ CONCAT('[', GROUP_CONCAT(JSON_OBJECT(
+ 'id', media.id,
+ 'label', media.label,
+ 'type', media.type,
+ 'path', media.path )),
+ ']')
+ FROM media
+ LEFT JOIN page_media ON page_media.media_id = media.id
+ WHERE page_media.page_id = :id
+ ) AS medias_json
+ FROM page
+ WHERE page.id = :id",
+ [ ':id' => $id]
+ )->getFirst());
+ }
+
+
+ /** add_page
+ * insert a new page
+ *
+ * all parametres are passed via $_POST array
+ *
+ * POST @param title
+ * POST @param body
+ * POST @param status (int): 0 = draft , 1 = published
+ */
+ public static function add_page()
+ {
+ $post = Registry::get('REQUEST')->POST;
+
+ // insert page content into daabase
+ $id = Registry::use('database')->query(
+ "INSERT INTO page (title, `body`, `status`)
+ VALUES (:title, :body, :status)",
+ [
+ ':title' => $post['title'],
+ ':body' => $post['body'],
+ 'status' => $post['status']
+ ]
+ )->lastInsertID();
+
+
+ if (isset($post['media'])) {
+ // update media's privileges;
+ // NOTE: media table; pages have public files (privilege_id=0)
+ self::update_medias_privileges($post['media'], 0);
+
+ // set page's media files
+ // NOTE: page_media table
+ self::create_medias_for_page($post['media'], $id);
+ }
+
+ self::update_pages_cache(); // update pages cache
+
+ return true;
+ }
+
+
+ /** update_page
+ *
+ * POST @param id (int)
+ * POST @param title
+ * POST @param body
+ * POST @param status (int): 0 = draft , 1 = published
+ */
+ public static function update_page()
+ {
+ $post = Registry::get('REQUEST')->POST;
+
+ // print_r($post); die();
+
+ // update page's content
+ Registry::use('database')->query(
+ "UPDATE page
+ SET title = :title, `body` = :body, `status` = :status
+ WHERE id = :id",
+ [
+ ':id' => $post['id'],
+ ':title' => $post['title'],
+ ':body' => $post['body'],
+ ':status' => $post['status']
+ ]
+ );
+
+ if (isset($post['media'])) {
+ // update media's privileges
+ self::update_medias_privileges($post['media'], 0);
+ }
+
+ // remove all old page's links to media files
+ Registry::use('database')->runQuery(
+ "DELETE from page_media WHERE page_id = :page",
+ [ ':page' => $post['id'] ]
+ );
+
+ if (isset($post['media'])) {
+ // update page's media files
+ self::create_medias_for_page($post['media'], $post['id']);
+ }
+
+ self::update_pages_cache(); // update pages cache
+
+ return true;
+ }
+
+
+ /** update pages cache
+ * --- -- -- - - -
+ * Forces re-caching of pages tree
+ * Shall run if anything changes to courses
+ *
+ * @param void
+ * @return (array): ['tree' => ..., 'breadcrumbs' => ... ]
+ */
+ public static function update_pages_cache()
+ {
+ return Cache_service::pages_list(PROXY_IGNORE_CACHE);
+ }
} \ No newline at end of file
diff --git a/public/app/controllers/cms/Course.php b/public/app/controllers/cms/Course.php
index a1de9c1..c795ab9 100644
--- a/public/app/controllers/cms/Course.php
+++ b/public/app/controllers/cms/Course.php
@@ -131,7 +131,9 @@ class Course {
'categories' => $tree,
'breadcrumbs' => $breadcrumbs,
'lessons' => $lessons,
- 'course_path' => $course_path
+ 'course_path' => $course_path,
+ // needed by footer
+ 'entity' => Cache_service::pages_list()
]);
}
@@ -174,6 +176,12 @@ class Course {
}
$course_path[] = intval($course_id);
+ // NOTE: CRITICAL:
+ // do not pass Class::method directly to the eported variables
+ // $entity = Cache_service::pages_list();
+
+ // var_dump($entity); die();
+
// then Render
// --- -- -- - - -
Render::view('templates/lesson', [
@@ -185,7 +193,9 @@ class Course {
// needed for side panel and breadcrunbs
'categories' => $tree,
'breadcrumbs' => $breadcrumbs,
- 'course_path' => $course_path
+ 'course_path' => $course_path,
+ // needed by footer
+ 'entity' => Cache_service::pages_list()
]);
} else { // user is not authorized
@@ -202,7 +212,31 @@ class Course {
}
+ /** lesson
+ *
+ * check if user is authorized to view the content;
+ * if so, prepare and render the lesson view
+ *
+ * @param $id : lesson id
+ */
+ public static function page($id)
+ {
+ $id = intval($id); // lesson id
+
+ $pages = Cache_service::pages_list();
+ $page = $pages[$id];
+
+ // then Render
+ // --- -- -- - - -
+ Render::view('templates/page', [
+ // main content
+ 'id' => $id,
+ 'page' => $page,
+ // needed by footer
+ 'entity' => $pages
+ ]);
+ }
diff --git a/public/app/extends/Cache_service.php b/public/app/extends/Cache_service.php
index 9aac1d0..52311f3 100644
--- a/public/app/extends/Cache_service.php
+++ b/public/app/extends/Cache_service.php
@@ -45,5 +45,38 @@ class Cache_service
);
}
+ public static function pages_list( $options = 0 )
+ {
+ return proxy(
+ [\app\models\cms\Course_model::class, 'pages'],
+ [], CACHE_ROOT_TTL,
+ $options
+ );
+ }
+
+
+ /** entity
+ *
+ * create and retrieve a cached array of some entity
+ *
+ * @param $entiry (string|method): method of the main CMS model
+ * NOTE: CRITICAL: method must exist in the main CMS model
+ */
+ public static function entity( $entity, $options = 0 )
+ {
+ $allowed_methods = [ // to make sure method existence
+ 'page',
+ 'course',
+ 'lesson',
+ ];
+
+ // TODO: needs testing before release
+ // return proxy(
+ // [\app\models\admin\Course_model::class, $entity],
+ // [], CACHE_ROOT_TTL,
+ // $options
+ // );
+ }
+
} \ 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 54f49cf..6614993 100644
--- a/public/app/models/cms/Course_model.php
+++ b/public/app/models/cms/Course_model.php
@@ -288,5 +288,27 @@ class Course_model {
}
+ /** 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/routes/backend.php b/public/app/routes/backend.php
index ed02295..2bbd056 100644
--- a/public/app/routes/backend.php
+++ b/public/app/routes/backend.php
@@ -31,18 +31,6 @@ Route::add('/admin/panel', function () { // admin panel #2
});
-// admin lessons
-////////////////////////////////////////////////////////////////////////////////
-
-Route::add('/admin/lessons', function () { // request admin-lessons page
- Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles
- Render::view('admin/skeleton', [
- 'title' => 'Διαχείριση Μαθημάτων',
- 'action' => 'lessons',
- ]);
-});
-
-
// admin categories (=courses)
////////////////////////////////////////////////////////////////////////////////
@@ -55,8 +43,6 @@ Route::add('/admin/categories', function () { // manage categories page
]);
});
-
-
Route::add('/admin/api/categories', function () { // ajax: get all courses; with breadcrumbs
Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles
Course_admin::breadcrumbs();
@@ -99,11 +85,17 @@ Route::add('/admin/api/privileges', function () {
-// admin lesson
+// admin lessons
////////////////////////////////////////////////////////////////////////////////
+Route::add('/admin/lessons', function () { // request admin-lessons page
+ Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles
+ Render::view('admin/skeleton', [
+ 'title' => 'Διαχείριση Μαθημάτων',
+ 'action' => 'lessons',
+ ]);
+});
-// ---
Route::add('/admin/edit_lesson', function () { // new lesson form
Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles
Render::view('admin/skeleton', [
@@ -130,13 +122,13 @@ Route::add('/admin/api/lesson/([0-9]*)', function ($id) { // ajax: get les
Route::add('/admin/api/lesson/add', function () { // ajax: add lesson
Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles
- Course_admin::add_lesson();
+ Render::json(['success' => Course_admin::add_lesson()]);
}, 'post');
Route::add('/admin/api/lesson/update', function () { // ajax: update lesson
Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles
- Course_admin::update_lesson();
+ Render::json(['success' => Course_admin::update_lesson()]);
}, 'post');
@@ -146,6 +138,7 @@ Route::add('/admin/api/lessons', function () { // ajax: get all lessons
});
+
// admin files
////////////////////////////////////////////////////////////////////////////////
@@ -170,3 +163,59 @@ Route::add('/admin/api/file_upload', function () {
Render::json(Course_admin::upload_file());
}, 'post');
+
+
+
+// admin page
+////////////////////////////////////////////////////////////////////////////////
+
+Route::add('/admin/pages', function () { // request admin-lessons page
+ Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles
+ Render::view('admin/skeleton', [
+ 'title' => 'Διαχείριση Σελίδων',
+ 'action' => 'pages',
+ ]);
+});
+
+
+Route::add('/admin/edit_page', function () { // new page form
+ Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles
+ Render::view('admin/skeleton', [
+ 'title' => 'Νέα Σελίδα',
+ 'action' => 'edit_page',
+ ]);
+});
+
+Route::add('/admin/edit_page/([0-9]*)', function ($id) { // edit page form
+ Auth::allowRoles([1, 2, 3]);
+ Render::view('admin/skeleton', [
+ 'title' => 'Επεξεργασία Σελίδας',
+ 'action' => 'edit_page',
+ 'id' => intval($id)
+ ]);
+});
+
+
+Route::add('/admin/api/page/([0-9]*)', function ($id) { // ajax: get page
+ Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles
+ Course_admin::get_page($id);
+});
+
+
+Route::add('/admin/api/page/add', function () { // ajax: add page
+ Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles
+ Render::json(['success' => Course_admin::add_page()]);
+}, 'post');
+
+
+Route::add('/admin/api/page/update', function () { // ajax: update page
+ Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles
+ Render::json(['success' => Course_admin::update_page()]);
+}, 'post');
+
+
+Route::add('/admin/api/pages', function () { // ajax: get all pages
+ Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles
+ Course_admin::all_pages();
+});
+
diff --git a/public/app/routes/frontend.php b/public/app/routes/frontend.php
index 33fe401..601641f 100644
--- a/public/app/routes/frontend.php
+++ b/public/app/routes/frontend.php
@@ -12,7 +12,8 @@ use app\extends\Cache_service;
Route::add('/', function() {
Render::view('welcome', [
- 'categories' => Cache_service::courses_struct()['tree']
+ 'categories' => Cache_service::courses_struct()['tree'],
+ 'entity' => Cache_service::pages_list()
]);
// need redirect?... header('Location: /some/default/url', true, 302);
});
@@ -40,6 +41,11 @@ Route::add('/lesson/([0-9]*)', // request lesson by lesson-id
function($id) { Course::lesson($id); }
);
+Route::add('/page/([0-9]*)', // request lesson by lesson-id
+ function($id) { Course::page($id); }
+);
+
+
Route::add('/serve/file/([0-9a-zA-Z-_\.\/]*)', // serve file by path
function ($path) { Course::serve_file($path); } // (also ?type= is sent)
);
diff --git a/public/app/views/admin/admin-menu.php b/public/app/views/admin/admin-menu.php
index b783b39..52e8522 100644
--- a/public/app/views/admin/admin-menu.php
+++ b/public/app/views/admin/admin-menu.php
@@ -21,7 +21,7 @@ $admin_options = [
'edit_lesson' => 'Νέο Μάθημα',
'lessons' => 'Μαθήματα',
'categories' => 'Κεφάλαια',
- // 'pages' => 'Σελίδες',
+ 'pages' => 'Σελίδες',
'files' => 'Αρχεία',
'privileges' => 'Πρόσβαση',
'users' => 'Χρήστες'
diff --git a/public/app/views/admin/edit_page.php b/public/app/views/admin/edit_page.php
new file mode 100644
index 0000000..46c47bc
--- /dev/null
+++ b/public/app/views/admin/edit_page.php
@@ -0,0 +1,139 @@
+<?php
+ // some labels (if editing new or existing record)
+ // --- -- -- - - -
+ if ($id == 0) {
+ $action_title = "Δημιουργία Σελίδας";
+ $action_button = "Δημιουργία";
+
+ } else {
+ $action_title = "Επεξεργασία Σελίδας";
+ $action_button = "Αποθήκευση Αλλαγών";
+ }
+?>
+
+<!-- title bar -->
+<div class="title-bar">
+ <div><h5><?=$action_title?></h5></div>
+ <div>
+ <button type="button" class="btn pull-right"
+ data-bs-toggle="modal" data-bs-target="#editorModal" data-action="preview">
+ <i class="fas fa-search"></i> &nbsp; Προεπισκόπηση
+ </button>
+ </div>
+</div>
+
+<!-- manage -->
+<div class="manage edit-page">
+ <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>
+
+ <!-- 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="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-bs-toggle="modal" data-bs-target="#editorModal" data-action="upload_file">
+ <i class="fas fa-plus"></i> &nbsp; Προσθήκη
+ </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">
+ <?=$action_button?>
+ </button>
+ </div>
+
+ </div>
+
+ </div>
+
+ </form>
+
+ </div>
+</div><!-- /manage -->
+
+
+<!-- MODAL for file uploads and preview -->
+<div class="modal fade" id="editorModal" aria-labelledby="myModalLabel" aria-hidden="true">
+ <div class="modal-dialog modal-lg" role="document">
+ <div class="modal-content">
+ <!-- content will be dynamic -->
+ </div>
+ </div>
+</div>
+
diff --git a/public/app/views/admin/pages.php b/public/app/views/admin/pages.php
new file mode 100644
index 0000000..dd8f954
--- /dev/null
+++ b/public/app/views/admin/pages.php
@@ -0,0 +1,109 @@
+ <!-- title bar -->
+ <div class="title-bar">
+ <div><h5>Διαχείριση Μαθημάτων</h5></div>
+ <div>
+ <!-- Button trigger modal -->
+ <a type="button" class="btn pull-right" href="/admin/edit_page">
+ <i class="fas fa-plus"></i> &nbsp; Νέα Σελίδα
+ </a>
+ </div>
+</div>
+
+<div class="manage">
+ <div class="row">
+ <div class="col-md-12">
+
+ <div id="pages">
+
+ <table id="dt-pages" class="table table-responsive dt-table" style="width:100%">
+ <thead>
+ <th class="dt-id">α/α</th>
+ <th class="dt-title">Τίτλος</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="managePages" 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">Παράμετροι Μαθήματος</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="title" value="" required="">
+ </div>
+ </div>
+
+
+ <!-- one line / two parts; status: pull right -->
+ <div class="row">
+ <div class="col-md-8">
+ &nbsp<!-- nothing -->
+ </div>
+ <div class="col-md-4">
+
+ <!-- status: published|unpublished -->
+ <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>
+ </div>
+
+
+
+
+ <div class="row form-group">
+ <input type="hidden" name="id" value="0"><!-- page-id -->
+ </div>
+
+
+ </div><!-- /modal body -->
+
+ <div class="modal-footer">
+ <div class="row" style="width: 50%;">
+ <div class="form-actions">
+ <div class="col-4">
+ <button type="button" class="btn btn-default js-modal-close col-sm-12" data-bs-dismiss="modal">Κλείσιμο</button>
+ </div>
+ <div class="col-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/components/footer.php b/public/app/views/components/footer.php
new file mode 100644
index 0000000..7cd4a5a
--- /dev/null
+++ b/public/app/views/components/footer.php
@@ -0,0 +1,240 @@
+<?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/lessons_list.php b/public/app/views/components/lessons_list.php
index 46c1f7e..a778d59 100644
--- a/public/app/views/components/lessons_list.php
+++ b/public/app/views/components/lessons_list.php
@@ -16,40 +16,39 @@
* -----------------------------------------------------------------------------
*/
?>
-<div class="row">
- <?php foreach($lessons as $post) : ?>
- <!-- <div class="col-xl-4 col-lg-6"> -->
- <div class="post-card">
+<?php foreach($lessons as $post) : ?>
- <?php if (in_array('date', $fieldset)) : ?>
- <?=$post['date']?>
- <?php endif; ?>
+ <!-- <div class="col-xl-4 col-lg-6"> -->
+ <div class="post-card">
- <div class="post-card--content">
+ <?php if (in_array('date', $fieldset)) : ?>
+ <?=$post['date']?>
+ <?php endif; ?>
- <h3>
- <a href="/lesson/<?=$post['id']?>"><?=$post['title']?></a>
- </h3>
+ <div class="post-card--content">
- <?php if (in_array('level', $fieldset)) : ?>
- <p class="getegory">(επίπεδο πρόσβασης <?=$post['privilege_id']?>)</p>
- <?php endif; ?>
+ <h3>
+ <a href="/lesson/<?=$post['id']?>"><?=$post['title']?></a>
+ </h3>
- <?php if (in_array('category', $fieldset)) : ?>
- <p class="category"><?=$post['course_id']?></p>
- <?php endif; ?>
+ <?php if (in_array('level', $fieldset)) : ?>
+ <p class="getegory">(επίπεδο πρόσβασης <?=$post['privilege_id']?>)</p>
+ <?php endif; ?>
- <?php if (in_array('intro', $fieldset) && $post['intro']) : ?>
- <p class="intro"><?=$post['intro']?></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>
- <!-- </div> -->
+ </div>
+ <!-- </div> -->
- <?php endforeach; ?>
+<?php endforeach; ?>
-</div> \ No newline at end of file
diff --git a/public/app/views/error/general.php b/public/app/views/error/general.php
index 0a27e56..6ed984b 100644
--- a/public/app/views/error/general.php
+++ b/public/app/views/error/general.php
@@ -55,8 +55,7 @@
<div class='container'>
<div class='content'>
<h3><?= isset($title) ? $title : PAGE_404_TITLE ?></h3>
- Oops!<br />
- —
+ <br />
<br />
<span><?= $message ?? "" ?></span>
</div>
diff --git a/public/app/views/templates/course.php b/public/app/views/templates/course.php
index 39e177f..1d212b8 100644
--- a/public/app/views/templates/course.php
+++ b/public/app/views/templates/course.php
@@ -76,6 +76,17 @@
</div>
</div>
+ <footer>
+ <div class="container">
+
+ <?php // render footer
+ ////////////////////////////////////////////////////////////////
+ Render::view('components/footer', [ 'entity' => $entity ]);
+ ?>
+
+ </div>
+ </footer>
+
<script src="/assets/js/classroom.js"></script>
</body>
diff --git a/public/app/views/templates/lesson.php b/public/app/views/templates/lesson.php
index 3baafd0..0867cd3 100644
--- a/public/app/views/templates/lesson.php
+++ b/public/app/views/templates/lesson.php
@@ -65,6 +65,16 @@
</div>
</div>
+ <footer>
+ <div class="container">
+
+ <?php // render footer
+ ////////////////////////////////////////////////////////////////
+ Render::view('components/footer', [ 'entity' => $entity ]);
+ ?>
+
+ </div>
+ </footer>
<script src="/assets/js/classroom.js"></script>
<script src="/assets/js/lesson-features.js"></script>
diff --git a/public/app/views/templates/page.php b/public/app/views/templates/page.php
new file mode 100644
index 0000000..6afe45e
--- /dev/null
+++ b/public/app/views/templates/page.php
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title><?=SITE_TITLE?> - <?=$page['title']?></title>
+
+ <?php // header includes
+ ////////////////////////////////////////////////////////////////////////
+ Render::view('components/header_includes');
+ ?>
+
+</head>
+<body class="classroom">
+
+ <?php // top-bar
+ ////////////////////////////////////////////////////////////////////////
+ Render::view('components/top_bar', [
+ 'id' => 0,
+ 'label' => '',
+ 'parents' => []
+ ]);
+ ?>
+
+
+ <div class="main-content container page-container">
+
+
+ <div class="lesson-view">
+
+ <!-- page Title -->
+ <h3>
+ <?=$page['title']?>
+ </h3>
+
+ <!-- page body -->
+ <div class="article-body">
+ <?php
+
+ $parsedown = new Parsedown();
+ echo $parsedown->text($page['body']);
+
+ ?>
+ </div>
+
+
+ </div>
+
+ </div>
+
+ <footer>
+ <div class="container">
+
+ <?php // render footer
+ ////////////////////////////////////////////////////////////////
+ Render::view('components/footer', [ 'entity' => $entity ]);
+ ?>
+
+ </div>
+ </footer>
+
+ <script src="/assets/js/classroom.js"></script>
+ <script src="/assets/js/lesson-features.js"></script>
+</body>
+</html>
diff --git a/public/app/views/welcome.php b/public/app/views/welcome.php
index 08be0a2..c5552a8 100644
--- a/public/app/views/welcome.php
+++ b/public/app/views/welcome.php
@@ -54,6 +54,17 @@
--- */ ?>
+ <footer>
+ <div class="container">
+
+ <?php // render footer
+ ////////////////////////////////////////////////////////////////
+ Render::view('components/footer', [ 'entity' => $entity ]);
+ ?>
+
+ </div>
+ </footer>
+
<script src="/assets/js/classroom.js"></script>
</body>