post comments, refactor post loading, hide load more btn
This commit is contained in:
parent
2968ee5280
commit
1f647374a8
22 changed files with 647 additions and 98 deletions
15
db/rest/comment/api_comment.sql
Normal file
15
db/rest/comment/api_comment.sql
Normal file
|
@ -0,0 +1,15 @@
|
|||
CREATE VIEW api.comment AS
|
||||
SELECT
|
||||
c.id,
|
||||
c.user_id,
|
||||
c.post_id,
|
||||
c.content,
|
||||
c.date
|
||||
FROM
|
||||
admin.comment c
|
||||
ORDER BY id ASC;
|
||||
|
||||
GRANT SELECT ON TABLE api.comment
|
||||
TO rest_anon, rest_user;
|
||||
GRANT SELECT ON TABLE admin.comment
|
||||
TO rest_anon, rest_user;
|
31
db/rest/comment/api_comment_delete.sql
Normal file
31
db/rest/comment/api_comment_delete.sql
Normal file
|
@ -0,0 +1,31 @@
|
|||
CREATE FUNCTION _api.comment_delete()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE plpgsql VOLATILE
|
||||
AS $BODY$
|
||||
DECLARE
|
||||
_user_id INTEGER;
|
||||
BEGIN
|
||||
_user_id = _api.get_user_id();
|
||||
|
||||
IF OLD.user_id <> _user_id THEN
|
||||
PERFORM _api.raise_deny();
|
||||
END IF;
|
||||
|
||||
DELETE FROM admin.comment
|
||||
WHERE user_id = _user_id
|
||||
AND id = OLD.id;
|
||||
END
|
||||
$BODY$;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION _api.comment_delete()
|
||||
TO rest_user;
|
||||
GRANT DELETE ON TABLE api.comment
|
||||
TO rest_user;
|
||||
GRANT DELETE ON TABLE admin.comment
|
||||
TO rest_user;
|
||||
|
||||
CREATE TRIGGER api_comment_delete_trgr
|
||||
INSTEAD OF DELETE
|
||||
ON api.comment
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE _api.comment_delete();
|
56
db/rest/comment/api_comment_insert.sql
Normal file
56
db/rest/comment/api_comment_insert.sql
Normal file
|
@ -0,0 +1,56 @@
|
|||
CREATE FUNCTION _api.comment_insert()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE plpgsql VOLATILE
|
||||
AS $BODY$
|
||||
DECLARE
|
||||
_user_id INTEGER;
|
||||
BEGIN
|
||||
_user_id = _api.get_user_id();
|
||||
|
||||
NEW.content := _api.trim(NEW.content);
|
||||
PERFORM _api.validate_text(
|
||||
_text => NEW.content,
|
||||
_column => 'content',
|
||||
_min => 1,
|
||||
_max => 1024
|
||||
);
|
||||
|
||||
PERFORM TRUE
|
||||
FROM admin.post
|
||||
WHERE id = NEW.post_id;
|
||||
|
||||
IF NOT FOUND THEN
|
||||
PERFORM _api.raise(
|
||||
_msg => 'api_null_post',
|
||||
_err => 400
|
||||
);
|
||||
END IF;
|
||||
|
||||
INSERT INTO admin.comment (
|
||||
user_id,
|
||||
post_id,
|
||||
content
|
||||
) VALUES (
|
||||
_user_id,
|
||||
NEW.post_id,
|
||||
NEW.content
|
||||
);
|
||||
|
||||
RETURN NEW;
|
||||
END
|
||||
$BODY$;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION _api.comment_insert()
|
||||
TO rest_user;
|
||||
GRANT INSERT ON TABLE api.comment
|
||||
TO rest_user;
|
||||
GRANT INSERT ON TABLE admin.comment
|
||||
TO rest_user;
|
||||
GRANT UPDATE ON TABLE sys.comment_id_seq
|
||||
TO rest_user;
|
||||
|
||||
CREATE TRIGGER api_comment_insert_trgr
|
||||
INSTEAD OF INSERT
|
||||
ON api.comment
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE _api.comment_insert();
|
50
db/rest/comment/api_comment_update.sql
Normal file
50
db/rest/comment/api_comment_update.sql
Normal file
|
@ -0,0 +1,50 @@
|
|||
CREATE FUNCTION _api.comment_update()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE plpgsql VOLATILE
|
||||
AS $BODY$
|
||||
DECLARE
|
||||
_user_id INTEGER;
|
||||
_changed BOOLEAN;
|
||||
BEGIN
|
||||
_user_id = _api.get_user_id();
|
||||
_changed = FALSE;
|
||||
|
||||
IF OLD.user_id <> _user_id THEN
|
||||
PERFORM _api.raise_deny();
|
||||
END IF;
|
||||
|
||||
NEW.content = COALESCE(NEW.content, OLD.content);
|
||||
NEW.content := _api.trim(NEW.content);
|
||||
PERFORM _api.validate_text(
|
||||
_text => NEW.content,
|
||||
_column => 'content',
|
||||
_min => 1,
|
||||
_max => 1024
|
||||
);
|
||||
|
||||
IF NEW.content IS DISTINCT FROM OLD.content THEN
|
||||
_changed = TRUE;
|
||||
END IF;
|
||||
|
||||
IF _changed THEN
|
||||
UPDATE admin.comment
|
||||
SET content = NEW.content
|
||||
WHERE id = OLD.id;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END
|
||||
$BODY$;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION _api.comment_update()
|
||||
TO rest_user;
|
||||
GRANT UPDATE ON TABLE api.comment
|
||||
TO rest_user;
|
||||
GRANT UPDATE ON TABLE admin.comment
|
||||
TO rest_user;
|
||||
|
||||
CREATE TRIGGER api_comment_update_trgr
|
||||
INSTEAD OF UPDATE
|
||||
ON api.comment
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE _api.comment_update();
|
|
@ -3,10 +3,21 @@ CREATE VIEW api.post AS
|
|||
p.id,
|
||||
p.user_id,
|
||||
p.content,
|
||||
p.date
|
||||
p.date,
|
||||
COALESCE(c.cc, 0)
|
||||
AS comment_count
|
||||
FROM
|
||||
admin.post p
|
||||
ORDER BY id DESC;
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
COUNT(c.id) as cc,
|
||||
c.post_id
|
||||
FROM
|
||||
admin.comment c
|
||||
GROUP BY
|
||||
c.post_id
|
||||
) c ON p.id = c.post_id
|
||||
ORDER BY p.id DESC;
|
||||
|
||||
GRANT SELECT ON TABLE api.post
|
||||
TO rest_anon, rest_user;
|
||||
|
|
|
@ -7,6 +7,8 @@ DECLARE
|
|||
BEGIN
|
||||
_user_id = _api.get_user_id();
|
||||
|
||||
NEW.content := _api.trim(NEW.content);
|
||||
|
||||
PERFORM _api.validate_text(
|
||||
_text => NEW.content,
|
||||
_column => 'content',
|
||||
|
|
|
@ -3,13 +3,45 @@ RETURNS TRIGGER
|
|||
LANGUAGE plpgsql VOLATILE
|
||||
AS $BODY$
|
||||
DECLARE
|
||||
_length INTEGER;
|
||||
_user_id INTEGER;
|
||||
_changed BOOLEAN;
|
||||
BEGIN
|
||||
_user_id = _api.get_user_id();
|
||||
_changed = FALSE;
|
||||
|
||||
IF OLD.user_id <> _user_id THEN
|
||||
PERFORM _api.raise_deny();
|
||||
END IF;
|
||||
|
||||
NEW.content = COALESCE(NEW.content, OLD.content);
|
||||
NEW.content := _api.trim(NEW.content);
|
||||
PERFORM _api.validate_text(
|
||||
_text => NEW.content,
|
||||
_column => 'content',
|
||||
_min => 1,
|
||||
_max => 4096
|
||||
);
|
||||
|
||||
IF NEW.content IS DISTINCT FROM OLD.content THEN
|
||||
_changed = TRUE;
|
||||
END IF;
|
||||
|
||||
IF _changed THEN
|
||||
UPDATE admin.post
|
||||
SET content = NEW.content
|
||||
WHERE id = OLD.id;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END
|
||||
$BODY$;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION _api.post_update() TO rest_user;
|
||||
GRANT EXECUTE ON FUNCTION _api.post_update()
|
||||
TO rest_user;
|
||||
GRANT UPDATE ON TABLE api.post
|
||||
TO rest_user;
|
||||
GRANT UPDATE ON TABLE admin.post
|
||||
TO rest_user;
|
||||
|
||||
CREATE TRIGGER api_post_update_trgr
|
||||
INSTEAD OF UPDATE
|
||||
|
|
|
@ -14,6 +14,7 @@ GRANT USAGE ON SCHEMA api TO rest_anon, rest_user;
|
|||
GRANT USAGE ON SCHEMA _api TO rest_anon, rest_user;
|
||||
|
||||
-- util
|
||||
\i /db/rest/util/_api_trim.sql;
|
||||
\i /db/rest/util/_api_serve_media.sql;
|
||||
\i /db/rest/util/_api_raise.sql;
|
||||
\i /db/rest/util/_api_raise_null.sql;
|
||||
|
@ -34,6 +35,12 @@ GRANT USAGE ON SCHEMA _api TO rest_anon, rest_user;
|
|||
\i /db/rest/post/api_post_update.sql;
|
||||
\i /db/rest/post/api_post_delete.sql;
|
||||
|
||||
-- comment
|
||||
\i /db/rest/comment/api_comment.sql;
|
||||
\i /db/rest/comment/api_comment_insert.sql;
|
||||
\i /db/rest/comment/api_comment_update.sql;
|
||||
\i /db/rest/comment/api_comment_delete.sql;
|
||||
|
||||
-- login
|
||||
\i /db/rest/login/_api_sign_jwt.sql;
|
||||
\i /db/rest/login/_api_verify_jwt.sql;
|
||||
|
|
|
@ -5,6 +5,16 @@ AS $BODY$
|
|||
DECLARE
|
||||
_length INTEGER;
|
||||
BEGIN
|
||||
|
||||
NEW.username := _api.trim(NEW.username);
|
||||
NEW.password := _api.trim(NEW.password);
|
||||
NEW.first_name := _api.trim(NEW.first_name);
|
||||
NEW.last_name := _api.trim(NEW.last_name);
|
||||
NEW.middle_name := _api.trim(NEW.middle_name);
|
||||
NEW.email := _api.trim(NEW.email);
|
||||
NEW.gender := _api.trim(NEW.gender);
|
||||
NEW.profile_bio := _api.trim(NEW.profile_bio);
|
||||
|
||||
PERFORM _api.validate_text(
|
||||
_text => NEW.username,
|
||||
_column => 'username',
|
||||
|
@ -22,6 +32,7 @@ BEGIN
|
|||
PERFORM _api.validate_text(
|
||||
_text => NEW.password,
|
||||
_column => 'password',
|
||||
_min => 1,
|
||||
_max => 256
|
||||
);
|
||||
|
||||
|
@ -82,8 +93,6 @@ BEGIN
|
|||
email,
|
||||
gender,
|
||||
birth_date,
|
||||
profile_avatar,
|
||||
profile_banner,
|
||||
profile_bio
|
||||
) VALUES (
|
||||
NEW.username,
|
||||
|
@ -94,8 +103,6 @@ BEGIN
|
|||
NEW.email,
|
||||
NEW.gender,
|
||||
NEW.birth_date,
|
||||
NEW.profile_avatar,
|
||||
NEW.profile_banner,
|
||||
NEW.profile_bio
|
||||
);
|
||||
|
||||
|
|
|
@ -3,15 +3,161 @@ RETURNS TRIGGER
|
|||
LANGUAGE plpgsql VOLATILE
|
||||
AS $BODY$
|
||||
DECLARE
|
||||
_length INTEGER;
|
||||
_user_id INTEGER;
|
||||
_changed BOOLEAN;
|
||||
BEGIN
|
||||
_user_id = _api.get_user_id();
|
||||
_changed = FALSE;
|
||||
|
||||
IF OLD.id <> _user_id THEN
|
||||
PERFORM _api.raise_deny();
|
||||
END IF;
|
||||
|
||||
-- username
|
||||
NEW.username = COALESCE(NEW.username, OLD.username);
|
||||
NEW.username := _api.trim(NEW.username);
|
||||
PERFORM _api.validate_text(
|
||||
_text => NEW.username,
|
||||
_column => 'username',
|
||||
_min => 1,
|
||||
_max => 24
|
||||
);
|
||||
|
||||
IF NEW.username IS DISTINCT FROM OLD.username THEN
|
||||
PERFORM TRUE FROM admin.user
|
||||
WHERE username = NEW.username;
|
||||
IF FOUND THEN
|
||||
PERFORM _api.raise_unique('username');
|
||||
END IF;
|
||||
_changed = TRUE;
|
||||
END IF;
|
||||
|
||||
-- password
|
||||
SELECT password
|
||||
INTO OLD.password
|
||||
FROM admin.user
|
||||
WHERE id = OLD.id;
|
||||
|
||||
NEW.password = COALESCE(NEW.password, OLD.password);
|
||||
NEW.password := _api.trim(NEW.password);
|
||||
PERFORM _api.validate_text(
|
||||
_text => NEW.password,
|
||||
_column => 'password',
|
||||
_min => 1,
|
||||
_max => 256
|
||||
);
|
||||
|
||||
IF NEW.password IS DISTINCT FROM OLD.password THEN
|
||||
_changed = TRUE;
|
||||
END IF;
|
||||
|
||||
-- first name
|
||||
NEW.first_name = COALESCE(NEW.first_name, OLD.first_name);
|
||||
NEW.first_name := _api.trim(NEW.first_name);
|
||||
PERFORM _api.validate_text(
|
||||
_text => NEW.first_name,
|
||||
_column => 'first_name',
|
||||
_max => 256
|
||||
);
|
||||
|
||||
IF NEW.first_name IS DISTINCT FROM OLD.first_name THEN
|
||||
_changed = TRUE;
|
||||
END IF;
|
||||
|
||||
-- last name
|
||||
NEW.last_name = COALESCE(NEW.last_name, OLD.last_name);
|
||||
NEW.last_name := _api.trim(NEW.last_name);
|
||||
PERFORM _api.validate_text(
|
||||
_text => NEW.last_name,
|
||||
_column => 'last_name',
|
||||
_max => 256
|
||||
);
|
||||
|
||||
IF NEW.last_name IS DISTINCT FROM OLD.last_name THEN
|
||||
_changed = TRUE;
|
||||
END IF;
|
||||
|
||||
-- middle name
|
||||
NEW.middle_name = COALESCE(NEW.middle_name, OLD.middle_name);
|
||||
NEW.middle_name := _api.trim(NEW.middle_name);
|
||||
PERFORM _api.validate_text(
|
||||
_text => NEW.middle_name,
|
||||
_column => 'middle_name',
|
||||
_max => 256
|
||||
);
|
||||
|
||||
IF NEW.middle_name IS DISTINCT FROM OLD.middle_name THEN
|
||||
_changed = TRUE;
|
||||
END IF;
|
||||
|
||||
-- email
|
||||
NEW.email = COALESCE(NEW.email, OLD.email);
|
||||
NEW.email := _api.trim(NEW.email);
|
||||
PERFORM _api.validate_text(
|
||||
_text => NEW.email,
|
||||
_column => 'email',
|
||||
_max => 256
|
||||
);
|
||||
|
||||
IF NEW.email IS DISTINCT FROM OLD.email THEN
|
||||
_changed = TRUE;
|
||||
END IF;
|
||||
|
||||
-- gender
|
||||
NEW.gender = COALESCE(NEW.gender, OLD.gender);
|
||||
NEW.gender := _api.trim(NEW.gender);
|
||||
PERFORM _api.validate_text(
|
||||
_text => NEW.gender,
|
||||
_column => 'gender',
|
||||
_max => 256
|
||||
);
|
||||
|
||||
IF NEW.gender IS DISTINCT FROM OLD.gender THEN
|
||||
_changed = TRUE;
|
||||
END IF;
|
||||
|
||||
-- birth date
|
||||
NEW.birth_date = COALESCE(NEW.birth_date, OLD.birth_date);
|
||||
IF NEW.birth_date IS DISTINCT FROM OLD.birth_date THEN
|
||||
_changed = TRUE;
|
||||
END IF;
|
||||
|
||||
-- profile bio
|
||||
NEW.profile_bio = COALESCE(NEW.profile_bio, OLD.profile_bio);
|
||||
NEW.profile_bio := _api.trim(NEW.profile_bio);
|
||||
PERFORM _api.validate_text(
|
||||
_text => NEW.profile_bio,
|
||||
_column => 'profile_bio',
|
||||
_max => 2048
|
||||
);
|
||||
|
||||
IF NEW.profile_bio IS DISTINCT FROM OLD.profile_bio THEN
|
||||
_changed = TRUE;
|
||||
END IF;
|
||||
|
||||
IF _changed THEN
|
||||
UPDATE admin.user SET
|
||||
username = NEW.username,
|
||||
password = NEW.password,
|
||||
first_name = NEW.first_name,
|
||||
last_name = NEW.last_name,
|
||||
middle_name = NEW.middle_name,
|
||||
email = NEW.email,
|
||||
gender = NEW.gender,
|
||||
birth_date = NEW.birth_date,
|
||||
profile_bio = NEW.profile_bio
|
||||
WHERE id = OLD.id;
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
END
|
||||
$BODY$;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION _api.user_update()
|
||||
TO rest_user;
|
||||
GRANT DELETE ON TABLE api.user
|
||||
GRANT UPDATE ON TABLE api.user
|
||||
TO rest_user;
|
||||
GRANT UPDATE ON TABLE admin.user
|
||||
TO rest_user;
|
||||
|
||||
CREATE TRIGGER api_user_update_trgr
|
||||
|
|
25
db/rest/util/_api_trim.sql
Normal file
25
db/rest/util/_api_trim.sql
Normal file
|
@ -0,0 +1,25 @@
|
|||
CREATE FUNCTION _api.trim(
|
||||
_text TEXT
|
||||
)
|
||||
RETURNS TEXT
|
||||
LANGUAGE plpgsql VOLATILE
|
||||
AS $BODY$
|
||||
DECLARE
|
||||
_new TEXT;
|
||||
BEGIN
|
||||
|
||||
IF _text IS NULL THEN
|
||||
RETURN NULL;
|
||||
END IF;
|
||||
|
||||
_new = _text;
|
||||
_new = TRIM(_new);
|
||||
_new = REGEXP_REPLACE(_new, '^(?: |\r|\n)*', '');
|
||||
_new = REGEXP_REPLACE(_new, '(?: |\r|\n)*$', '');
|
||||
|
||||
RETURN _new;
|
||||
END
|
||||
$BODY$;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION _api.trim(TEXT)
|
||||
TO rest_anon, rest_user;
|
|
@ -33,6 +33,7 @@ BEGIN
|
|||
_detail => _column,
|
||||
_hint => _min || ''
|
||||
);
|
||||
RETURN FALSE;
|
||||
END IF;
|
||||
|
||||
IF _max IS NOT NULL AND _length > _max THEN
|
||||
|
@ -41,6 +42,7 @@ BEGIN
|
|||
_detail => _column,
|
||||
_hint => _max || ''
|
||||
);
|
||||
RETURN FALSE;
|
||||
END IF;
|
||||
|
||||
RETURN TRUE;
|
||||
|
|
129
web/_controller/_util/post.php
Normal file
129
web/_controller/_util/post.php
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||
class Post_controller extends Controller {
|
||||
|
||||
// the request model
|
||||
private $request_model;
|
||||
|
||||
// the caceh model
|
||||
private $cache_model;
|
||||
|
||||
// page size
|
||||
private $page_size;
|
||||
|
||||
function __construct($load) {
|
||||
parent::__construct($load);
|
||||
$this->request_model = $this->load->model('request');
|
||||
$this->cache_model = $this->load->model('cache');
|
||||
$this->page_size = 10;
|
||||
}
|
||||
|
||||
public function index(): void {
|
||||
$this->view('template/posts');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public function posts(): array {
|
||||
$page = $this->request_model->get_int('page', 0);
|
||||
$max = $this->request_model->get_int('max');
|
||||
$offset = $page * $this->page_size;
|
||||
|
||||
$user = $this->main->user();
|
||||
|
||||
$query = $this->db;
|
||||
|
||||
if ($user) {
|
||||
$query = $query->select('p.*, l.post_id IS NOT NULL as liked');
|
||||
} else {
|
||||
$query = $query->select('p.*, FALSE as liked');
|
||||
}
|
||||
|
||||
$query = $query->from('api.post p');
|
||||
|
||||
if ($user) {
|
||||
$query = $query->join('admin.like l', 'p.id = l.post_id AND l.user_id')
|
||||
->eq($user['id']);
|
||||
}
|
||||
|
||||
if ($max) {
|
||||
$query = $query
|
||||
->where('id')->le($max);
|
||||
}
|
||||
|
||||
$posts = $query
|
||||
->limit($this->page_size)
|
||||
->offset($offset)
|
||||
->rows();
|
||||
|
||||
$users = $this->cache_model->get_users($posts);
|
||||
$max = 0;
|
||||
|
||||
foreach ($posts as $post) {
|
||||
$max = max($max, $post['id']);
|
||||
$data = array();
|
||||
$data['page_size'] = $this->page_size;
|
||||
$data['user'] = $users[$post['user_id']];
|
||||
$data['post'] = $post;
|
||||
$this->view('template/post', $data);
|
||||
}
|
||||
|
||||
$pc = $this->db
|
||||
->select('COUNT(p.id) as pc')
|
||||
->from('api.post p')
|
||||
->row()['pc'];
|
||||
|
||||
|
||||
return array(
|
||||
'loaded' => count($posts),
|
||||
'total' => $pc,
|
||||
'page_size' => $this->page_size,
|
||||
'max' => $max,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public function comments(): array {
|
||||
$page = $this->request_model->get_int('page', 0);
|
||||
$max = $this->request_model->get_int('max');
|
||||
$id = $this->request_model->get_int('id', 0);
|
||||
$offset = $page * $this->page_size;
|
||||
|
||||
$query = $this->db
|
||||
->select('*')
|
||||
->from('api.comment')
|
||||
->where('post_id')
|
||||
->eq($id);
|
||||
|
||||
if ($max) {
|
||||
$query = $query
|
||||
->and()
|
||||
->where('id')
|
||||
->le($max);
|
||||
}
|
||||
|
||||
$comments = $query
|
||||
->limit($this->page_size)
|
||||
->offset($offset)
|
||||
->rows();
|
||||
|
||||
$users = $this->cache_model->get_users($comments);
|
||||
$max = 0;
|
||||
|
||||
foreach ($comments as $comment) {
|
||||
$max = max($max, $comment['id']);
|
||||
$data = array();
|
||||
$data['user'] = $users[$comment['user_id']];
|
||||
$data['comment'] = $comment;
|
||||
$this->view('template/comment', $data);
|
||||
}
|
||||
|
||||
return array(
|
||||
'loaded' => count($comments),
|
||||
'page_size' => $this->page_size,
|
||||
'max' => $max,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -4,17 +4,13 @@ class Home_controller extends Controller {
|
|||
// the home model
|
||||
private $home_model;
|
||||
|
||||
// the request model
|
||||
private $request_model;
|
||||
|
||||
// the caceh model
|
||||
private $cache_model;
|
||||
// the post controller
|
||||
protected $post_controller;
|
||||
|
||||
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');
|
||||
$this->post_controller = $this->load->controller('_util/post');
|
||||
}
|
||||
|
||||
public function index(): void {
|
||||
|
@ -24,66 +20,6 @@ class Home_controller extends Controller {
|
|||
$this->view('apps/home/main', $data);
|
||||
}
|
||||
|
||||
public function posts(): void {
|
||||
$page = $this->request_model->get_int('page', 0);
|
||||
$page_size = 20;
|
||||
$offset = $page * $page_size;
|
||||
|
||||
$user = $this->main->user();
|
||||
|
||||
$query = $this->db;
|
||||
|
||||
if ($user) {
|
||||
$query = $query->select('p.*, l.post_id IS NOT NULL as liked');
|
||||
} else {
|
||||
$query = $query->select('p.*, FALSE as liked');
|
||||
}
|
||||
|
||||
$query = $query->from('api.post p');
|
||||
|
||||
if ($user) {
|
||||
$query = $query->join('admin.like l', 'p.id = l.post_id')
|
||||
->where('l.user_id')->eq($user['id'])
|
||||
->or()->where('l.user_id IS NULL');
|
||||
}
|
||||
|
||||
$posts = $query->limit($page_size)
|
||||
->offset($offset)
|
||||
->rows();
|
||||
|
||||
$users = $this->cache_model->get_users($posts);
|
||||
|
||||
foreach ($posts as $post) {
|
||||
$data = array();
|
||||
$data['user'] = $users[$post['user_id']];
|
||||
$data['post'] = $post;
|
||||
$this->view('template/post', $data);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
$comments = $this->db
|
||||
->select('*')
|
||||
->from('admin.comment')
|
||||
->limit($page_size)
|
||||
->offset($offset)
|
||||
->rows();
|
||||
|
||||
$users = $this->cache_model->get_users($comments);
|
||||
|
||||
foreach ($comments as $comment) {
|
||||
$data = array();
|
||||
$data['user'] = $users[$comment['user_id']];
|
||||
$data['comment'] = $comment;
|
||||
$this->view('template/comment', $data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||
class Format_model extends Modal {
|
||||
class Format_model extends Model {
|
||||
|
||||
function __construct($load) {
|
||||
parent::__construct($load);
|
||||
|
|
|
@ -23,8 +23,5 @@
|
|||
</script>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div id="post-container">
|
||||
<?=$this->posts()?>
|
||||
</div>
|
||||
<?=ilang('action_load_posts', id: 'action-load-posts', class: 'btn btn-line')?>
|
||||
<?php $this->post_controller->index(); ?>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
|
||||
<?php /* vi: syntax=php */ ?>
|
||||
<?php
|
||||
$format_model = $this->load->model('format');
|
||||
?>
|
||||
<div class="comment row mt">
|
||||
<?php $this->view('template/pfp', array('user' => $user))?>
|
||||
<div class="ml col sub-card">
|
||||
<div class="row">
|
||||
<strong><?=$this->main->display_name($user)?></strong>
|
||||
<span class="dim ml"><?=$this->main->display_date($comment['date'])?></span>
|
||||
<strong><?=$format_model->name($user)?></strong>
|
||||
<span class="dim ml"><?=$format_model->date($comment['date'])?></span>
|
||||
</div>
|
||||
<?=$comment['content']?>
|
||||
</div>
|
||||
|
|
|
@ -29,25 +29,40 @@
|
|||
<div class="col comments">
|
||||
<?php
|
||||
$_GET['id'] = $post['id'];
|
||||
$this->comments();
|
||||
$cdata = $this->comments();
|
||||
|
||||
$loaded = $cdata['loaded'];
|
||||
$max = $cdata['max'];
|
||||
$page_size = $cdata['page_size'];
|
||||
$total = $post['comment_count'];
|
||||
|
||||
if ($loaded >= $page_size && $page_size < $total) {
|
||||
ilang('action_load_comments',
|
||||
class: 'action-load-comments btn btn-line mt',
|
||||
attrs: array('postId' => $post['id'])
|
||||
attrs: array(
|
||||
'postId' => $post['id'],
|
||||
'loaded' => $loaded,
|
||||
'pageSize' => $page_size,
|
||||
'commentCount' => $total,
|
||||
'commentMax' => $max,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
?>
|
||||
</div>
|
||||
<?php if ($self): ?>
|
||||
<div class="row grow mt">
|
||||
<?php $this->view('template/pfp', array('user' => $user))?>
|
||||
<form class="ml">
|
||||
<form class="ml action-new-comment-form">
|
||||
<input
|
||||
type="hidden"
|
||||
name="id"
|
||||
value="<?=$post['id']?>"
|
||||
>
|
||||
<input
|
||||
id="new-comment-<?=$post['id']?>"
|
||||
class="input"
|
||||
class="action-new-comment input"
|
||||
postId="<?=$post['id']?>"
|
||||
autocomplete="off"
|
||||
type="text"
|
||||
name="text"
|
||||
|
|
23
web/_views/template/posts.php
Normal file
23
web/_views/template/posts.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<div id="post-container">
|
||||
<?php
|
||||
$pdata = $this->posts();
|
||||
|
||||
$loaded = $pdata['loaded'];
|
||||
$page_size = $pdata['page_size'];
|
||||
$total = $pdata['total'];
|
||||
$max = $pdata['max'];
|
||||
|
||||
if ($loaded >= $page_size && $page_size < $total) {
|
||||
ilang('action_load_posts',
|
||||
id: 'action-load-posts',
|
||||
class: 'btn btn-line mb',
|
||||
attrs: array(
|
||||
'loaded' => $loaded,
|
||||
'pageSize' => $page_size,
|
||||
'postCount' => $total,
|
||||
'postMax' => $max,
|
||||
)
|
||||
);
|
||||
}
|
||||
?>
|
||||
</div>
|
|
@ -69,6 +69,18 @@ class DatabaseQuery {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function lt($item) {
|
||||
$this->query .= "< ?\n";
|
||||
array_push($this->param, $item);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function le($item) {
|
||||
$this->query .= "<= ?\n";
|
||||
array_push($this->param, $item);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function where_in($column, $array) {
|
||||
if (!$this->where) {
|
||||
$this->where = TRUE;
|
||||
|
|
|
@ -10,3 +10,7 @@
|
|||
.action-load-comments {
|
||||
margin-left: 4rem;
|
||||
}
|
||||
|
||||
#action-load-posts {
|
||||
justify-content: center;
|
||||
}
|
||||
|
|
|
@ -5,14 +5,28 @@ observe('#main-content', '.action-load-comments', function(me) {
|
|||
page = '1';
|
||||
}
|
||||
let newPage = Number(page) + 1;
|
||||
let id = me.attr('postId');
|
||||
me.attr('page', newPage + '');
|
||||
let url = '/home/comments?page=' + page + '&id=' + id;
|
||||
|
||||
let postId = me.attr('postId');
|
||||
let loaded = Number(me.attr('loaded'));
|
||||
let pageSize = Number(me.attr('pageSize'));
|
||||
let commmentCount = Number(me.attr('commentCount'));
|
||||
let commentMax = Number(me.attr('commentMax'));
|
||||
|
||||
let url = '/_util/post/comments?page=' + page + '&id=' + postId + '&max' + commentMax;
|
||||
$.get(url, function (data) {
|
||||
if (data === '') {
|
||||
me.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
$(data).insertBefore(me);
|
||||
|
||||
loaded += pageSize;
|
||||
if (loaded >= commmentCount) {
|
||||
me.remove();
|
||||
} else {
|
||||
$(me).prepend(data);
|
||||
me.attr('loaded', loaded + '');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -26,13 +40,45 @@ observe('#main-content', '#action-load-posts', function(me) {
|
|||
}
|
||||
let newPage = Number(page) + 1;
|
||||
me.attr('page', newPage + '');
|
||||
let url = '/home/posts?page=' + page;
|
||||
|
||||
let loaded = Number(me.attr('loaded'));
|
||||
let pageSize = Number(me.attr('pageSize'));
|
||||
let postCount = Number(me.attr('postCount'));
|
||||
let postMax = Number(me.attr('postMax'));
|
||||
|
||||
let url = '/_util/post/posts?page=' + page + '&max=' + postMax;
|
||||
$.get(url, function (data) {
|
||||
if (data === '') {
|
||||
me.remove();
|
||||
return;
|
||||
}
|
||||
|
||||
$(data).insertBefore(me);
|
||||
|
||||
loaded += pageSize;
|
||||
if (loaded >= postCount) {
|
||||
me.remove();
|
||||
} else {
|
||||
$('#post-container').append(data);
|
||||
me.attr('loaded', loaded + '');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
observe('#main-content', '.action-new-comment-form', function(me) {
|
||||
me.on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
let input = me.find('.action-new-comment');
|
||||
let content = input.val();
|
||||
let post_id = input.attr('postId');
|
||||
$.ajax({
|
||||
url: '/api/comment',
|
||||
method: 'POST',
|
||||
data: JSON.stringify({ post_id, content }),
|
||||
success: function(_data) {
|
||||
window.location.reload();
|
||||
},
|
||||
error: errorToast
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue