diff --git a/db/rest/post/api_post.sql b/db/rest/post/api_post.sql index a91d9d2..b49289c 100644 --- a/db/rest/post/api_post.sql +++ b/db/rest/post/api_post.sql @@ -5,7 +5,8 @@ CREATE VIEW api.post AS p.content, p.date FROM - admin.post p; + admin.post p + ORDER BY id DESC; GRANT SELECT ON TABLE api.post TO rest_anon, rest_user; diff --git a/db/rest/post/api_post_insert.sql b/db/rest/post/api_post_insert.sql index 9eb200c..02b9d8d 100644 --- a/db/rest/post/api_post_insert.sql +++ b/db/rest/post/api_post_insert.sql @@ -32,6 +32,8 @@ GRANT INSERT ON TABLE api.post TO rest_user; GRANT INSERT ON TABLE admin.post TO rest_user; +GRANT UPDATE ON TABLE sys.post_id_seq + TO rest_user; CREATE TRIGGER api_post_insert_trgr INSTEAD OF INSERT diff --git a/db/rest/util/_api_validate_text.sql b/db/rest/util/_api_validate_text.sql index 2a3764c..e4a6a7b 100644 --- a/db/rest/util/_api_validate_text.sql +++ b/db/rest/util/_api_validate_text.sql @@ -29,7 +29,7 @@ BEGIN IF _min IS NOT NULL AND _length < _min THEN PERFORM _api.raise( - _msg => 'api_text_min', + _msg => 'api_min_value', _detail => _column, _hint => _min || '' ); @@ -37,7 +37,7 @@ BEGIN IF _max IS NOT NULL AND _length > _max THEN PERFORM _api.raise( - _msg => 'api_text_max', + _msg => 'api_max_value', _detail => _column, _hint => _max || '' ); diff --git a/web/_controller/_index.php b/web/_controller/_index.php new file mode 100644 index 0000000..fdf9440 --- /dev/null +++ b/web/_controller/_index.php @@ -0,0 +1,23 @@ +main->session) { + $this->redirect('/home'); + } else { + $this->redirect('/login'); + } + } + +} + +?> diff --git a/web/_controller/apps/error.php b/web/_controller/apps/error.php new file mode 100644 index 0000000..5ce9ec4 --- /dev/null +++ b/web/_controller/apps/error.php @@ -0,0 +1,20 @@ +error_model = $this->load->model('apps/error'); + } + + public function index() { + parent::index(); + $data = $this->error_model->get_data(); + $this->view('header', $data); + $this->view('apps/error/main', $data); + } + +} + +?> diff --git a/web/routes/home/controller.php b/web/_controller/apps/home.php similarity index 56% rename from web/routes/home/controller.php rename to web/_controller/apps/home.php index 775e43a..25c8c4e 100644 --- a/web/routes/home/controller.php +++ b/web/_controller/apps/home.php @@ -1,22 +1,31 @@ model = $model; + // the request model + private $request_model; + + // the caceh model + private $cache_model; + + function __construct($load) { + parent::__construct($load); + $this->home_model = $this->load->model('apps/home'); + $this->request_model = $this->load->model('request'); + $this->cache_model = $this->load->model('cache'); } - public function index() { + public function index(): void { parent::index(); - $data = $this->model->get_data(); + $data = $this->home_model->get_data(); $this->view('header', $data); - $this->app_view('main', $data); + $this->view('apps/home/main', $data); } - public function posts() { - $page = $this->main->get_num('page', 0); + public function posts(): void { + $page = $this->request_model->get_int('page', 0); $page_size = 20; $offset = $page * $page_size; @@ -30,7 +39,7 @@ class HomeController extends Controller { $query = $query->select('p.*, FALSE as liked'); } - $query = $query->from('admin.post p'); + $query = $query->from('api.post p'); if ($user) { $query = $query->join('admin.like l', 'p.id = l.post_id') @@ -42,7 +51,7 @@ class HomeController extends Controller { ->offset($offset) ->rows(); - $users = $this->main->get_users($posts); + $users = $this->cache_model->get_users($posts); foreach ($posts as $post) { $data = array(); @@ -52,9 +61,9 @@ class HomeController extends Controller { } } - public function comments() { - $page = $this->main->get_num('page', 0); - $id = $this->main->get_num('id'); + public function comments(): void { + $page = $this->request_model->get_int('page', 0); + $id = $this->request_model->get_int('id'); $page_size = 20; $offset = $page * $page_size; @@ -65,7 +74,7 @@ class HomeController extends Controller { ->offset($offset) ->rows(); - $users = $this->main->get_users($comments); + $users = $this->cache_model->get_users($comments); foreach ($comments as $comment) { $data = array(); @@ -75,10 +84,6 @@ class HomeController extends Controller { } } - public function new_post_modal() { - $this->modal(lang('new_post_modal_title'), 'new-post'); - } - } ?> diff --git a/web/_controller/modal.php b/web/_controller/modal.php new file mode 100644 index 0000000..9ae4ca8 --- /dev/null +++ b/web/_controller/modal.php @@ -0,0 +1,26 @@ +view('template/modal', $data); + } + + public function new_post(): void { + $this->modal('new_post'); + } +} + +?> + diff --git a/web/_controller/template.php b/web/_controller/template.php new file mode 100644 index 0000000..7a8cdf8 --- /dev/null +++ b/web/_controller/template.php @@ -0,0 +1,22 @@ +request_model = $this->load->model('request'); + } + + public function toast(): void { + $data = array( + 'msg' => $this->request_model->get_str('msg', FALSE), + 'detail' => $this->request_model->get_str('detail', FALSE), + 'hint' => $this->request_model->get_str('hint', FALSE) + ); + $this->view('template/toast', $data); + } + +} + diff --git a/web/routes/error/model.php b/web/_model/apps/error.php similarity index 80% rename from web/routes/error/model.php rename to web/_model/apps/error.php index a30fccc..ad72b28 100644 --- a/web/routes/error/model.php +++ b/web/_model/apps/error.php @@ -1,5 +1,9 @@ get_msg($data); return $data; diff --git a/web/routes/home/model.php b/web/_model/apps/home.php similarity index 60% rename from web/routes/home/model.php rename to web/_model/apps/home.php index 44a8549..82fbf26 100644 --- a/web/routes/home/model.php +++ b/web/_model/apps/home.php @@ -1,7 +1,11 @@ db ->select('*') ->from('admin.post') @@ -9,11 +13,10 @@ class HomeModel extends Model { ->rows(); } - public function get_data() { + public function get_data(): array { $data = parent::get_data(); $data['title'] = lang('title'); $data['posts'] = $this->get_posts(); return $data; } } -?> diff --git a/web/_model/cache.php b/web/_model/cache.php new file mode 100644 index 0000000..6cf9924 --- /dev/null +++ b/web/_model/cache.php @@ -0,0 +1,37 @@ +users = array(); + } + + /** + * Gets a array of users + */ + public function get_users($objs) { + $ids = array(); + foreach ($objs as $obj) { + $id = $obj['user_id']; + if (!array_key_exists($id, $this->users)) { + array_push($ids, intval($id)); + } + } + if (!empty($ids)) { + $result = $this->main->db + ->select('*') + ->from('api.user') + ->where_in('id', $ids) + ->rows(); + foreach ($result as $user) { + $id = $user['id']; + $this->users[$id] = $user; + } + } + return $this->users; + } + +} diff --git a/web/_model/format.php b/web/_model/format.php new file mode 100644 index 0000000..d8c7480 --- /dev/null +++ b/web/_model/format.php @@ -0,0 +1,45 @@ +db = new DatabaseHelper(); + /// load the current session + if (array_key_exists('jwt', $_SESSION)) { + $this->get_session($_SESSION['jwt']); + } else { + $this->session = NULL; + }; + /// init other vars + $this->users = array(); + } + + /** + * Loads current session + * @param string $jwt - the user provided JWT + */ + private function get_session($jwt) { + $query = $this->db + ->select("_api.verify_jwt('" . $jwt . "') AS user_id;"); + $result = $query->row(); + $user_id = $result['user_id']; + if ($user_id) { + $this->session = array( + 'id' => $user_id, + 'jwt' => $jwt + ); + } + } + + /** + * Loads a css html link + * @param string $path - the path to the css file + */ + public function link_css($path) { + return ''; + } + + /** + * Loads a js html link + * @param string $path - the path to the js file + */ + public function link_js($path) { + return ''; + } + + /** + * Gets the current user + */ + public function user() { + if ($this->session) { + return $this->db + ->select('*') + ->from('api.user') + ->where('id') + ->eq($this->session['id']) + ->row(); + } else { + return NULL; + } + } + +} + +?> diff --git a/web/_model/request.php b/web/_model/request.php new file mode 100644 index 0000000..4cce07a --- /dev/null +++ b/web/_model/request.php @@ -0,0 +1,40 @@ + [ 'js/jquery-3.7.1.min.js', 'js/lib.js', - 'js/modal.js', + 'js/shared/modal.js', ], 'css' => [ 'css/common.css' @@ -22,7 +22,8 @@ class Aesthetic { ), 'home' => array( 'js' => [ - 'js/post.js', + 'js/shared/post.js', + 'js/routes/home.js', ], 'css' => [ 'css/home.css', diff --git a/web/config/routes.php b/web/config/routes.php new file mode 100644 index 0000000..78df332 --- /dev/null +++ b/web/config/routes.php @@ -0,0 +1,7 @@ +load = $load; + $this->main = $this->load->model('main'); + $this->db = $this->main->db; + + $info = $this->main->info; + $lang = $info['lang']; + $this->load->lang($lang); + $app = $info['app']; + if ($app) { + $this->load->app_lang($lang, $app); + } + } + + public function index() {} + + public function redirect($link) { + header('Location: '. $link, true, 301); + die(); + } + + protected function view($__name, $data = array()) { + $__root = $GLOBALS['webroot']; + $__path = $__root . '/views/' . $__name . '.php'; + if (is_file($__path)) { + extract($data); + require($__path); + return; + } + } + +} +?> diff --git a/web/core/_model.php b/web/core/_model.php new file mode 100644 index 0000000..936fab4 --- /dev/null +++ b/web/core/_model.php @@ -0,0 +1,44 @@ +load = $load; + $this->main = $this->load->model('main'); + $this->db = $this->main->db; + $this->config = new Aesthetic(); + } + + /** + * @returns the base model data + */ + public function get_data(): array { + $data = array(); + $data['self'] = $this->main->user(); + + $info = $this->main->info; + $app = $info['app']; + + if ($app) { + $files = $this->config->get_files($app); + $data = array_merge($data, $files); + } else { + $files = $this->config->get_files(); + $data = array_merge($data, $files); + } + + return $data; + } +} diff --git a/web/core/controller.php b/web/core/controller.php deleted file mode 100644 index 946b460..0000000 --- a/web/core/controller.php +++ /dev/null @@ -1,55 +0,0 @@ -main = $GLOBALS['__vars']['main']; - $this->load = $GLOBALS['__vars']['load']; - $this->db = $this->main->db; - - $info = $this->main->info; - $lang_code = $info['lang']; - $route_name = $info['route']; - $this->load->lang($lang_code); - $this->load->route_lang($lang_code, $route_name); - } - - public function index() {} - - protected function view($__name, $data = array()) { - $__root = $GLOBALS['webroot']; - $__path = $__root . '/views/' . $__name . '.php'; - if (is_file($__path)) { - extract($data); - require($__path); - return; - } - } - - protected function app_view($__name, $data = array()) { - $__root = $GLOBALS['webroot']; - $__route = $this->main->info['route']; - $__path = $__root . '/routes/' . $__route . '/views/' . $__name . '.php'; - if (is_file($__path)) { - extract($data); - require($__path); - return; - } - } - - protected function modal($title, $content, $data = array()) { - $data['title'] = $title; - $data['content'] = $content; - $this->view('template/modal', $data); - } - -} -?> diff --git a/web/core/database.php b/web/core/database.php index b3a597b..4b44e86 100644 --- a/web/core/database.php +++ b/web/core/database.php @@ -170,4 +170,3 @@ class DatabaseHelper { } } -?> diff --git a/web/core/loader.php b/web/core/loader.php index 4d4526c..2091533 100644 --- a/web/core/loader.php +++ b/web/core/loader.php @@ -1,16 +1,79 @@ loaded = array(); + } + + /** + * Loads a $type of object from a $dir with a given $name + * @param string $name - the name of the object to load + * @param string $dir - the directory theese objects are stored in + * @param string $type - the type of the object + */ + private function load_type($name, $dir, $type): object|NULL { + $path = $dir . '/' . $name . '.php'; + if (array_key_exists($path, $this->loaded)) { + return $this->loaded[$path]; + } + + if (!file_exists($path)) { + return NULL; + } + + $parts = explode('/', $name); + $part = end($parts); + $class = ucfirst($part) . '_' . $type; + require($path); + + $ref = NULL; + try { + $ref = new ReflectionClass($class); + } catch (Exception $_e) {} + + if ($ref === NULL) { + return NULL; + } + + $obj = $ref->newInstance($this); + $this->loaded[$path] = $obj; + + return $obj; + } + + /** + * Loads a model + * @param string $name - the name of the model to load + */ + public function model($name): object|NULL { + $root = $GLOBALS['webroot']; + $dir = $root . '/_model'; + return $this->load_type($name, $dir, 'model'); + } + + /** + * Loads a controller + * @param string $name - the name of the controller to load + */ + public function controller($name): Controller|NULL { + $root = $GLOBALS['webroot']; + $dir = $root . '/_controller'; + return $this->load_type($name, $dir, 'controller'); + } + /** * Loads the given common lang - * @param lang_code - the language code + * @param string $lang_code 0 the language code */ - public function lang($lang_code) { + public function lang($lang_code): void { $dir = $GLOBALS['webroot'] . '/lang/' . $lang_code . '/'; $lang = $GLOBALS['lang']; if ($handle = opendir($dir)) { while (false !== ($entry = readdir($handle))) { - if ($entry === '.' || $entry === '..' || $entry === 'routes') { + if ($entry === '.' || $entry === '..' || $entry === 'apps') { continue; } $path = $dir . $entry; @@ -21,12 +84,12 @@ class Loader { } /** - * Loads a given route specific lang - * @param lang_coed - the language code - * #param name - the name of the route + * Loads a given app specific lang + * @param string $lang_code - the language code + * @param string $name - the name of the app */ - public function route_lang($lang_code, $name) { - $dir = $GLOBALS['webroot'] . '/lang/' . $lang_code . '/routes/'; + public function app_lang($lang_code, $name): void { + $dir = $GLOBALS['webroot'] . '/lang/' . $lang_code . '/apps/'; $file = $dir . $name . '.php'; if (file_exists($file)) { $lang = $GLOBALS['lang']; diff --git a/web/core/main.php b/web/core/main.php deleted file mode 100644 index c3c65dd..0000000 --- a/web/core/main.php +++ /dev/null @@ -1,123 +0,0 @@ -info = NULL; - $this->db = new DatabaseHelper(); - $this->users = array(); - $_SESSION['jwt'] = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicmVzdF91c2VyIiwidXNlcl9pZCI6MSwiZXhwIjoxNzExODUxMDUzfQ.FUcFO44SWV--YtVOy7NftTF8OeeOYGZDaDHigygQxsY'; - if (array_key_exists('jwt', $_SESSION)) { - $this->get_session($_SESSION['jwt']); - } else { - $this->user_id = NULL; - }; - } - - private function get_session($jwt) { - $query = $this->db - ->select("_api.verify_jwt('" . $jwt . "') AS user_id;"); - $result = $query->row(); - $user_id = $result['user_id']; - if ($user_id) { - $this->user_id = $user_id; - } - } - - public function link_css($path) { - return ''; - } - - public function link_js($path) { - return ''; - } - - public function user() { - if ($this->user_id) { - return $this->db - ->select('*') - ->from('api.user') - ->where('id') - ->eq($this->user_id) - ->row(); - } else { - return NULL; - } - } - - public function get_num($key, $default = NULL) { - if (!array_key_exists($key, $_GET)) { - if ($default !== NULL) { - return $default; - } else { - error_page(400, lang('error_400')); - } - } else { - $val = $_GET[$key]; - $val = intval($val); - if ($val < 0) { - return 0; - } else { - return $val; - } - } - } - - public function get_users($objs) { - $ids = array(); - foreach ($objs as $obj) { - $id = $obj['user_id']; - if (!array_key_exists($id, $this->users)) { - array_push($ids, intval($id)); - } - } - if (!empty($ids)) { - $result = $this->db - ->select('*') - ->from('api.user') - ->where_in('id', $ids) - ->rows(); - foreach ($result as $user) { - $id = $user['id']; - $this->users[$id] = $user; - } - } - return $this->users; - } - - public function display_name($user) { - $name = ''; - if ($user['first_name']) { - $name .= $user['first_name']; - } - if ($user['middle_name']) { - if ($name != '') { - $name .= ' '; - } - $name .= $user['middle_name']; - } - if ($user['last_name']) { - if ($name != '') { - $name .= ' '; - } - $name .= $user['last_name']; - } - if ($name == '') { - $name = '@' . $user['username']; - } - return $name; - } - - public function display_date($date) { - return $date; - } - -} - -?> diff --git a/web/core/model.php b/web/core/model.php deleted file mode 100644 index 039b138..0000000 --- a/web/core/model.php +++ /dev/null @@ -1,29 +0,0 @@ -main = $GLOBALS['__vars']['main']; - $this->load = $GLOBALS['__vars']['load']; - $this->db = $this->main->db; - $this->config = new Aesthetic(); - } - - public function get_data() { - $data = array(); - $route = $this->main->info['route']; - $files = $this->config->get_files($route); - $data = array_merge($data, $files); - $data['self'] = $this->main->user(); - return $data; - } -} -?> diff --git a/web/core/router.php b/web/core/router.php index 6ee28a9..72c7674 100644 --- a/web/core/router.php +++ b/web/core/router.php @@ -1,127 +1,147 @@ newInstance(); - - $controller_ref = new ReflectionClass($controller_cls); - $controller = $controller_ref->newInstance($model); - - return $controller; - } - - function __construct($main, $load) { - - $routes = array( - 'home' => array( - 'slugs' => ['', 'home'], - 'model' => 'HomeModel', - 'controller' => 'HomeController', - ), - ); - - $this->routes = array(); - foreach ($routes as $name => $route) { - foreach ($route['slugs'] as $slug) { - $this->routes[$slug] = $route; - $this->routes[$slug]['name'] = $name; - } - } - - $this->main = $main; + /** + * Creates a router + * @param Loader $load - the main laoder object + */ + function __construct($load) { $this->load = $load; + $this->main = $this->load->model('main'); } - function get_info() { - $uri = parse_url($_SERVER['REQUEST_URI']); + /** + * @param string $path - the current request path + * Gets the current route + * @return array + */ + private function get_req_route($path): array { + // trim the path + $path = trim($path); + // remove first '/' + $path = substr($path, 1); + // get path parts + $parts = explode('/', $path); + + $len = count($parts); + + // get route info + $route = array(); + // e.g. / + if ($path === '') { + $route = array( + 'route' => '', + 'slug' => 'index', + ); + // e.g. /home /login + } else if ($len === 1) { + $route = array( + 'route' => $parts[0], + 'slug' => 'index', + ); + // e.g. /home/posts + } else { + $route = array ( + 'route' => implode('/', array_slice($parts, 0, -1)), + 'slug' => end($parts) + ); + }; + + $route['app'] = $route['route']; + $routes = $GLOBALS['routes']; + if (array_key_exists($route['route'], $routes)) { + $route['route'] = $routes[$route['route']]; + } + + return $route; + } + + /** + * Gets the curret request info + * @return array + */ + private function get_req(): array { $method = $_SERVER['REQUEST_METHOD']; - $parts = explode('/', $uri['path']); - $slug = sizeof($parts) > 1 ? $parts[1] : ''; - $path = sizeof($parts) > 2 ? $parts[2] : 'index'; + $uri = parse_url($_SERVER['REQUEST_URI']); + $path = $uri['path']; - if (sizeof($parts) > 3) { - return NULL; - } - - return array( - 'method' => $method, - 'uri' => $uri, - - 'slug' => $slug, - 'path' => $path + return array_merge( + array( + 'uri' => $uri, + 'method' => $method, + 'lang' => $this->get_lang(), + ), + $this->get_req_route($path), ); } - function handle_error($code) { - $route = array( - 'name' => 'error', - 'model' => 'ErrorModel', - 'controller' => 'ErrorController' - ); - $this->main->info = array( - 'slug' => 'error', - 'lang' => 'en_US', - 'route' => 'error' - ); - $controller = $this->load_route($route); + /** + * Gets the current language + * @return string + */ + private function get_lang(): string { + return 'en_US'; + } + + /** + * Handles a router error code + * @param int $code - the http error code + * @param bool $recursed + */ + private function handle_error($code, $recursed): void { + if ($recursed) { + die($code . ' (recursed)'); + } + + $this->main->info['slug'] = 'index'; + $this->main->info['app'] = 'error'; + $this->main->info['route'] = 'apps/error'; + $req = $this->main->info; $_GET['code'] = $code; - http_response_code($code); - $controller->index(); + + $this->handle_req($req, TRUE); } - public function handle_request() { - $request = $this->get_info(); + /** + * @param array $req + * @param bool $recursed + */ + private function handle_req($req, $recursed = FALSE): void { + $controller = $this->load->controller($req['route']); - if ($request === NULL) { - $this->handle_error(404); + if ($controller === NULL) { + $this->handle_error(404, $recursed); return; } - $slug = $request['slug']; - if (!array_key_exists($slug, $this->routes)) { - $this->handle_error(404); - return; - } - - $route = $this->routes[$slug]; - $this->main->info = array( - 'lang' => 'en_US', - 'slug' => $slug, - 'route' => $route['name'], - ); - - $controller = $this->load_route($route); - - $path = $request['path']; $ref = NULL; - try { - $ref = new ReflectionMethod($controller, $path); + $ref = new ReflectionMethod($controller, $req['slug']); } catch (Exception $_e) {} if ($ref === NULL || !$ref->isPublic()) { - $this->handle_error(404); + $this->handle_error(404, $recursed); return; } $ref->invoke($controller); + } + /** + * Handels the incomming reuqest + */ + public function handle_request(): void { + $req = $this->get_req(); + $this->main->info = $req; + $this->handle_req($req); } } diff --git a/web/helper/error.php b/web/helper/error.php new file mode 100644 index 0000000..6fcaddd --- /dev/null +++ b/web/helper/error.php @@ -0,0 +1,9 @@ + $attr) { + echo $key . '="' . $attr . '" '; + } + echo '> '; + if ($icon) { + echo ''; + if ($content) { + echo $content; + } + echo ''; + } + if ($text) { + echo '' . $text . ''; + } + if ($click) { + echo ''; + } else { + echo ''; + } +} diff --git a/web/index.php b/web/index.php index 1032b7f..9c2d239 100644 --- a/web/index.php +++ b/web/index.php @@ -2,114 +2,26 @@ session_start(); -$lang = array(); -$__vars = array(); $webroot = dirname(__FILE__); -function error_page($code, $msg) { - $root = $GLOBALS['webroot']; - error_reporting(E_ERROR | E_PARSE); - http_response_code($code); - require($root . '/core/error.php'); - die(); -} +// load all the helper files +require($webroot . '/helper/error.php'); +require($webroot . '/helper/lang.php'); -function lang($key, $default = NULL, $sub = NULL) { - $lang = $GLOBALS['lang']; - if(array_key_exists($key, $lang)) { - if ($sub) { - return sprintf($lang[$key], ...$sub); - } else { - return $lang[$key]; - } - } else if ($default !== NULL) { - return $default; - } else { - return $key; - } -} +// load all the config files +require($webroot . '/config/aesthetic.php'); +require($webroot . '/config/routes.php'); -function ilang($key, - $class = NULL, - $id = NULL, - $href = NULL, - $click = NULL, - $attrs = array(), - $sub = NULL, - $button = FALSE, -) { - $text = lang($key . "_text", FALSE, sub: $sub); - $tip = lang($key . "_tip", FALSE); - $icon = lang($key . "_icon", FALSE); - $content = lang($key . "_content", FALSE); - - if ($click || $button) { - echo ''; - } else { - echo ''; - } -} +// load all core files +require($webroot . '/core/_controller.php'); +require($webroot . '/core/_model.php'); +require($webroot . '/core/database.php'); +require($webroot . '/core/loader.php'); +require($webroot . '/core/router.php'); function __init() { - - $root = $GLOBALS['webroot']; - - // load all core files - require($root . '/core/database.php'); - require($root . '/core/aesthetic.php'); - require($root . '/core/controller.php'); - require($root . '/core/model.php'); - require($root . '/core/loader.php'); - require($root . '/core/main.php'); - require($root . '/core/router.php'); - - $main = new MainModel(); $load = new Loader(); - $router = new Router($main, $load); - - $GLOBALS['__vars']['main'] = $main; - $GLOBALS['__vars']['load'] = $load; - $GLOBALS['__vars']['router'] = $router; - + $router = new Router($load); $router->handle_request(); }; @@ -118,5 +30,3 @@ if (!file_exists('/status/ready')) { } __init(); - -?> diff --git a/web/lang/en_US/api_lang.php b/web/lang/en_US/api_lang.php new file mode 100644 index 0000000..129147c --- /dev/null +++ b/web/lang/en_US/api_lang.php @@ -0,0 +1,26 @@ + diff --git a/web/lang/en_US/apps/home.php b/web/lang/en_US/apps/home.php new file mode 100644 index 0000000..a30eb88 --- /dev/null +++ b/web/lang/en_US/apps/home.php @@ -0,0 +1,9 @@ + diff --git a/web/lang/en_US/common_lang.php b/web/lang/en_US/common_lang.php index 3ce2fdb..7e214b5 100644 --- a/web/lang/en_US/common_lang.php +++ b/web/lang/en_US/common_lang.php @@ -1,4 +1,4 @@ - diff --git a/web/public/css/common.css b/web/public/css/common.css index 05f429f..84aabfc 100644 --- a/web/public/css/common.css +++ b/web/public/css/common.css @@ -52,6 +52,8 @@ body { } header { + top: 0; + position: sticky; height: 3.5rem; background-color: var(--primary); display: flex; @@ -145,6 +147,10 @@ input:focus { align-items: center; } +.nav { + position: sticky; +} + .nav-right { flex: 1; justify-content: flex-end; @@ -333,6 +339,30 @@ input:focus { border-radius: .5rem; display: flex; flex-direction: column; + animation: fadeIn .1s, slideInModal .1s linear; +} + +@keyframes slideInModal { + 0% { + animation-timing-function: ease-in; + transform: translate(-50%, -60%); + } +} + +@keyframes slideIn { + 0% { + animation-timing-function: ease-out; + transform: translate(0, -50%); + } +} + +@keyframes fadeIn { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } } .modal>form { @@ -402,3 +432,30 @@ button[type="submit"]:hover { background-color: var(--logo); } +#toast-container { + position: fixed; + top: 4rem; + left: 100%; + transform: translateX(-110%); + margin-top: 1rem; + z-index: 10000; +} + +.toast { + padding: .75rem; + margin: .5rem; + border-radius: .5rem; + min-width: 15rem; + font-family: sfpro; + animation: fadeIn .1s, slideIn .25s linear; + display: flex; + justify-content: space-between; +} + +.toast.error { + background-color: var(--error); +} + +.toast.success { + background-color: var(--success); +} diff --git a/web/public/js/lib.js b/web/public/js/lib.js index d822b02..7647208 100644 --- a/web/public/js/lib.js +++ b/web/public/js/lib.js @@ -1,4 +1,8 @@ +/// +/// document ready functions +/// + let ready = false; $(function() { @@ -15,9 +19,14 @@ var r$ = function(callback) { } } -function observe(containerSelector, elementSelector, callback) { - r$(() => { +/// +/// dom observer +/// checks for elements on the DOM now and added later +/// +function observe(containerSelector, elementSelector, callback) { + + r$(() => { $(containerSelector + ' ' + elementSelector).each(function (_, e) { let me = $(e); callback(me); @@ -37,9 +46,64 @@ function observe(containerSelector, elementSelector, callback) { }; var target = $(containerSelector)[0]; + + if (!target) { + console.warn('[observe] didnt find container: ', containerSelector); + return; + } + var config = { childList: true, subtree: true }; var MutationObserver = window.MutationObserver; var observer = new MutationObserver(onMutationsObserved); observer.observe(target, config); }); } + +/// +/// ajax setup +/// + +let ajaxHeaders = {}; +ajaxHeaders['Content-Type'] = 'application/json'; +if (jwtStr) { + ajaxHeaders['Authorization'] = 'Bearer ' + jwtStr +} + +$.ajaxSetup({ + headers: ajaxHeaders +}) + +/// +/// ajax error handle +/// + +var errorToast = (xhr) => { + let data = xhr.responseJSON; + let msg = data.message; + let detail = data.details; + let hint = data.hint; + + let query = '?msg=' + msg; + if (detail) { + query += '&detail=' + detail; + } + if (hint) { + query += '&hint=' + hint; + } + let url = '/template/toast' + query; + $.get(url, function (data) { + $('#toast-container').prepend(data); + }) +} + +observe('#toast-container', '.action-close-toast', function(el) { + el.on('click', function() { + el.parent().remove(); + }); + + setTimeout(function() { + el.parent().remove(); + }, 5000); +}); + + diff --git a/web/core/helper.php b/web/public/js/routes/home.js similarity index 100% rename from web/core/helper.php rename to web/public/js/routes/home.js diff --git a/web/public/js/modal.js b/web/public/js/shared/modal.js similarity index 100% rename from web/public/js/modal.js rename to web/public/js/shared/modal.js diff --git a/web/public/js/post.js b/web/public/js/shared/post.js similarity index 92% rename from web/public/js/post.js rename to web/public/js/shared/post.js index 736fa2b..afbeaf0 100644 --- a/web/public/js/post.js +++ b/web/public/js/shared/post.js @@ -1,4 +1,4 @@ -observe('.post', '.action-load-comments', function(me) { +observe('#main-content', '.action-load-comments', function(me) { me.on('click', function() { let page = me.attr('page'); if (!page) { diff --git a/web/routes/error/controller.php b/web/routes/error/controller.php deleted file mode 100644 index 3cb2345..0000000 --- a/web/routes/error/controller.php +++ /dev/null @@ -1,20 +0,0 @@ -model = $model; - } - - public function index() { - parent::index(); - $data = $this->model->get_data(); - $this->view('header', $data); - $this->app_view('error', $data); - } - -} - -?> diff --git a/web/routes/error/views/error.php b/web/routes/error/views/error.php deleted file mode 100644 index 3b926bc..0000000 --- a/web/routes/error/views/error.php +++ /dev/null @@ -1,4 +0,0 @@ -
-

- -
diff --git a/web/views/apps/error/main.php b/web/views/apps/error/main.php new file mode 100644 index 0000000..81051bd --- /dev/null +++ b/web/views/apps/error/main.php @@ -0,0 +1,6 @@ + + +
+

+ +
diff --git a/web/routes/home/views/main.php b/web/views/apps/home/main.php similarity index 84% rename from web/routes/home/views/main.php rename to web/views/apps/home/main.php index bf0087b..b1c1efc 100644 --- a/web/routes/home/views/main.php +++ b/web/views/apps/home/main.php @@ -1,4 +1,5 @@ - + +
@@ -15,7 +16,7 @@
main->link_js($js); @@ -71,4 +79,6 @@ menu.toggleClass('visible'); }); - + +
+
diff --git a/web/views/modal/new-post.php b/web/views/modal/new_post.php similarity index 57% rename from web/views/modal/new-post.php rename to web/views/modal/new_post.php index 7215862..82243fb 100644 --- a/web/views/modal/new-post.php +++ b/web/views/modal/new_post.php @@ -1,7 +1,9 @@ + + main->user(); ?> -
+
view('template/pfp', array('user' => $user))?> @@ -12,8 +14,8 @@
@@ -26,3 +28,19 @@ )?>
+ diff --git a/web/views/template/comment.php b/web/views/template/comment.php index ef7a081..943f232 100644 --- a/web/views/template/comment.php +++ b/web/views/template/comment.php @@ -1,3 +1,5 @@ + +
view('template/pfp', array('user' => $user))?>
diff --git a/web/core/error.php b/web/views/template/error.php similarity index 100% rename from web/core/error.php rename to web/views/template/error.php diff --git a/web/views/template/modal.php b/web/views/template/modal.php index 4f47400..e3ce6fe 100644 --- a/web/views/template/modal.php +++ b/web/views/template/modal.php @@ -1,3 +1,5 @@ + +