From 530bbf058781e00e588f1457b6ee589a64b74da1 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Fri, 5 Apr 2024 10:46:09 -0400 Subject: [PATCH] i did thing oh god large commit --- src/db/migrations/0000.sql | 12 +- .../_api_serve_system_media.sql} | 20 +- src/db/rest/media/_api_serve_user_media.sql | 37 ++++ .../_api_serve_user_or_default_media.sql | 41 +++++ src/db/rest/media/api_profile_avatar.sql | 30 +-- src/db/rest/media/api_profile_banner.sql | 13 +- src/db/rest/post/api_post.sql | 15 +- src/db/rest/rest.sql | 4 +- src/db/rest/user/api_user.sql | 67 ++++++- src/db/rest/util/_api_raise_not_found.sql | 16 ++ src/public/css/common.css | 35 +++- src/public/css/home.css | 7 +- src/public/css/people.css | 56 ++---- src/public/css/post.css | 16 ++ src/public/css/profile.css | 45 ++++- src/public/js/lib.js | 16 +- src/public/js/post.js | 21 +++ src/web/_controller/_util/post.php | 8 +- src/web/_controller/apps/people.php | 7 + src/web/_controller/apps/profile.php | 6 +- src/web/_model/apps/people.php | 62 +++---- src/web/_views/apps/home/main.php | 2 +- src/web/_views/apps/people/card.php | 26 +-- src/web/_views/apps/people/footer.php | 3 + src/web/_views/apps/people/header.php | 6 + src/web/_views/apps/people/main.php | 133 +++++++------- src/web/_views/apps/profile/main.php | 173 +++++++++++++++--- src/web/_views/header.php | 16 +- src/web/_views/modal/new_post.php | 2 +- src/web/_views/template/comment.php | 2 +- src/web/_views/template/pfp.php | 17 -- src/web/_views/template/post.php | 5 +- src/web/_views/template/posts.php | 2 +- src/web/config/aesthetic.php | 1 + src/web/helper/image.php | 33 ++++ src/web/index.php | 1 + src/web/lang/en_US/apps/profile.php | 23 ++- src/web/lang/en_US/common_lang.php | 1 + 38 files changed, 701 insertions(+), 279 deletions(-) rename src/db/rest/{util/_api_serve_media.sql => media/_api_serve_system_media.sql} (63%) create mode 100644 src/db/rest/media/_api_serve_user_media.sql create mode 100644 src/db/rest/media/_api_serve_user_or_default_media.sql create mode 100644 src/db/rest/util/_api_raise_not_found.sql create mode 100644 src/web/_views/apps/people/footer.php create mode 100644 src/web/_views/apps/people/header.php delete mode 100644 src/web/_views/template/pfp.php create mode 100644 src/web/helper/image.php diff --git a/src/db/migrations/0000.sql b/src/db/migrations/0000.sql index 7e14ac4..aa20d2f 100644 --- a/src/db/migrations/0000.sql +++ b/src/db/migrations/0000.sql @@ -198,7 +198,7 @@ CREATE TABLE admin.media ( id INTEGER DEFAULT nextval('sys.media_id_seq'::regclass) NOT NULL, name TEXT NOT NULL, content BYTEA NOT NULL, - type TEXT NOT NULL, + mime TEXT NOT NULL, created TIMESTAMP WITH TIME ZONE DEFAULT clock_timestamp() NOT NULL, modified TIMESTAMP WITH TIME ZONE DEFAULT clock_timestamp() NOT NULL ); @@ -224,9 +224,12 @@ CREATE TYPE admin.user_media_type AS ENUM ( CREATE TABLE admin.user_media ( id INTEGER DEFAULT nextval('sys.user_media_id_seq'::regclass) NOT NULL, - media_id INTEGER NOT NULL, user_id INTEGER NOT NULL, - type admin.user_media_type NOT NULL + content BYTEA NOT NULL, + mime TEXT NOT NULL, + type admin.user_media_type NOT NULL, + created TIMESTAMP WITH TIME ZONE DEFAULT clock_timestamp() NOT NULL, + modified TIMESTAMP WITH TIME ZONE DEFAULT clock_timestamp() NOT NULL ); ALTER TABLE admin.user_media OWNER TO xssbook; @@ -234,9 +237,6 @@ ALTER TABLE admin.user_media OWNER TO xssbook; ALTER TABLE ONLY admin.user_media ADD CONSTRAINT user_media_pkey PRIMARY KEY (id); -ALTER TABLE ONLY admin.user_media - ADD CONSTRAINT user_media_media_id_fkey FOREIGN KEY (media_id) REFERENCES admin.media (id) ON DELETE CASCADE; - ALTER TABLE ONLY admin.user_media ADD CONSTRAINT user_media_user_id_fkey FOREIGN KEY (user_id) REFERENCES admin.user (id) ON DELETE CASCADE; diff --git a/src/db/rest/util/_api_serve_media.sql b/src/db/rest/media/_api_serve_system_media.sql similarity index 63% rename from src/db/rest/util/_api_serve_media.sql rename to src/db/rest/media/_api_serve_system_media.sql index c2e213a..5cd87c2 100644 --- a/src/db/rest/util/_api_serve_media.sql +++ b/src/db/rest/media/_api_serve_system_media.sql @@ -1,4 +1,4 @@ -CREATE FUNCTION _api.serve_media( +CREATE FUNCTION _api.serve_system_media( _media_id INTEGER ) RETURNS sys."*/*" @@ -8,34 +8,30 @@ DECLARE _headers TEXT; _data BYTEA; BEGIN - SELECT FORMAT( '[{"Content-Type": "%s"},' '{"Content-Disposition": "inline; filename=\"%s\""},' '{"Cache-Control": "max-age=259200"}]' - , m.type, m.name) + , m.mime, m.name) FROM admin.media m - WHERE m.id = _media_id INTO _headers; - - PERFORM SET_CONFIG('response.headers', _headers, true); + WHERE m.id = _media_id + INTO _headers; SELECT m.content FROM admin.media m WHERE m.id = _media_id INTO _data; - IF FOUND THEN + IF _data IS NOT NULL THEN + PERFORM SET_CONFIG('response.headers', _headers, true); RETURN(_data); ELSE - PERFORM _api.raise( - _msg => 'api_not_found', - _err => 404 - ); + PERFORM _api.raise_not_found(); END IF; END $BODY$; -GRANT EXECUTE ON FUNCTION _api.serve_media(INTEGER) +GRANT EXECUTE ON FUNCTION _api.serve_system_media(INTEGER) TO rest_anon, rest_user; GRANT SELECT ON TABLE admin.media TO rest_anon, rest_user; diff --git a/src/db/rest/media/_api_serve_user_media.sql b/src/db/rest/media/_api_serve_user_media.sql new file mode 100644 index 0000000..3487493 --- /dev/null +++ b/src/db/rest/media/_api_serve_user_media.sql @@ -0,0 +1,37 @@ +CREATE FUNCTION _api.serve_user_media( + _media_id INTEGER +) +RETURNS sys."*/*" +LANGUAGE plpgsql VOLATILE +AS $BODY$ +DECLARE + _headers TEXT; + _data BYTEA; +BEGIN + SELECT FORMAT( + '[{"Content-Type": "%s"},' + '{"Content-Disposition": "inline"},' + '{"Cache-Control": "max-age=259200"}]' + , m.mime) + FROM admin.user_media m + WHERE m.id = _media_id + INTO _headers; + + SELECT m.content + FROM admin.user_media m + WHERE m.id = _media_id + INTO _data; + + IF _data IS NOT NULL THEN + PERFORM SET_CONFIG('response.headers', _headers, true); + RETURN(_data); + ELSE + PERFORM _api.raise_not_found(); + END IF; +END +$BODY$; + +GRANT EXECUTE ON FUNCTION _api.serve_user_media(INTEGER) + TO rest_anon, rest_user; +GRANT SELECT ON TABLE admin.user_media + TO rest_anon, rest_user; diff --git a/src/db/rest/media/_api_serve_user_or_default_media.sql b/src/db/rest/media/_api_serve_user_or_default_media.sql new file mode 100644 index 0000000..c079ba9 --- /dev/null +++ b/src/db/rest/media/_api_serve_user_or_default_media.sql @@ -0,0 +1,41 @@ +CREATE FUNCTION _api.serve_user_or_default_media( + _user_id INTEGER, + _type admin.user_media_type, + _default TEXT +) +RETURNS sys."*/*" +LANGUAGE plpgsql VOLATILE +AS $BODY$ +DECLARE + _media_id INTEGER; +BEGIN + + SELECT id + FROM admin.user_media m + WHERE m.type = _type + AND m.user_id = _user_id + INTO _media_id; + + IF FOUND THEN + RETURN _api.serve_user_media(_media_id); + END IF; + + SELECT id + FROM admin.media m + WHERE m.name = _default + INTO _media_id; + + IF FOUND THEN + RETURN _api.serve_system_media(_media_id); + END IF; + + PERFORM _api_raise_not_found(); +END +$BODY$; + +GRANT EXECUTE ON FUNCTION _api.serve_user_or_default_media(INTEGER, admin.user_media_type, TEXT) + TO rest_anon, rest_user; +GRANT SELECT ON TABLE admin.user_media + TO rest_anon, rest_user; +GRANT SELECT ON TABLE admin.media + TO rest_anon, rest_user; diff --git a/src/db/rest/media/api_profile_avatar.sql b/src/db/rest/media/api_profile_avatar.sql index 8607999..b3e456c 100644 --- a/src/db/rest/media/api_profile_avatar.sql +++ b/src/db/rest/media/api_profile_avatar.sql @@ -5,32 +5,16 @@ RETURNS sys."*/*" LANGUAGE plpgsql VOLATILE AS $BODY$ DECLARE - _id INTEGER; - _mod INTEGER; - _name TEXT; + _default TEXT; BEGIN - SELECT media_id INTO _id - FROM admin.user_media m - WHERE m.user_id = profile_avatar.user_id - AND type = 'avatar'::admin.user_media_type; - - -- get default if not exists - IF NOT FOUND THEN - _mod = MOD(user_id, 24); - _name = 'default_avatar_' || _mod || '.png'; - - SELECT id INTO _id - FROM admin.media - WHERE name = _name; - END IF; - - RETURN _api.serve_media(_id); + _default := 'default_avatar_' || MOD(user_id, 25) || '.png'; + RETURN _api.serve_user_or_default_media( + user_id, + 'avatar'::admin.user_media_type, + _default + ); END $BODY$; GRANT EXECUTE ON FUNCTION api.profile_avatar(INTEGER) TO rest_anon, rest_user; -GRANT SELECT ON TABLE admin.user_media - TO rest_anon, rest_user; -GRANT SELECT ON TABLE admin.media - TO rest_anon, rest_user; diff --git a/src/db/rest/media/api_profile_banner.sql b/src/db/rest/media/api_profile_banner.sql index 272d021..d98f553 100644 --- a/src/db/rest/media/api_profile_banner.sql +++ b/src/db/rest/media/api_profile_banner.sql @@ -4,10 +4,21 @@ CREATE FUNCTION api.profile_banner( RETURNS sys."*/*" LANGUAGE plpgsql VOLATILE AS $BODY$ +DECLARE + _default TEXT; BEGIN - PERFORM _api.raise_deny(); + _default := 'default_banner_' || MOD(user_id, 25) || '.png'; + RETURN _api.serve_user_or_default_media( + user_id, + 'banner'::admin.user_media_type, + _default + ); END $BODY$; GRANT EXECUTE ON FUNCTION api.profile_banner(INTEGER) TO rest_anon, rest_user; +GRANT SELECT ON TABLE admin.user_media + TO rest_anon, rest_user; +GRANT SELECT ON TABLE admin.media + TO rest_anon, rest_user; diff --git a/src/db/rest/post/api_post.sql b/src/db/rest/post/api_post.sql index 0d60473..b5c42a8 100644 --- a/src/db/rest/post/api_post.sql +++ b/src/db/rest/post/api_post.sql @@ -6,7 +6,9 @@ CREATE VIEW api.post AS p.created, p.modified, COALESCE(c.cc, 0) - AS comment_count + AS comment_count, + COALESCE(l.lc, 0) + AS like_count FROM admin.post p LEFT JOIN ( @@ -20,6 +22,17 @@ CREATE VIEW api.post AS ) c ON p.id = c.post_id + LEFT JOIN ( + SELECT + COUNT(l.id) as lc, + l.post_id + FROM + admin.like l + GROUP BY + l.post_id + ) l + ON + p.id = l.post_id LEFT JOIN admin.user u ON diff --git a/src/db/rest/rest.sql b/src/db/rest/rest.sql index e203f27..783866a 100644 --- a/src/db/rest/rest.sql +++ b/src/db/rest/rest.sql @@ -15,7 +15,6 @@ 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; \i /db/rest/util/_api_raise_unique.sql; @@ -47,6 +46,9 @@ GRANT USAGE ON SCHEMA _api TO rest_anon, rest_user; \i /db/rest/like/api_like_delete.sql; -- media +\i /db/rest/media/_api_serve_user_media.sql; +\i /db/rest/media/_api_serve_system_media.sql; +\i /db/rest/media/_api_serve_user_or_default_media.sql; \i /db/rest/media/api_profile_avatar.sql; \i /db/rest/media/api_profile_banner.sql; diff --git a/src/db/rest/user/api_user.sql b/src/db/rest/user/api_user.sql index 6735775..d71fd1b 100644 --- a/src/db/rest/user/api_user.sql +++ b/src/db/rest/user/api_user.sql @@ -13,9 +13,74 @@ CREATE VIEW api.user AS u.profile_bio, u.created, u.modified, - u.seen + u.seen, + COALESCE(f.fc, 0) + AS follower_count, + COALESCE(fl.fc, 0) + AS followed_count, + COALESCE(c.cc, 0) + AS comment_count, + COALESCE(p.pc, 0) + AS post_count, + COALESCE(l.lc, 0) + AS like_count FROM admin.user u + LEFT JOIN ( + SELECT + COUNT(f.id) as fc, + f.followee_id + FROM + admin.follow f + GROUP BY + f.followee_id + ) f + ON + u.id = f.followee_id + LEFT JOIN ( + SELECT + COUNT(fl.id) as fc, + fl.follower_id + FROM + admin.follow fl + GROUP BY + fl.follower_id + ) fl + ON + u.id = fl.follower_id + LEFT JOIN ( + SELECT + COUNT(c.id) as cc, + c.user_id + FROM + admin.comment c + GROUP BY + c.user_id + ) c + ON + u.id = c.user_id + LEFT JOIN ( + SELECT + COUNT(p.id) as pc, + p.user_id + FROM + admin.post p + GROUP BY + p.user_id + ) p + ON + u.id = p.user_id + LEFT JOIN ( + SELECT + COUNT(l.id) as lc, + l.user_id + FROM + admin.like l + GROUP BY + l.user_id + ) l + ON + u.id = l.user_id WHERE u.deleted <> TRUE; diff --git a/src/db/rest/util/_api_raise_not_found.sql b/src/db/rest/util/_api_raise_not_found.sql new file mode 100644 index 0000000..f4997a6 --- /dev/null +++ b/src/db/rest/util/_api_raise_not_found.sql @@ -0,0 +1,16 @@ +CREATE FUNCTION _api.raise_not_found() +RETURNS BOOLEAN +LANGUAGE plpgsql VOLATILE +AS $BODY$ +BEGIN + PERFORM _api.raise( + _msg => 'api_not_found', + _err => 404 + ); + + RETURN TRUE; +END +$BODY$; + +GRANT EXECUTE ON FUNCTION _api.raise_not_found() + TO rest_anon, rest_user; diff --git a/src/public/css/common.css b/src/public/css/common.css index 0750b8a..281df6b 100644 --- a/src/public/css/common.css +++ b/src/public/css/common.css @@ -170,6 +170,21 @@ a, button { color: var(--blue-alt); } +.btn { + position: relative; +} + +.btn-border::before { + position: absolute; + content: ""; + display: block; + bottom: -1px; + left: 0; + right: 0; + height: 1px; + background: var(--blue-alt); +} + input.btn:focus { border: none; outline: none; @@ -205,6 +220,7 @@ input.btn:focus { display: flex; flex-direction: row; align-items: center; + z-index: 5; } .nav { @@ -224,7 +240,7 @@ input.btn:focus { flex: 1; justify-content: center; height: 100%; - z-index: 2; + z-index: 6; } @media (min-width: 800px) { @@ -274,6 +290,11 @@ input.btn:focus { .nav-center .btn.active { border-bottom: none; } + + .nav .btn-border::before { + background: inherit; + } + } .nav-right .image-loading { @@ -305,6 +326,10 @@ input.btn:focus { animation: shimmer 1s linear infinite; } +.image-loaded { + background-color: var(--base); +} + .card { background-color: var(--surface0); border-radius: .5rem; @@ -393,6 +418,14 @@ input.btn:focus { display: flex; flex-direction: column; animation: fadeIn .1s, slideInModal .1s linear; + z-index: 10; +} + +@media (max-width: 40rem) { + .modal { + min-width: 100%; + width: 100%; + } } @keyframes slideInModal { diff --git a/src/public/css/home.css b/src/public/css/home.css index 3c2a3a1..3fdc381 100644 --- a/src/public/css/home.css +++ b/src/public/css/home.css @@ -2,11 +2,8 @@ display: flex; flex-direction: column; align-items: center; -} - -.card { - width: 40rem; - margin-bottom: 1rem; + padding: 1rem; + padding-bottom: 0; } .new-post-modal textarea { diff --git a/src/public/css/people.css b/src/public/css/people.css index 279c839..6b07eff 100644 --- a/src/public/css/people.css +++ b/src/public/css/people.css @@ -11,42 +11,20 @@ } #people-container { + display: grid; + width: 100%; + padding: 1rem 2rem; + margin-bottom: 1rem; + grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr) ); + grid-auto-rows: max-content; + grid-gap: 2rem; +} + +.profile { + width: 16rem; + text-decoration: none; margin-left: auto; margin-right: auto; - padding: 1rem 2rem; - padding-bottom: 0; - flex-direction: row; - align-items: center; - flex-wrap: wrap; - max-width: 90rem; -} - -.profile { - width: 25rem; -} - -@media(max-width: 1400px) { - #people-container { - max-width: 70rem; - } - .profile { - width: 25rem; - } -} - -@media(max-width: 1000px) { - #people-container { - max-width: 50rem; - } - .profile { - width: 20rem; - } -} - -.profile { - margin: 1rem; - text-decoration: none; - height: fit-content; } .profile:hover { @@ -54,16 +32,22 @@ } .profile strong { - font-size: 2rem; + font-size: 1.5rem; } .profile .pfp, .profile .pfp img { padding: none; margin: none; - height: 6rem; + width: 100%; + height: 100%; + aspect-ratio: 1; border-radius: .3rem; } +.profile .pfp { + margin-bottom: 1rem; +} + td:nth-child(1) { font-weight: bold; color: var(--subtext); diff --git a/src/public/css/post.css b/src/public/css/post.css index 6fd7ca0..2b6a4b1 100644 --- a/src/public/css/post.css +++ b/src/public/css/post.css @@ -8,6 +8,22 @@ justify-content: center; } +.post, #new-post { + margin-bottom: 1rem; + width: 40rem; +} + .post { padding-bottom: 0; } + +@media(max-width: 40rem) { + .post, #new-post { + width: 100%; + } +} + +.post .likes { + display: block; + padding-top: .25rem; +} diff --git a/src/public/css/profile.css b/src/public/css/profile.css index a16fdfd..71cbbfa 100644 --- a/src/public/css/profile.css +++ b/src/public/css/profile.css @@ -4,17 +4,34 @@ padding: 0; } -#profile-header { +#profile-header-container { + width: 100%; + display: flex; + flex-direction: row; + justify-content: center; background-color: var(--surface0); - margin-bottom: 2rem; + margin-bottom: 1rem; + border-bottom: 1px solid var(--surface1); +} + +#profile-header { + min-width: 0; + max-width: 80rem; + flex-grow: 1; } #profile-header .banner { width: 100%; - min-height: 20rem; + min-height: 30rem; aspect-ratio: 5; } +#profile-header .banner img { + height: 100%; + width: 100%; + object-fit: cover; +} + #profile-header .info .pfp-wrapper .pfp, #profile-header .info .pfp-wrapper .pfp img { height: 12.5rem; @@ -32,7 +49,7 @@ border-radius: 100%; position: absolute; top: -2.5rem; - left: 2rem; + left: 1rem; } #profile-header .info .content { @@ -65,13 +82,27 @@ text-align: center; } -#tab-posts, -#post-container { - width: 40rem; +.tab { + max-width: 80rem; + width: 100%; margin-left: auto; margin-right: auto; + padding: 0 1rem; + margin-bottom: 1rem; +} + +#post-container { + max-width: 40rem; + width: 100%; + margin-left: auto; + margin-right: auto; + margin-bottom: -1rem; } #post-container .post { margin-bottom: 1rem; } + +td:nth-child(1) { + padding-right: 2rem; +} diff --git a/src/public/js/lib.js b/src/public/js/lib.js index 19019ad..95f83b7 100644 --- a/src/public/js/lib.js +++ b/src/public/js/lib.js @@ -13,7 +13,8 @@ var $$ = (selector) => { 'click', 'submit', 'each', - 'error' + 'error', + 'one' ]; let vtable = {}; @@ -46,9 +47,9 @@ var $$ = (selector) => { let config = { childList: true, subtree: true }; let MutationObserver = window.MutationObserver; let observer = new MutationObserver(onMutate); + observer.observe(document.body, config); }); - }; } @@ -121,3 +122,14 @@ $.ajaxSetup({ })(), error: errorToastAjax }) + +var onImgLoad = function(me) { + me.parentElement.classList.remove('image-loading'); + me.parentElement.classList.add('image-loaded'); +} + +var onImgError = function(me) { + me.parentElement.classList.remove('image-loading'); + me.parentElement.classList.add('image-loaded'); + me.remove(); +} diff --git a/src/public/js/post.js b/src/public/js/post.js index 38bbb78..3c03bae 100644 --- a/src/public/js/post.js +++ b/src/public/js/post.js @@ -45,8 +45,15 @@ $$('#action-load-posts').on('click', function() { let pageSize = Number(me.attr('pageSize')); let postCount = Number(me.attr('postCount')); let postMax = Number(me.attr('postMax')); + let filterUid = me.attr('userId'); let url = '/_util/post/posts?page=' + page + '&max=' + postMax; + + if (!isNaN(filterUid)) { + console.log(filterUid); + url += '&user_id=' + filterUid; + } + $.get(url, function (data) { if (data === '') { me.remove(); @@ -101,13 +108,27 @@ $$('.action-like').on('click', function() { let like_id = me.attr('likeId'); let post_id = me.attr('postId'); + const updateLiked = (liked) => { + let post = me.closest('.post'); + let likes = post.find('.likes'); + let count = likes.find('.count'); + + let c = Number(count[0].textContent); + c += liked ? 1 : -1; + count[0].textContent = c; + } + const onPatch = () => { + let liked = me.hasClass('btn-blue'); me.toggleClass('btn-blue'); + updateLiked(!liked); } const onPost = (data) => { + let liked = me.hasClass('btn-blue'); me.attr('likeId', data[0].id + ''); me.toggleClass('btn-blue'); + updateLiked(!liked); } if (like_id) { diff --git a/src/web/_controller/_util/post.php b/src/web/_controller/_util/post.php index 4da2671..5346497 100644 --- a/src/web/_controller/_util/post.php +++ b/src/web/_controller/_util/post.php @@ -79,9 +79,9 @@ class Post_controller extends Controller { ->where('p.id')->le($max); } - if ($uid) { + if ($filter_uid) { $query = $query - ->where('p.user_id')->eq($uid); + ->where('p.user_id')->eq($filter_uid); } $posts = $query @@ -106,9 +106,9 @@ class Post_controller extends Controller { ->select('COUNT(p.id) as pc') ->from('api.post p'); - if ($uid) { + if ($filter_uid) { $query = $query - ->where('p.user_id')->eq($uid); + ->where('p.user_id')->eq($filter_uid); } $pc = $query diff --git a/src/web/_controller/apps/people.php b/src/web/_controller/apps/people.php index 19910ac..86da3b3 100644 --- a/src/web/_controller/apps/people.php +++ b/src/web/_controller/apps/people.php @@ -17,10 +17,17 @@ class People_controller extends Controller { parent::index(); $data = $this->people_model->get_data(); $this->view('header', $data); + $this->view('apps/people/header', $data); $this->view('apps/people/main', $data); + $this->view('apps/people/footer', $data); $this->view('footer', $data); } + public function content(): void { + $data = $this->people_model->get_data(); + $this->view('apps/people/main', $data); + } + /** * @return array */ diff --git a/src/web/_controller/apps/profile.php b/src/web/_controller/apps/profile.php index aaed348..3bc9a91 100644 --- a/src/web/_controller/apps/profile.php +++ b/src/web/_controller/apps/profile.php @@ -7,12 +7,16 @@ class Profile_controller extends Controller { // the format model protected $format_model; - // the post model + // the post controller protected $post_controller; + // the people controller + protected $people_controller; + function __construct($load) { parent::__construct($load); $this->profile_model = $this->load->model('apps/profile'); + $this->people_controller = $this->load->controller('apps/people'); $this->format_model = $this->load->model('format'); $this->post_controller = $this->load->controller('_util/post'); } diff --git a/src/web/_model/apps/people.php b/src/web/_model/apps/people.php index 1bb110f..ade59d3 100644 --- a/src/web/_model/apps/people.php +++ b/src/web/_model/apps/people.php @@ -7,40 +7,32 @@ class People_model extends Model { parent::__construct($load); $this->request_model = $this->load->model('request'); } - - private function get_filted_query($select) { - $filter_username = $this->request_model->get_str('filter_username', FALSE); - $filter_fisrt_name = $this->request_model->get_str('filter_first_name', FALSE); - $filter_last_name = $this->request_model->get_str('filter_last_name', FALSE); - $filter_email = $this->request_model->get_str('filter_email', FALSE); - $max = $this->request_model->get_int('max', FALSE); + /** + * @param mixed $select + */ + private function get_filted_query($select): DatabaseQuery { + $filter_type = $this->request_model->get_str('filter', FALSE); + $filter_uid = $this->request_model->get_int('uid', FALSE); + $max = $this->request_model->get_int('max', FALSE); $query = $this->db ->select($select) ->from('api.user u'); - if ($filter_username) { - $query = $query - ->where('u.username') - ->like('%' . $filter_username . '%'); - } + if ($filter_type && $filter_uid) { + switch ($filter_type) { + case 'follower': { + $query = $query + ->join('admin.follow f', 'f.follower_id = u.id AND f.followee_id', 'INNER') + ->eq($filter_uid); + } break; - if ($filter_fisrt_name) { - $query = $query - ->where('u.first_name') - ->like('%'. $filter_fisrt_name . '%'); - } - - if ($filter_last_name) { - $query = $query - ->where('u.last_name') - ->like('%' . $filter_last_name . '%'); - } - - if ($filter_email) { - $query = $query - ->where('u.email') - ->like('%' . $filter_email . '%'); + case 'followee': { + $query = $query + ->join('admin.follow f', 'f.followee_id = u.id AND f.follower_id', 'INNER') + ->eq($filter_uid); + } break; + } } if ($max) { @@ -52,12 +44,15 @@ class People_model extends Model { return $query; } - public function get_users(): array { + /** + * @return array + */ + public function get_users(): array { $page = $this->request_model->get_int('page', 0); $page_size = 24; $offset = $page_size * $page; - $users = $this->get_filted_query('*') + $users = $this->get_filted_query('u.*') ->order_by('u.id', 'DESC') ->offset($offset) ->limit($page_size) @@ -72,11 +67,16 @@ class People_model extends Model { $max = max($max, $user['id']); } + $filter_type = $this->request_model->get_str('filter', FALSE); + $filter_uid = $this->request_model->get_int('uid', FALSE); + return array( 'users' => $users, 'count' => $count, 'page_size' => $page_size, - 'max_id' => $max + 'max_id' => $max, + 'filter_type' => $filter_type || '', + 'filter_uid' => $filter_uid || '' ); } diff --git a/src/web/_views/apps/home/main.php b/src/web/_views/apps/home/main.php index 29bf7c3..735e3d8 100644 --- a/src/web/_views/apps/home/main.php +++ b/src/web/_views/apps/home/main.php @@ -4,7 +4,7 @@
- view('template/pfp', array('user' => $self))?> + - diff --git a/src/web/_views/apps/people/header.php b/src/web/_views/apps/people/header.php new file mode 100644 index 0000000..7f3d95b --- /dev/null +++ b/src/web/_views/apps/people/header.php @@ -0,0 +1,6 @@ + + +
+

+

+
diff --git a/src/web/_views/apps/people/main.php b/src/web/_views/apps/people/main.php index 171f25c..deec4c2 100644 --- a/src/web/_views/apps/people/main.php +++ b/src/web/_views/apps/people/main.php @@ -1,67 +1,72 @@ -
-

-

-
-
- people(); - ?> -
- - = $page_size && $page_size < $total): ?> - $loaded, - 'pageSize' => $page_size, - 'userCount' => $total, - 'userMax' => $max - ) - )?> - - +
+people(); +?>
+ += $page_size && $page_size < $total): ?> + $loaded, + 'pageSize' => $page_size, + 'userCount' => $total, + 'userMax' => $max, + 'filterUid' => $filter_uid, + 'filterType' => $filer_type + ) + )?> + + diff --git a/src/web/_views/apps/profile/main.php b/src/web/_views/apps/profile/main.php index afa45bc..e3d65b5 100644 --- a/src/web/_views/apps/profile/main.php +++ b/src/web/_views/apps/profile/main.php @@ -1,37 +1,158 @@ + +
-
- -
-
- view('template/pfp', array('user' => $user)); ?> -
-
- format_model->name($user)?> - format_model->date($user['created'])?> +
+
+ +
+
+ +
+
+ format_model->name($user)?> + + 0): ?> +
+ + + +
+
+
+ + + +
-
-
- - -
-
+
post_controller->index(); ?>
+
+

+ + + + + + + + + + + + + + + + + + + + + +
+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ people_controller->content(); + ?> +
+
+ people_controller->content(); + ?> +
+
+
diff --git a/src/web/_views/header.php b/src/web/_views/header.php index 8a0333e..f1aef01 100644 --- a/src/web/_views/header.php +++ b/src/web/_views/header.php @@ -11,7 +11,7 @@