diff --git a/server/migrations/2020-07-08-202609_add_creator_published/down.sql b/server/migrations/2020-07-08-202609_add_creator_published/down.sql new file mode 100644 index 000000000..b8e4452e3 --- /dev/null +++ b/server/migrations/2020-07-08-202609_add_creator_published/down.sql @@ -0,0 +1,388 @@ +drop view user_mention_view; +drop view reply_fast_view; +drop view comment_fast_view; +drop view comment_view; + +drop view user_mention_fast_view; +drop table comment_aggregates_fast; +drop view comment_aggregates_view; + +create view comment_aggregates_view as +select + ct.*, + -- community details + p.community_id, + c.actor_id as community_actor_id, + c."local" as community_local, + c."name" as community_name, + -- creator details + u.banned as banned, + coalesce(cb.id, 0)::bool as banned_from_community, + u.actor_id as creator_actor_id, + u.local as creator_local, + u.name as creator_name, + u.avatar as creator_avatar, + -- score details + coalesce(cl.total, 0) as score, + coalesce(cl.up, 0) as upvotes, + coalesce(cl.down, 0) as downvotes, + hot_rank(coalesce(cl.total, 0), ct.published) as hot_rank +from comment ct +left join post p on ct.post_id = p.id +left join community c on p.community_id = c.id +left join user_ u on ct.creator_id = u.id +left join community_user_ban cb on ct.creator_id = cb.user_id and p.id = ct.post_id and p.community_id = cb.community_id +left join ( + select + l.comment_id as id, + sum(l.score) as total, + count(case when l.score = 1 then 1 else null end) as up, + count(case when l.score = -1 then 1 else null end) as down + from comment_like l + group by comment_id +) as cl on cl.id = ct.id; + +create or replace view comment_view as ( +select + cav.*, + us.user_id as user_id, + us.my_vote as my_vote, + us.is_subbed::bool as subscribed, + us.is_saved::bool as saved +from comment_aggregates_view cav +cross join lateral ( + select + u.id as user_id, + coalesce(cl.score, 0) as my_vote, + coalesce(cf.id, 0) as is_subbed, + coalesce(cs.id, 0) as is_saved + from user_ u + left join comment_like cl on u.id = cl.user_id and cav.id = cl.comment_id + left join comment_saved cs on u.id = cs.user_id and cs.comment_id = cav.id + left join community_follower cf on u.id = cf.user_id and cav.community_id = cf.community_id +) as us + +union all + +select + cav.*, + null as user_id, + null as my_vote, + null as subscribed, + null as saved +from comment_aggregates_view cav +); + +create table comment_aggregates_fast as select * from comment_aggregates_view; +alter table comment_aggregates_fast add primary key (id); + +create view comment_fast_view as +select + cav.*, + us.user_id as user_id, + us.my_vote as my_vote, + us.is_subbed::bool as subscribed, + us.is_saved::bool as saved +from comment_aggregates_fast cav +cross join lateral ( + select + u.id as user_id, + coalesce(cl.score, 0) as my_vote, + coalesce(cf.id, 0) as is_subbed, + coalesce(cs.id, 0) as is_saved + from user_ u + left join comment_like cl on u.id = cl.user_id and cav.id = cl.comment_id + left join comment_saved cs on u.id = cs.user_id and cs.comment_id = cav.id + left join community_follower cf on u.id = cf.user_id and cav.community_id = cf.community_id +) as us + +union all + +select + cav.*, + null as user_id, + null as my_vote, + null as subscribed, + null as saved +from comment_aggregates_fast cav; + +create view user_mention_view as +select + c.id, + um.id as user_mention_id, + c.creator_id, + c.creator_actor_id, + c.creator_local, + c.post_id, + c.parent_id, + c.content, + c.removed, + um.read, + c.published, + c.updated, + c.deleted, + c.community_id, + c.community_actor_id, + c.community_local, + c.community_name, + c.banned, + c.banned_from_community, + c.creator_name, + c.creator_avatar, + c.score, + c.upvotes, + c.downvotes, + c.hot_rank, + c.user_id, + c.my_vote, + c.saved, + um.recipient_id, + (select actor_id from user_ u where u.id = um.recipient_id) as recipient_actor_id, + (select local from user_ u where u.id = um.recipient_id) as recipient_local +from user_mention um, comment_view c +where um.comment_id = c.id; + +create view user_mention_fast_view as +select + ac.id, + um.id as user_mention_id, + ac.creator_id, + ac.creator_actor_id, + ac.creator_local, + ac.post_id, + ac.parent_id, + ac.content, + ac.removed, + um.read, + ac.published, + ac.updated, + ac.deleted, + ac.community_id, + ac.community_actor_id, + ac.community_local, + ac.community_name, + ac.banned, + ac.banned_from_community, + ac.creator_name, + ac.creator_avatar, + ac.score, + ac.upvotes, + ac.downvotes, + ac.hot_rank, + u.id as user_id, + coalesce(cl.score, 0) as my_vote, + (select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved, + um.recipient_id, + (select actor_id from user_ u where u.id = um.recipient_id) as recipient_actor_id, + (select local from user_ u where u.id = um.recipient_id) as recipient_local +from user_ u +cross join ( + select + ca.* + from comment_aggregates_fast ca +) ac +left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id +left join user_mention um on um.comment_id = ac.id + +union all + +select + ac.id, + um.id as user_mention_id, + ac.creator_id, + ac.creator_actor_id, + ac.creator_local, + ac.post_id, + ac.parent_id, + ac.content, + ac.removed, + um.read, + ac.published, + ac.updated, + ac.deleted, + ac.community_id, + ac.community_actor_id, + ac.community_local, + ac.community_name, + ac.banned, + ac.banned_from_community, + ac.creator_name, + ac.creator_avatar, + ac.score, + ac.upvotes, + ac.downvotes, + ac.hot_rank, + null as user_id, + null as my_vote, + null as saved, + um.recipient_id, + (select actor_id from user_ u where u.id = um.recipient_id) as recipient_actor_id, + (select local from user_ u where u.id = um.recipient_id) as recipient_local +from comment_aggregates_fast ac +left join user_mention um on um.comment_id = ac.id +; + +-- Do the reply_view referencing the comment_fast_view +create view reply_fast_view as +with closereply as ( + select + c2.id, + c2.creator_id as sender_id, + c.creator_id as recipient_id + from comment c + inner join comment c2 on c.id = c2.parent_id + where c2.creator_id != c.creator_id + -- Do union where post is null + union + select + c.id, + c.creator_id as sender_id, + p.creator_id as recipient_id + from comment c, post p + where c.post_id = p.id and c.parent_id is null and c.creator_id != p.creator_id +) +select cv.*, +closereply.recipient_id +from comment_fast_view cv, closereply +where closereply.id = cv.id +; + +-- add creator_published to the post view +drop view post_fast_view; +drop table post_aggregates_fast; +drop view post_view; +drop view post_aggregates_view; + +create view post_aggregates_view as +select + p.*, + -- creator details + u.actor_id as creator_actor_id, + u."local" as creator_local, + u."name" as creator_name, + u.avatar as creator_avatar, + u.banned as banned, + cb.id::bool as banned_from_community, + -- community details + c.actor_id as community_actor_id, + c."local" as community_local, + c."name" as community_name, + c.removed as community_removed, + c.deleted as community_deleted, + c.nsfw as community_nsfw, + -- post score data/comment count + coalesce(ct.comments, 0) as number_of_comments, + coalesce(pl.score, 0) as score, + coalesce(pl.upvotes, 0) as upvotes, + coalesce(pl.downvotes, 0) as downvotes, + hot_rank( + coalesce(pl.score , 0), ( + case + when (p.published < ('now'::timestamp - '1 month'::interval)) + then p.published + else greatest(ct.recent_comment_time, p.published) + end + ) + ) as hot_rank, + ( + case + when (p.published < ('now'::timestamp - '1 month'::interval)) + then p.published + else greatest(ct.recent_comment_time, p.published) + end + ) as newest_activity_time +from post p +left join user_ u on p.creator_id = u.id +left join community_user_ban cb on p.creator_id = cb.user_id and p.community_id = cb.community_id +left join community c on p.community_id = c.id +left join ( + select + post_id, + count(*) as comments, + max(published) as recent_comment_time + from comment + group by post_id +) ct on ct.post_id = p.id +left join ( + select + post_id, + sum(score) as score, + sum(score) filter (where score = 1) as upvotes, + -sum(score) filter (where score = -1) as downvotes + from post_like + group by post_id +) pl on pl.post_id = p.id +order by p.id; + +create view post_view as +select + pav.*, + us.id as user_id, + us.user_vote as my_vote, + us.is_subbed::bool as subscribed, + us.is_read::bool as read, + us.is_saved::bool as saved +from post_aggregates_view pav +cross join lateral ( + select + u.id, + coalesce(cf.community_id, 0) as is_subbed, + coalesce(pr.post_id, 0) as is_read, + coalesce(ps.post_id, 0) as is_saved, + coalesce(pl.score, 0) as user_vote + from user_ u + left join community_user_ban cb on u.id = cb.user_id and cb.community_id = pav.community_id + left join community_follower cf on u.id = cf.user_id and cf.community_id = pav.community_id + left join post_read pr on u.id = pr.user_id and pr.post_id = pav.id + left join post_saved ps on u.id = ps.user_id and ps.post_id = pav.id + left join post_like pl on u.id = pl.user_id and pav.id = pl.post_id +) as us + +union all + +select +pav.*, +null as user_id, +null as my_vote, +null as subscribed, +null as read, +null as saved +from post_aggregates_view pav; + +create table post_aggregates_fast as select * from post_aggregates_view; +alter table post_aggregates_fast add primary key (id); + +create view post_fast_view as +select + pav.*, + us.id as user_id, + us.user_vote as my_vote, + us.is_subbed::bool as subscribed, + us.is_read::bool as read, + us.is_saved::bool as saved +from post_aggregates_fast pav +cross join lateral ( + select + u.id, + coalesce(cf.community_id, 0) as is_subbed, + coalesce(pr.post_id, 0) as is_read, + coalesce(ps.post_id, 0) as is_saved, + coalesce(pl.score, 0) as user_vote + from user_ u + left join community_user_ban cb on u.id = cb.user_id and cb.community_id = pav.community_id + left join community_follower cf on u.id = cf.user_id and cf.community_id = pav.community_id + left join post_read pr on u.id = pr.user_id and pr.post_id = pav.id + left join post_saved ps on u.id = ps.user_id and ps.post_id = pav.id + left join post_like pl on u.id = pl.user_id and pav.id = pl.post_id +) as us + +union all + +select +pav.*, +null as user_id, +null as my_vote, +null as subscribed, +null as read, +null as saved +from post_aggregates_fast pav; \ No newline at end of file diff --git a/server/migrations/2020-07-08-202609_add_creator_published/up.sql b/server/migrations/2020-07-08-202609_add_creator_published/up.sql new file mode 100644 index 000000000..1f2b59ea9 --- /dev/null +++ b/server/migrations/2020-07-08-202609_add_creator_published/up.sql @@ -0,0 +1,390 @@ +drop view user_mention_view; +drop view reply_fast_view; +drop view comment_fast_view; +drop view comment_view; + +drop view user_mention_fast_view; +drop table comment_aggregates_fast; +drop view comment_aggregates_view; + +create view comment_aggregates_view as +select + ct.*, + -- community details + p.community_id, + c.actor_id as community_actor_id, + c."local" as community_local, + c."name" as community_name, + -- creator details + u.banned as banned, + coalesce(cb.id, 0)::bool as banned_from_community, + u.actor_id as creator_actor_id, + u.local as creator_local, + u.name as creator_name, + u.published as creator_published, + u.avatar as creator_avatar, + -- score details + coalesce(cl.total, 0) as score, + coalesce(cl.up, 0) as upvotes, + coalesce(cl.down, 0) as downvotes, + hot_rank(coalesce(cl.total, 0), ct.published) as hot_rank +from comment ct +left join post p on ct.post_id = p.id +left join community c on p.community_id = c.id +left join user_ u on ct.creator_id = u.id +left join community_user_ban cb on ct.creator_id = cb.user_id and p.id = ct.post_id and p.community_id = cb.community_id +left join ( + select + l.comment_id as id, + sum(l.score) as total, + count(case when l.score = 1 then 1 else null end) as up, + count(case when l.score = -1 then 1 else null end) as down + from comment_like l + group by comment_id +) as cl on cl.id = ct.id; + +create or replace view comment_view as ( +select + cav.*, + us.user_id as user_id, + us.my_vote as my_vote, + us.is_subbed::bool as subscribed, + us.is_saved::bool as saved +from comment_aggregates_view cav +cross join lateral ( + select + u.id as user_id, + coalesce(cl.score, 0) as my_vote, + coalesce(cf.id, 0) as is_subbed, + coalesce(cs.id, 0) as is_saved + from user_ u + left join comment_like cl on u.id = cl.user_id and cav.id = cl.comment_id + left join comment_saved cs on u.id = cs.user_id and cs.comment_id = cav.id + left join community_follower cf on u.id = cf.user_id and cav.community_id = cf.community_id +) as us + +union all + +select + cav.*, + null as user_id, + null as my_vote, + null as subscribed, + null as saved +from comment_aggregates_view cav +); + +create table comment_aggregates_fast as select * from comment_aggregates_view; +alter table comment_aggregates_fast add primary key (id); + +create view comment_fast_view as +select + cav.*, + us.user_id as user_id, + us.my_vote as my_vote, + us.is_subbed::bool as subscribed, + us.is_saved::bool as saved +from comment_aggregates_fast cav +cross join lateral ( + select + u.id as user_id, + coalesce(cl.score, 0) as my_vote, + coalesce(cf.id, 0) as is_subbed, + coalesce(cs.id, 0) as is_saved + from user_ u + left join comment_like cl on u.id = cl.user_id and cav.id = cl.comment_id + left join comment_saved cs on u.id = cs.user_id and cs.comment_id = cav.id + left join community_follower cf on u.id = cf.user_id and cav.community_id = cf.community_id +) as us + +union all + +select + cav.*, + null as user_id, + null as my_vote, + null as subscribed, + null as saved +from comment_aggregates_fast cav; + +create view user_mention_view as +select + c.id, + um.id as user_mention_id, + c.creator_id, + c.creator_actor_id, + c.creator_local, + c.post_id, + c.parent_id, + c.content, + c.removed, + um.read, + c.published, + c.updated, + c.deleted, + c.community_id, + c.community_actor_id, + c.community_local, + c.community_name, + c.banned, + c.banned_from_community, + c.creator_name, + c.creator_avatar, + c.score, + c.upvotes, + c.downvotes, + c.hot_rank, + c.user_id, + c.my_vote, + c.saved, + um.recipient_id, + (select actor_id from user_ u where u.id = um.recipient_id) as recipient_actor_id, + (select local from user_ u where u.id = um.recipient_id) as recipient_local +from user_mention um, comment_view c +where um.comment_id = c.id; + +create view user_mention_fast_view as +select + ac.id, + um.id as user_mention_id, + ac.creator_id, + ac.creator_actor_id, + ac.creator_local, + ac.post_id, + ac.parent_id, + ac.content, + ac.removed, + um.read, + ac.published, + ac.updated, + ac.deleted, + ac.community_id, + ac.community_actor_id, + ac.community_local, + ac.community_name, + ac.banned, + ac.banned_from_community, + ac.creator_name, + ac.creator_avatar, + ac.score, + ac.upvotes, + ac.downvotes, + ac.hot_rank, + u.id as user_id, + coalesce(cl.score, 0) as my_vote, + (select cs.id::bool from comment_saved cs where u.id = cs.user_id and cs.comment_id = ac.id) as saved, + um.recipient_id, + (select actor_id from user_ u where u.id = um.recipient_id) as recipient_actor_id, + (select local from user_ u where u.id = um.recipient_id) as recipient_local +from user_ u +cross join ( + select + ca.* + from comment_aggregates_fast ca +) ac +left join comment_like cl on u.id = cl.user_id and ac.id = cl.comment_id +left join user_mention um on um.comment_id = ac.id + +union all + +select + ac.id, + um.id as user_mention_id, + ac.creator_id, + ac.creator_actor_id, + ac.creator_local, + ac.post_id, + ac.parent_id, + ac.content, + ac.removed, + um.read, + ac.published, + ac.updated, + ac.deleted, + ac.community_id, + ac.community_actor_id, + ac.community_local, + ac.community_name, + ac.banned, + ac.banned_from_community, + ac.creator_name, + ac.creator_avatar, + ac.score, + ac.upvotes, + ac.downvotes, + ac.hot_rank, + null as user_id, + null as my_vote, + null as saved, + um.recipient_id, + (select actor_id from user_ u where u.id = um.recipient_id) as recipient_actor_id, + (select local from user_ u where u.id = um.recipient_id) as recipient_local +from comment_aggregates_fast ac +left join user_mention um on um.comment_id = ac.id +; + +-- Do the reply_view referencing the comment_fast_view +create view reply_fast_view as +with closereply as ( + select + c2.id, + c2.creator_id as sender_id, + c.creator_id as recipient_id + from comment c + inner join comment c2 on c.id = c2.parent_id + where c2.creator_id != c.creator_id + -- Do union where post is null + union + select + c.id, + c.creator_id as sender_id, + p.creator_id as recipient_id + from comment c, post p + where c.post_id = p.id and c.parent_id is null and c.creator_id != p.creator_id +) +select cv.*, +closereply.recipient_id +from comment_fast_view cv, closereply +where closereply.id = cv.id +; + +-- add creator_published to the post view +drop view post_fast_view; +drop table post_aggregates_fast; +drop view post_view; +drop view post_aggregates_view; + +create view post_aggregates_view as +select + p.*, + -- creator details + u.actor_id as creator_actor_id, + u."local" as creator_local, + u."name" as creator_name, + u.published as creator_published, + u.avatar as creator_avatar, + u.banned as banned, + cb.id::bool as banned_from_community, + -- community details + c.actor_id as community_actor_id, + c."local" as community_local, + c."name" as community_name, + c.removed as community_removed, + c.deleted as community_deleted, + c.nsfw as community_nsfw, + -- post score data/comment count + coalesce(ct.comments, 0) as number_of_comments, + coalesce(pl.score, 0) as score, + coalesce(pl.upvotes, 0) as upvotes, + coalesce(pl.downvotes, 0) as downvotes, + hot_rank( + coalesce(pl.score , 0), ( + case + when (p.published < ('now'::timestamp - '1 month'::interval)) + then p.published + else greatest(ct.recent_comment_time, p.published) + end + ) + ) as hot_rank, + ( + case + when (p.published < ('now'::timestamp - '1 month'::interval)) + then p.published + else greatest(ct.recent_comment_time, p.published) + end + ) as newest_activity_time +from post p +left join user_ u on p.creator_id = u.id +left join community_user_ban cb on p.creator_id = cb.user_id and p.community_id = cb.community_id +left join community c on p.community_id = c.id +left join ( + select + post_id, + count(*) as comments, + max(published) as recent_comment_time + from comment + group by post_id +) ct on ct.post_id = p.id +left join ( + select + post_id, + sum(score) as score, + sum(score) filter (where score = 1) as upvotes, + -sum(score) filter (where score = -1) as downvotes + from post_like + group by post_id +) pl on pl.post_id = p.id +order by p.id; + +create view post_view as +select + pav.*, + us.id as user_id, + us.user_vote as my_vote, + us.is_subbed::bool as subscribed, + us.is_read::bool as read, + us.is_saved::bool as saved +from post_aggregates_view pav +cross join lateral ( + select + u.id, + coalesce(cf.community_id, 0) as is_subbed, + coalesce(pr.post_id, 0) as is_read, + coalesce(ps.post_id, 0) as is_saved, + coalesce(pl.score, 0) as user_vote + from user_ u + left join community_user_ban cb on u.id = cb.user_id and cb.community_id = pav.community_id + left join community_follower cf on u.id = cf.user_id and cf.community_id = pav.community_id + left join post_read pr on u.id = pr.user_id and pr.post_id = pav.id + left join post_saved ps on u.id = ps.user_id and ps.post_id = pav.id + left join post_like pl on u.id = pl.user_id and pav.id = pl.post_id +) as us + +union all + +select +pav.*, +null as user_id, +null as my_vote, +null as subscribed, +null as read, +null as saved +from post_aggregates_view pav; + +create table post_aggregates_fast as select * from post_aggregates_view; +alter table post_aggregates_fast add primary key (id); + +create view post_fast_view as +select + pav.*, + us.id as user_id, + us.user_vote as my_vote, + us.is_subbed::bool as subscribed, + us.is_read::bool as read, + us.is_saved::bool as saved +from post_aggregates_fast pav +cross join lateral ( + select + u.id, + coalesce(cf.community_id, 0) as is_subbed, + coalesce(pr.post_id, 0) as is_read, + coalesce(ps.post_id, 0) as is_saved, + coalesce(pl.score, 0) as user_vote + from user_ u + left join community_user_ban cb on u.id = cb.user_id and cb.community_id = pav.community_id + left join community_follower cf on u.id = cf.user_id and cf.community_id = pav.community_id + left join post_read pr on u.id = pr.user_id and pr.post_id = pav.id + left join post_saved ps on u.id = ps.user_id and ps.post_id = pav.id + left join post_like pl on u.id = pl.user_id and pav.id = pl.post_id +) as us + +union all + +select +pav.*, +null as user_id, +null as my_vote, +null as subscribed, +null as read, +null as saved +from post_aggregates_fast pav; \ No newline at end of file diff --git a/server/src/api/user.rs b/server/src/api/user.rs index 9b72a9199..1284c6608 100644 --- a/server/src/api/user.rs +++ b/server/src/api/user.rs @@ -451,6 +451,11 @@ impl Perform for Oper { None => read_user.email, }; + let avatar = match &data.avatar { + Some(avatar) => Some(avatar.to_owned()), + None => read_user.avatar, + }; + let password_encrypted = match &data.new_password { Some(new_password) => { match &data.new_password_verify { @@ -488,7 +493,7 @@ impl Perform for Oper { name: read_user.name, email, matrix_user_id: data.matrix_user_id.to_owned(), - avatar: data.avatar.to_owned(), + avatar, password_encrypted, preferred_username: read_user.preferred_username, updated: Some(naive_now()), diff --git a/server/src/db/comment_view.rs b/server/src/db/comment_view.rs index d1b27a3c8..7c853a817 100644 --- a/server/src/db/comment_view.rs +++ b/server/src/db/comment_view.rs @@ -27,6 +27,7 @@ table! { creator_actor_id -> Text, creator_local -> Bool, creator_name -> Varchar, + creator_published -> Timestamp, creator_avatar -> Nullable, score -> BigInt, upvotes -> BigInt, @@ -62,6 +63,7 @@ table! { creator_actor_id -> Text, creator_local -> Bool, creator_name -> Varchar, + creator_published -> Timestamp, creator_avatar -> Nullable, score -> BigInt, upvotes -> BigInt, @@ -100,6 +102,7 @@ pub struct CommentView { pub creator_actor_id: String, pub creator_local: bool, pub creator_name: String, + pub creator_published: chrono::NaiveDateTime, pub creator_avatar: Option, pub score: i64, pub upvotes: i64, @@ -314,6 +317,7 @@ table! { creator_local -> Bool, creator_name -> Varchar, creator_avatar -> Nullable, + creator_published -> Timestamp, score -> BigInt, upvotes -> BigInt, downvotes -> BigInt, @@ -353,6 +357,7 @@ pub struct ReplyView { pub creator_local: bool, pub creator_name: String, pub creator_avatar: Option, + pub creator_published: chrono::NaiveDateTime, pub score: i64, pub upvotes: i64, pub downvotes: i64, @@ -576,6 +581,7 @@ mod tests { published: inserted_comment.published, updated: None, creator_name: inserted_user.name.to_owned(), + creator_published: inserted_user.published, creator_avatar: None, score: 1, downvotes: 0, @@ -609,6 +615,7 @@ mod tests { published: inserted_comment.published, updated: None, creator_name: inserted_user.name.to_owned(), + creator_published: inserted_user.published, creator_avatar: None, score: 1, downvotes: 0, diff --git a/server/src/db/post_view.rs b/server/src/db/post_view.rs index 808cf28c4..cda5cecf0 100644 --- a/server/src/db/post_view.rs +++ b/server/src/db/post_view.rs @@ -28,6 +28,7 @@ table! { creator_actor_id -> Text, creator_local -> Bool, creator_name -> Varchar, + creator_published -> Timestamp, creator_avatar -> Nullable, banned -> Bool, banned_from_community -> Bool, @@ -75,6 +76,7 @@ table! { creator_actor_id -> Text, creator_local -> Bool, creator_name -> Varchar, + creator_published -> Timestamp, creator_avatar -> Nullable, banned -> Bool, banned_from_community -> Bool, @@ -125,6 +127,7 @@ pub struct PostView { pub creator_actor_id: String, pub creator_local: bool, pub creator_name: String, + pub creator_published: chrono::NaiveDateTime, pub creator_avatar: Option, pub banned: bool, pub banned_from_community: bool, @@ -499,6 +502,7 @@ mod tests { body: None, creator_id: inserted_user.id, creator_name: user_name.to_owned(), + creator_published: inserted_user.published, creator_avatar: None, banned: false, banned_from_community: false, @@ -548,6 +552,7 @@ mod tests { stickied: false, creator_id: inserted_user.id, creator_name: user_name, + creator_published: inserted_user.published, creator_avatar: None, banned: false, banned_from_community: false, diff --git a/server/src/schema.rs b/server/src/schema.rs index 0367c7506..18a522df8 100644 --- a/server/src/schema.rs +++ b/server/src/schema.rs @@ -56,6 +56,7 @@ table! { creator_actor_id -> Nullable, creator_local -> Nullable, creator_name -> Nullable, + creator_published -> Nullable, creator_avatar -> Nullable, score -> Nullable, upvotes -> Nullable, @@ -317,6 +318,7 @@ table! { creator_actor_id -> Nullable, creator_local -> Nullable, creator_name -> Nullable, + creator_published -> Nullable, creator_avatar -> Nullable, banned -> Nullable, banned_from_community -> Nullable, diff --git a/ui/src/components/cake-day.tsx b/ui/src/components/cake-day.tsx new file mode 100644 index 000000000..f28be33c2 --- /dev/null +++ b/ui/src/components/cake-day.tsx @@ -0,0 +1,25 @@ +import { Component } from 'inferno'; +import { i18n } from '../i18next'; + +interface CakeDayProps { + creatorName: string; +} + +export class CakeDay extends Component { + render() { + return ( +
+ + + +
+ ); + } + + cakeDayTippy(): string { + return i18n.t('cake_day_info', { creator_name: this.props.creatorName }); + } +} diff --git a/ui/src/components/comment-form.tsx b/ui/src/components/comment-form.tsx index 22f871d22..04720cbb0 100644 --- a/ui/src/components/comment-form.tsx +++ b/ui/src/components/comment-form.tsx @@ -1,4 +1,5 @@ import { Component, linkEvent } from 'inferno'; +import { Link } from 'inferno-router'; import { Subscription } from 'rxjs'; import { retryWhen, delay, take } from 'rxjs/operators'; import { Prompt } from 'inferno-router'; @@ -24,6 +25,7 @@ import autosize from 'autosize'; import Tribute from 'tributejs/src/Tribute.js'; import emojiShortName from 'emoji-short-name'; import { i18n } from '../i18next'; +import { T } from 'inferno-i18next'; interface CommentFormProps { postId?: number; @@ -97,29 +99,31 @@ export class CommentForm extends Component { componentDidMount() { let textarea: any = document.getElementById(this.id); - autosize(textarea); - this.tribute.attach(textarea); - textarea.addEventListener('tribute-replaced', () => { - this.state.commentForm.content = textarea.value; - this.setState(this.state); - autosize.update(textarea); - }); + if (textarea) { + autosize(textarea); + this.tribute.attach(textarea); + textarea.addEventListener('tribute-replaced', () => { + this.state.commentForm.content = textarea.value; + this.setState(this.state); + autosize.update(textarea); + }); - // Quoting of selected text - let selectedText = window.getSelection().toString(); - if (selectedText) { - let quotedText = - selectedText - .split('\n') - .map(t => `> ${t}`) - .join('\n') + '\n\n'; - this.state.commentForm.content = quotedText; - this.setState(this.state); - // Not sure why this needs a delay - setTimeout(() => autosize.update(textarea), 10); + // Quoting of selected text + let selectedText = window.getSelection().toString(); + if (selectedText) { + let quotedText = + selectedText + .split('\n') + .map(t => `> ${t}`) + .join('\n') + '\n\n'; + this.state.commentForm.content = quotedText; + this.setState(this.state); + // Not sure why this needs a delay + setTimeout(() => autosize.update(textarea), 10); + } + + textarea.focus(); } - - textarea.focus(); } componentDidUpdate() { @@ -142,106 +146,119 @@ export class CommentForm extends Component { when={this.state.commentForm.content} message={i18n.t('block_leaving')} /> -
-
-
-