parent
0dfe703a34
commit
21d55af62d
15 changed files with 371 additions and 51 deletions
50
server/migrations/2019-09-09-042010_add_stickied_posts/down.sql
vendored
Normal file
50
server/migrations/2019-09-09-042010_add_stickied_posts/down.sql
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
drop view post_view;
|
||||
drop view mod_sticky_post_view;
|
||||
alter table post drop column stickied;
|
||||
|
||||
drop table mod_sticky_post;
|
||||
|
||||
create view post_view as
|
||||
with all_post as
|
||||
(
|
||||
select
|
||||
p.*,
|
||||
(select u.banned from user_ u where p.creator_id = u.id) as banned,
|
||||
(select cb.id::bool from community_user_ban cb where p.creator_id = cb.user_id and p.community_id = cb.community_id) as banned_from_community,
|
||||
(select name from user_ where p.creator_id = user_.id) as creator_name,
|
||||
(select name from community where p.community_id = community.id) as community_name,
|
||||
(select removed from community c where p.community_id = c.id) as community_removed,
|
||||
(select deleted from community c where p.community_id = c.id) as community_deleted,
|
||||
(select nsfw from community c where p.community_id = c.id) as community_nsfw,
|
||||
(select count(*) from comment where comment.post_id = p.id) as number_of_comments,
|
||||
coalesce(sum(pl.score), 0) as score,
|
||||
count (case when pl.score = 1 then 1 else null end) as upvotes,
|
||||
count (case when pl.score = -1 then 1 else null end) as downvotes,
|
||||
hot_rank(coalesce(sum(pl.score) , 0), p.published) as hot_rank
|
||||
from post p
|
||||
left join post_like pl on p.id = pl.post_id
|
||||
group by p.id
|
||||
)
|
||||
|
||||
select
|
||||
ap.*,
|
||||
u.id as user_id,
|
||||
coalesce(pl.score, 0) as my_vote,
|
||||
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||
from user_ u
|
||||
cross join all_post ap
|
||||
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ap.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as subscribed,
|
||||
null as read,
|
||||
null as saved
|
||||
from all_post ap
|
||||
;
|
67
server/migrations/2019-09-09-042010_add_stickied_posts/up.sql
vendored
Normal file
67
server/migrations/2019-09-09-042010_add_stickied_posts/up.sql
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
-- Add the column
|
||||
alter table post add column stickied boolean default false not null;
|
||||
|
||||
-- Add the mod table
|
||||
create table mod_sticky_post (
|
||||
id serial primary key,
|
||||
mod_user_id int references user_ on update cascade on delete cascade not null,
|
||||
post_id int references post on update cascade on delete cascade not null,
|
||||
stickied boolean default true,
|
||||
when_ timestamp not null default now()
|
||||
);
|
||||
|
||||
-- Add mod view
|
||||
create view mod_sticky_post_view as
|
||||
select msp.*,
|
||||
(select name from user_ u where msp.mod_user_id = u.id) as mod_user_name,
|
||||
(select name from post p where msp.post_id = p.id) as post_name,
|
||||
(select c.id from post p, community c where msp.post_id = p.id and p.community_id = c.id) as community_id,
|
||||
(select c.name from post p, community c where msp.post_id = p.id and p.community_id = c.id) as community_name
|
||||
from mod_sticky_post msp;
|
||||
|
||||
-- Recreate the view
|
||||
drop view post_view;
|
||||
create view post_view as
|
||||
with all_post as
|
||||
(
|
||||
select
|
||||
p.*,
|
||||
(select u.banned from user_ u where p.creator_id = u.id) as banned,
|
||||
(select cb.id::bool from community_user_ban cb where p.creator_id = cb.user_id and p.community_id = cb.community_id) as banned_from_community,
|
||||
(select name from user_ where p.creator_id = user_.id) as creator_name,
|
||||
(select name from community where p.community_id = community.id) as community_name,
|
||||
(select removed from community c where p.community_id = c.id) as community_removed,
|
||||
(select deleted from community c where p.community_id = c.id) as community_deleted,
|
||||
(select nsfw from community c where p.community_id = c.id) as community_nsfw,
|
||||
(select count(*) from comment where comment.post_id = p.id) as number_of_comments,
|
||||
coalesce(sum(pl.score), 0) as score,
|
||||
count (case when pl.score = 1 then 1 else null end) as upvotes,
|
||||
count (case when pl.score = -1 then 1 else null end) as downvotes,
|
||||
hot_rank(coalesce(sum(pl.score) , 0), p.published) as hot_rank
|
||||
from post p
|
||||
left join post_like pl on p.id = pl.post_id
|
||||
group by p.id
|
||||
)
|
||||
|
||||
select
|
||||
ap.*,
|
||||
u.id as user_id,
|
||||
coalesce(pl.score, 0) as my_vote,
|
||||
(select cf.id::bool from community_follower cf where u.id = cf.user_id and cf.community_id = ap.community_id) as subscribed,
|
||||
(select pr.id::bool from post_read pr where u.id = pr.user_id and pr.post_id = ap.id) as read,
|
||||
(select ps.id::bool from post_saved ps where u.id = ps.user_id and ps.post_id = ap.id) as saved
|
||||
from user_ u
|
||||
cross join all_post ap
|
||||
left join post_like pl on u.id = pl.user_id and ap.id = pl.post_id
|
||||
|
||||
union all
|
||||
|
||||
select
|
||||
ap.*,
|
||||
null as user_id,
|
||||
null as my_vote,
|
||||
null as subscribed,
|
||||
null as read,
|
||||
null as saved
|
||||
from all_post ap
|
||||
;
|
|
@ -74,6 +74,7 @@ pub struct EditPost {
|
|||
deleted: Option<bool>,
|
||||
nsfw: bool,
|
||||
locked: Option<bool>,
|
||||
stickied: Option<bool>,
|
||||
reason: Option<String>,
|
||||
auth: String,
|
||||
}
|
||||
|
@ -121,6 +122,7 @@ impl Perform<PostResponse> for Oper<CreatePost> {
|
|||
deleted: None,
|
||||
nsfw: data.nsfw,
|
||||
locked: None,
|
||||
stickied: None,
|
||||
updated: None,
|
||||
};
|
||||
|
||||
|
@ -365,6 +367,7 @@ impl Perform<PostResponse> for Oper<EditPost> {
|
|||
deleted: data.deleted.to_owned(),
|
||||
nsfw: data.nsfw,
|
||||
locked: data.locked.to_owned(),
|
||||
stickied: data.stickied.to_owned(),
|
||||
updated: Some(naive_now()),
|
||||
};
|
||||
|
||||
|
@ -393,6 +396,15 @@ impl Perform<PostResponse> for Oper<EditPost> {
|
|||
ModLockPost::create(&conn, &form)?;
|
||||
}
|
||||
|
||||
if let Some(stickied) = data.stickied.to_owned() {
|
||||
let form = ModStickyPostForm {
|
||||
mod_user_id: user_id,
|
||||
post_id: data.edit_id,
|
||||
stickied: Some(stickied),
|
||||
};
|
||||
ModStickyPost::create(&conn, &form)?;
|
||||
}
|
||||
|
||||
let post_view = PostView::read(&conn, data.edit_id, Some(user_id))?;
|
||||
|
||||
Ok(PostResponse {
|
||||
|
|
|
@ -43,6 +43,7 @@ pub struct GetModlogResponse {
|
|||
op: String,
|
||||
removed_posts: Vec<ModRemovePostView>,
|
||||
locked_posts: Vec<ModLockPostView>,
|
||||
stickied_posts: Vec<ModStickyPostView>,
|
||||
removed_comments: Vec<ModRemoveCommentView>,
|
||||
removed_communities: Vec<ModRemoveCommunityView>,
|
||||
banned_from_community: Vec<ModBanFromCommunityView>,
|
||||
|
@ -122,6 +123,13 @@ impl Perform<GetModlogResponse> for Oper<GetModlog> {
|
|||
data.page,
|
||||
data.limit,
|
||||
)?;
|
||||
let stickied_posts = ModStickyPostView::list(
|
||||
&conn,
|
||||
data.community_id,
|
||||
data.mod_user_id,
|
||||
data.page,
|
||||
data.limit,
|
||||
)?;
|
||||
let removed_comments = ModRemoveCommentView::list(
|
||||
&conn,
|
||||
data.community_id,
|
||||
|
@ -161,6 +169,7 @@ impl Perform<GetModlogResponse> for Oper<GetModlog> {
|
|||
op: self.op.to_string(),
|
||||
removed_posts: removed_posts,
|
||||
locked_posts: locked_posts,
|
||||
stickied_posts: stickied_posts,
|
||||
removed_comments: removed_comments,
|
||||
removed_communities: removed_communities,
|
||||
banned_from_community: banned_from_community,
|
||||
|
|
|
@ -205,6 +205,7 @@ mod tests {
|
|||
removed: None,
|
||||
deleted: None,
|
||||
locked: None,
|
||||
stickied: None,
|
||||
updated: None,
|
||||
nsfw: false,
|
||||
};
|
||||
|
|
|
@ -291,6 +291,7 @@ mod tests {
|
|||
removed: None,
|
||||
deleted: None,
|
||||
locked: None,
|
||||
stickied: None,
|
||||
updated: None,
|
||||
nsfw: false,
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::*;
|
||||
use crate::schema::{
|
||||
mod_add, mod_add_community, mod_ban, mod_ban_from_community, mod_lock_post, mod_remove_comment,
|
||||
mod_remove_community, mod_remove_post,
|
||||
mod_remove_community, mod_remove_post, mod_sticky_post,
|
||||
};
|
||||
|
||||
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
|
||||
|
@ -94,6 +94,50 @@ impl Crud<ModLockPostForm> for ModLockPost {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
|
||||
#[table_name = "mod_sticky_post"]
|
||||
pub struct ModStickyPost {
|
||||
pub id: i32,
|
||||
pub mod_user_id: i32,
|
||||
pub post_id: i32,
|
||||
pub stickied: Option<bool>,
|
||||
pub when_: chrono::NaiveDateTime,
|
||||
}
|
||||
|
||||
#[derive(Insertable, AsChangeset, Clone, Serialize, Deserialize)]
|
||||
#[table_name = "mod_sticky_post"]
|
||||
pub struct ModStickyPostForm {
|
||||
pub mod_user_id: i32,
|
||||
pub post_id: i32,
|
||||
pub stickied: Option<bool>,
|
||||
}
|
||||
|
||||
impl Crud<ModStickyPostForm> for ModStickyPost {
|
||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||
use crate::schema::mod_sticky_post::dsl::*;
|
||||
mod_sticky_post.find(from_id).first::<Self>(conn)
|
||||
}
|
||||
|
||||
fn delete(conn: &PgConnection, from_id: i32) -> Result<usize, Error> {
|
||||
use crate::schema::mod_sticky_post::dsl::*;
|
||||
diesel::delete(mod_sticky_post.find(from_id)).execute(conn)
|
||||
}
|
||||
|
||||
fn create(conn: &PgConnection, form: &ModStickyPostForm) -> Result<Self, Error> {
|
||||
use crate::schema::mod_sticky_post::dsl::*;
|
||||
insert_into(mod_sticky_post)
|
||||
.values(form)
|
||||
.get_result::<Self>(conn)
|
||||
}
|
||||
|
||||
fn update(conn: &PgConnection, from_id: i32, form: &ModStickyPostForm) -> Result<Self, Error> {
|
||||
use crate::schema::mod_sticky_post::dsl::*;
|
||||
diesel::update(mod_sticky_post.find(from_id))
|
||||
.set(form)
|
||||
.get_result::<Self>(conn)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
|
||||
#[table_name = "mod_remove_comment"]
|
||||
pub struct ModRemoveComment {
|
||||
|
@ -443,6 +487,7 @@ mod tests {
|
|||
removed: None,
|
||||
deleted: None,
|
||||
locked: None,
|
||||
stickied: None,
|
||||
updated: None,
|
||||
nsfw: false,
|
||||
};
|
||||
|
@ -472,9 +517,8 @@ mod tests {
|
|||
removed: None,
|
||||
};
|
||||
let inserted_mod_remove_post = ModRemovePost::create(&conn, &mod_remove_post_form).unwrap();
|
||||
let read_moderator_remove_post =
|
||||
ModRemovePost::read(&conn, inserted_mod_remove_post.id).unwrap();
|
||||
let expected_moderator_remove_post = ModRemovePost {
|
||||
let read_mod_remove_post = ModRemovePost::read(&conn, inserted_mod_remove_post.id).unwrap();
|
||||
let expected_mod_remove_post = ModRemovePost {
|
||||
id: inserted_mod_remove_post.id,
|
||||
post_id: inserted_post.id,
|
||||
mod_user_id: inserted_mod.id,
|
||||
|
@ -491,8 +535,8 @@ mod tests {
|
|||
locked: None,
|
||||
};
|
||||
let inserted_mod_lock_post = ModLockPost::create(&conn, &mod_lock_post_form).unwrap();
|
||||
let read_moderator_lock_post = ModLockPost::read(&conn, inserted_mod_lock_post.id).unwrap();
|
||||
let expected_moderator_lock_post = ModLockPost {
|
||||
let read_mod_lock_post = ModLockPost::read(&conn, inserted_mod_lock_post.id).unwrap();
|
||||
let expected_mod_lock_post = ModLockPost {
|
||||
id: inserted_mod_lock_post.id,
|
||||
post_id: inserted_post.id,
|
||||
mod_user_id: inserted_mod.id,
|
||||
|
@ -500,6 +544,23 @@ mod tests {
|
|||
when_: inserted_mod_lock_post.when_,
|
||||
};
|
||||
|
||||
// sticky post
|
||||
|
||||
let mod_sticky_post_form = ModStickyPostForm {
|
||||
mod_user_id: inserted_mod.id,
|
||||
post_id: inserted_post.id,
|
||||
stickied: None,
|
||||
};
|
||||
let inserted_mod_sticky_post = ModStickyPost::create(&conn, &mod_sticky_post_form).unwrap();
|
||||
let read_mod_sticky_post = ModStickyPost::read(&conn, inserted_mod_sticky_post.id).unwrap();
|
||||
let expected_mod_sticky_post = ModStickyPost {
|
||||
id: inserted_mod_sticky_post.id,
|
||||
post_id: inserted_post.id,
|
||||
mod_user_id: inserted_mod.id,
|
||||
stickied: Some(true),
|
||||
when_: inserted_mod_sticky_post.when_,
|
||||
};
|
||||
|
||||
// comment
|
||||
|
||||
let mod_remove_comment_form = ModRemoveCommentForm {
|
||||
|
@ -510,9 +571,9 @@ mod tests {
|
|||
};
|
||||
let inserted_mod_remove_comment =
|
||||
ModRemoveComment::create(&conn, &mod_remove_comment_form).unwrap();
|
||||
let read_moderator_remove_comment =
|
||||
let read_mod_remove_comment =
|
||||
ModRemoveComment::read(&conn, inserted_mod_remove_comment.id).unwrap();
|
||||
let expected_moderator_remove_comment = ModRemoveComment {
|
||||
let expected_mod_remove_comment = ModRemoveComment {
|
||||
id: inserted_mod_remove_comment.id,
|
||||
comment_id: inserted_comment.id,
|
||||
mod_user_id: inserted_mod.id,
|
||||
|
@ -532,9 +593,9 @@ mod tests {
|
|||
};
|
||||
let inserted_mod_remove_community =
|
||||
ModRemoveCommunity::create(&conn, &mod_remove_community_form).unwrap();
|
||||
let read_moderator_remove_community =
|
||||
let read_mod_remove_community =
|
||||
ModRemoveCommunity::read(&conn, inserted_mod_remove_community.id).unwrap();
|
||||
let expected_moderator_remove_community = ModRemoveCommunity {
|
||||
let expected_mod_remove_community = ModRemoveCommunity {
|
||||
id: inserted_mod_remove_community.id,
|
||||
community_id: inserted_community.id,
|
||||
mod_user_id: inserted_mod.id,
|
||||
|
@ -556,9 +617,9 @@ mod tests {
|
|||
};
|
||||
let inserted_mod_ban_from_community =
|
||||
ModBanFromCommunity::create(&conn, &mod_ban_from_community_form).unwrap();
|
||||
let read_moderator_ban_from_community =
|
||||
let read_mod_ban_from_community =
|
||||
ModBanFromCommunity::read(&conn, inserted_mod_ban_from_community.id).unwrap();
|
||||
let expected_moderator_ban_from_community = ModBanFromCommunity {
|
||||
let expected_mod_ban_from_community = ModBanFromCommunity {
|
||||
id: inserted_mod_ban_from_community.id,
|
||||
community_id: inserted_community.id,
|
||||
mod_user_id: inserted_mod.id,
|
||||
|
@ -579,8 +640,8 @@ mod tests {
|
|||
expires: None,
|
||||
};
|
||||
let inserted_mod_ban = ModBan::create(&conn, &mod_ban_form).unwrap();
|
||||
let read_moderator_ban = ModBan::read(&conn, inserted_mod_ban.id).unwrap();
|
||||
let expected_moderator_ban = ModBan {
|
||||
let read_mod_ban = ModBan::read(&conn, inserted_mod_ban.id).unwrap();
|
||||
let expected_mod_ban = ModBan {
|
||||
id: inserted_mod_ban.id,
|
||||
mod_user_id: inserted_mod.id,
|
||||
other_user_id: inserted_user.id,
|
||||
|
@ -600,9 +661,9 @@ mod tests {
|
|||
};
|
||||
let inserted_mod_add_community =
|
||||
ModAddCommunity::create(&conn, &mod_add_community_form).unwrap();
|
||||
let read_moderator_add_community =
|
||||
let read_mod_add_community =
|
||||
ModAddCommunity::read(&conn, inserted_mod_add_community.id).unwrap();
|
||||
let expected_moderator_add_community = ModAddCommunity {
|
||||
let expected_mod_add_community = ModAddCommunity {
|
||||
id: inserted_mod_add_community.id,
|
||||
community_id: inserted_community.id,
|
||||
mod_user_id: inserted_mod.id,
|
||||
|
@ -619,8 +680,8 @@ mod tests {
|
|||
removed: None,
|
||||
};
|
||||
let inserted_mod_add = ModAdd::create(&conn, &mod_add_form).unwrap();
|
||||
let read_moderator_add = ModAdd::read(&conn, inserted_mod_add.id).unwrap();
|
||||
let expected_moderator_add = ModAdd {
|
||||
let read_mod_add = ModAdd::read(&conn, inserted_mod_add.id).unwrap();
|
||||
let expected_mod_add = ModAdd {
|
||||
id: inserted_mod_add.id,
|
||||
mod_user_id: inserted_mod.id,
|
||||
other_user_id: inserted_user.id,
|
||||
|
@ -630,6 +691,7 @@ mod tests {
|
|||
|
||||
ModRemovePost::delete(&conn, inserted_mod_remove_post.id).unwrap();
|
||||
ModLockPost::delete(&conn, inserted_mod_lock_post.id).unwrap();
|
||||
ModStickyPost::delete(&conn, inserted_mod_sticky_post.id).unwrap();
|
||||
ModRemoveComment::delete(&conn, inserted_mod_remove_comment.id).unwrap();
|
||||
ModRemoveCommunity::delete(&conn, inserted_mod_remove_community.id).unwrap();
|
||||
ModBanFromCommunity::delete(&conn, inserted_mod_ban_from_community.id).unwrap();
|
||||
|
@ -643,25 +705,14 @@ mod tests {
|
|||
User_::delete(&conn, inserted_user.id).unwrap();
|
||||
User_::delete(&conn, inserted_mod.id).unwrap();
|
||||
|
||||
assert_eq!(expected_moderator_remove_post, read_moderator_remove_post);
|
||||
assert_eq!(expected_moderator_lock_post, read_moderator_lock_post);
|
||||
assert_eq!(
|
||||
expected_moderator_remove_comment,
|
||||
read_moderator_remove_comment
|
||||
);
|
||||
assert_eq!(
|
||||
expected_moderator_remove_community,
|
||||
read_moderator_remove_community
|
||||
);
|
||||
assert_eq!(
|
||||
expected_moderator_ban_from_community,
|
||||
read_moderator_ban_from_community
|
||||
);
|
||||
assert_eq!(expected_moderator_ban, read_moderator_ban);
|
||||
assert_eq!(
|
||||
expected_moderator_add_community,
|
||||
read_moderator_add_community
|
||||
);
|
||||
assert_eq!(expected_moderator_add, read_moderator_add);
|
||||
assert_eq!(expected_mod_remove_post, read_mod_remove_post);
|
||||
assert_eq!(expected_mod_lock_post, read_mod_lock_post);
|
||||
assert_eq!(expected_mod_sticky_post, read_mod_sticky_post);
|
||||
assert_eq!(expected_mod_remove_comment, read_mod_remove_comment);
|
||||
assert_eq!(expected_mod_remove_community, read_mod_remove_community);
|
||||
assert_eq!(expected_mod_ban_from_community, read_mod_ban_from_community);
|
||||
assert_eq!(expected_mod_ban, read_mod_ban);
|
||||
assert_eq!(expected_mod_add_community, read_mod_add_community);
|
||||
assert_eq!(expected_mod_add, read_mod_add);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,6 +120,65 @@ impl ModLockPostView {
|
|||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
mod_sticky_post_view (id) {
|
||||
id -> Int4,
|
||||
mod_user_id -> Int4,
|
||||
post_id -> Int4,
|
||||
stickied -> Nullable<Bool>,
|
||||
when_ -> Timestamp,
|
||||
mod_user_name -> Varchar,
|
||||
post_name -> Varchar,
|
||||
community_id -> Int4,
|
||||
community_name -> Varchar,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, QueryableByName, Clone,
|
||||
)]
|
||||
#[table_name = "mod_sticky_post_view"]
|
||||
pub struct ModStickyPostView {
|
||||
pub id: i32,
|
||||
pub mod_user_id: i32,
|
||||
pub post_id: i32,
|
||||
pub stickied: Option<bool>,
|
||||
pub when_: chrono::NaiveDateTime,
|
||||
pub mod_user_name: String,
|
||||
pub post_name: String,
|
||||
pub community_id: i32,
|
||||
pub community_name: String,
|
||||
}
|
||||
|
||||
impl ModStickyPostView {
|
||||
pub fn list(
|
||||
conn: &PgConnection,
|
||||
from_community_id: Option<i32>,
|
||||
from_mod_user_id: Option<i32>,
|
||||
page: Option<i64>,
|
||||
limit: Option<i64>,
|
||||
) -> Result<Vec<Self>, Error> {
|
||||
use super::moderator_views::mod_sticky_post_view::dsl::*;
|
||||
let mut query = mod_sticky_post_view.into_boxed();
|
||||
|
||||
let (limit, offset) = limit_and_offset(page, limit);
|
||||
|
||||
if let Some(from_community_id) = from_community_id {
|
||||
query = query.filter(community_id.eq(from_community_id));
|
||||
};
|
||||
|
||||
if let Some(from_mod_user_id) = from_mod_user_id {
|
||||
query = query.filter(mod_user_id.eq(from_mod_user_id));
|
||||
};
|
||||
|
||||
query
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.order_by(when_.desc())
|
||||
.load::<Self>(conn)
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
mod_remove_comment_view (id) {
|
||||
id -> Int4,
|
||||
|
|
|
@ -16,6 +16,7 @@ pub struct Post {
|
|||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub deleted: bool,
|
||||
pub nsfw: bool,
|
||||
pub stickied: bool,
|
||||
}
|
||||
|
||||
#[derive(Insertable, AsChangeset, Clone)]
|
||||
|
@ -31,6 +32,7 @@ pub struct PostForm {
|
|||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub deleted: Option<bool>,
|
||||
pub nsfw: bool,
|
||||
pub stickied: Option<bool>,
|
||||
}
|
||||
|
||||
impl Crud<PostForm> for Post {
|
||||
|
@ -216,6 +218,7 @@ mod tests {
|
|||
removed: None,
|
||||
deleted: None,
|
||||
locked: None,
|
||||
stickied: None,
|
||||
nsfw: false,
|
||||
updated: None,
|
||||
};
|
||||
|
@ -232,6 +235,7 @@ mod tests {
|
|||
published: inserted_post.published,
|
||||
removed: false,
|
||||
locked: false,
|
||||
stickied: false,
|
||||
nsfw: false,
|
||||
deleted: false,
|
||||
updated: None,
|
||||
|
|
|
@ -24,6 +24,7 @@ table! {
|
|||
nsfw -> Bool,
|
||||
banned -> Bool,
|
||||
banned_from_community -> Bool,
|
||||
stickied -> Bool,
|
||||
creator_name -> Varchar,
|
||||
community_name -> Varchar,
|
||||
community_removed -> Bool,
|
||||
|
@ -61,6 +62,7 @@ pub struct PostView {
|
|||
pub nsfw: bool,
|
||||
pub banned: bool,
|
||||
pub banned_from_community: bool,
|
||||
pub stickied: bool,
|
||||
pub creator_name: String,
|
||||
pub community_name: String,
|
||||
pub community_removed: bool,
|
||||
|
@ -100,10 +102,6 @@ impl PostView {
|
|||
|
||||
let mut query = post_view.into_boxed();
|
||||
|
||||
if let Some(for_community_id) = for_community_id {
|
||||
query = query.filter(community_id.eq(for_community_id));
|
||||
};
|
||||
|
||||
if let Some(for_creator_id) = for_creator_id {
|
||||
query = query.filter(creator_id.eq(for_creator_id));
|
||||
};
|
||||
|
@ -116,6 +114,11 @@ impl PostView {
|
|||
query = query.filter(url.eq(url_search));
|
||||
};
|
||||
|
||||
if let Some(for_community_id) = for_community_id {
|
||||
query = query.filter(community_id.eq(for_community_id));
|
||||
query = query.then_order_by(stickied.desc());
|
||||
};
|
||||
|
||||
// TODO these are wrong, bc they'll only show saved for your logged in user, not theirs
|
||||
if saved_only {
|
||||
query = query.filter(saved.eq(true));
|
||||
|
@ -147,22 +150,22 @@ impl PostView {
|
|||
|
||||
query = match sort {
|
||||
SortType::Hot => query
|
||||
.order_by(hot_rank.desc())
|
||||
.then_order_by(hot_rank.desc())
|
||||
.then_order_by(published.desc()),
|
||||
SortType::New => query.order_by(published.desc()),
|
||||
SortType::TopAll => query.order_by(score.desc()),
|
||||
SortType::New => query.then_order_by(published.desc()),
|
||||
SortType::TopAll => query.then_order_by(score.desc()),
|
||||
SortType::TopYear => query
|
||||
.filter(published.gt(now - 1.years()))
|
||||
.order_by(score.desc()),
|
||||
.then_order_by(score.desc()),
|
||||
SortType::TopMonth => query
|
||||
.filter(published.gt(now - 1.months()))
|
||||
.order_by(score.desc()),
|
||||
.then_order_by(score.desc()),
|
||||
SortType::TopWeek => query
|
||||
.filter(published.gt(now - 1.weeks()))
|
||||
.order_by(score.desc()),
|
||||
.then_order_by(score.desc()),
|
||||
SortType::TopDay => query
|
||||
.filter(published.gt(now - 1.days()))
|
||||
.order_by(score.desc()),
|
||||
.then_order_by(score.desc()),
|
||||
};
|
||||
|
||||
query = query
|
||||
|
@ -249,6 +252,7 @@ mod tests {
|
|||
removed: None,
|
||||
deleted: None,
|
||||
locked: None,
|
||||
stickied: None,
|
||||
updated: None,
|
||||
nsfw: false,
|
||||
};
|
||||
|
@ -293,6 +297,7 @@ mod tests {
|
|||
removed: false,
|
||||
deleted: false,
|
||||
locked: false,
|
||||
stickied: false,
|
||||
community_name: community_name.to_owned(),
|
||||
community_removed: false,
|
||||
community_deleted: false,
|
||||
|
@ -320,6 +325,7 @@ mod tests {
|
|||
removed: false,
|
||||
deleted: false,
|
||||
locked: false,
|
||||
stickied: false,
|
||||
creator_id: inserted_user.id,
|
||||
creator_name: user_name.to_owned(),
|
||||
banned: false,
|
||||
|
|
|
@ -173,6 +173,16 @@ table! {
|
|||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
mod_sticky_post (id) {
|
||||
id -> Int4,
|
||||
mod_user_id -> Int4,
|
||||
post_id -> Int4,
|
||||
stickied -> Nullable<Bool>,
|
||||
when_ -> Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
post (id) {
|
||||
id -> Int4,
|
||||
|
@ -187,6 +197,7 @@ table! {
|
|||
updated -> Nullable<Timestamp>,
|
||||
deleted -> Bool,
|
||||
nsfw -> Bool,
|
||||
stickied -> Bool,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,6 +290,8 @@ joinable!(mod_remove_community -> community (community_id));
|
|||
joinable!(mod_remove_community -> user_ (mod_user_id));
|
||||
joinable!(mod_remove_post -> post (post_id));
|
||||
joinable!(mod_remove_post -> user_ (mod_user_id));
|
||||
joinable!(mod_sticky_post -> post (post_id));
|
||||
joinable!(mod_sticky_post -> user_ (mod_user_id));
|
||||
joinable!(post -> community (community_id));
|
||||
joinable!(post -> user_ (creator_id));
|
||||
joinable!(post_like -> post (post_id));
|
||||
|
@ -307,6 +320,7 @@ allow_tables_to_appear_in_same_query!(
|
|||
mod_remove_comment,
|
||||
mod_remove_community,
|
||||
mod_remove_post,
|
||||
mod_sticky_post,
|
||||
post,
|
||||
post_like,
|
||||
post_read,
|
||||
|
|
13
ui/src/components/modlog.tsx
vendored
13
ui/src/components/modlog.tsx
vendored
|
@ -2,14 +2,15 @@ import { Component, linkEvent } from 'inferno';
|
|||
import { Link } from 'inferno-router';
|
||||
import { Subscription } from "rxjs";
|
||||
import { retryWhen, delay, take } from 'rxjs/operators';
|
||||
import { UserOperation, GetModlogForm, GetModlogResponse, ModRemovePost, ModLockPost, ModRemoveComment, ModRemoveCommunity, ModBanFromCommunity, ModBan, ModAddCommunity, ModAdd } from '../interfaces';
|
||||
import { UserOperation, GetModlogForm, GetModlogResponse, ModRemovePost, ModLockPost, ModStickyPost, ModRemoveComment, ModRemoveCommunity, ModBanFromCommunity, ModBan, ModAddCommunity, ModAdd } from '../interfaces';
|
||||
import { WebSocketService } from '../services';
|
||||
import { msgOp, addTypeInfo, fetchLimit } from '../utils';
|
||||
import { MomentTime } from './moment-time';
|
||||
import * as moment from 'moment';
|
||||
import { i18n } from '../i18next';
|
||||
|
||||
interface ModlogState {
|
||||
combined: Array<{type_: string, data: ModRemovePost | ModLockPost | ModRemoveCommunity | ModAdd | ModBan}>,
|
||||
combined: Array<{type_: string, data: ModRemovePost | ModLockPost | ModStickyPost | ModRemoveCommunity | ModAdd | ModBan}>,
|
||||
communityId?: number,
|
||||
communityName?: string,
|
||||
page: number;
|
||||
|
@ -51,6 +52,7 @@ export class Modlog extends Component<any, ModlogState> {
|
|||
setCombined(res: GetModlogResponse) {
|
||||
let removed_posts = addTypeInfo(res.removed_posts, "removed_posts");
|
||||
let locked_posts = addTypeInfo(res.locked_posts, "locked_posts");
|
||||
let stickied_posts = addTypeInfo(res.stickied_posts, "stickied_posts");
|
||||
let removed_comments = addTypeInfo(res.removed_comments, "removed_comments");
|
||||
let removed_communities = addTypeInfo(res.removed_communities, "removed_communities");
|
||||
let banned_from_community = addTypeInfo(res.banned_from_community, "banned_from_community");
|
||||
|
@ -61,6 +63,7 @@ export class Modlog extends Component<any, ModlogState> {
|
|||
|
||||
this.state.combined.push(...removed_posts);
|
||||
this.state.combined.push(...locked_posts);
|
||||
this.state.combined.push(...stickied_posts);
|
||||
this.state.combined.push(...removed_comments);
|
||||
this.state.combined.push(...removed_communities);
|
||||
this.state.combined.push(...banned_from_community);
|
||||
|
@ -99,6 +102,12 @@ export class Modlog extends Component<any, ModlogState> {
|
|||
<span> Post <Link to={`/post/${(i.data as ModLockPost).post_id}`}>{(i.data as ModLockPost).post_name}</Link></span>
|
||||
</>
|
||||
}
|
||||
{i.type_ == 'stickied_posts' &&
|
||||
<>
|
||||
{(i.data as ModStickyPost).stickied? 'Stickied' : 'Unstickied'}
|
||||
<span> Post <Link to={`/post/${(i.data as ModStickyPost).post_id}`}>{(i.data as ModStickyPost).post_name}</Link></span>
|
||||
</>
|
||||
}
|
||||
{i.type_ == 'removed_comments' &&
|
||||
<>
|
||||
{(i.data as ModRemoveComment).removed? 'Removed' : 'Restored'}
|
||||
|
|
19
ui/src/components/post-listing.tsx
vendored
19
ui/src/components/post-listing.tsx
vendored
|
@ -129,6 +129,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
{post.locked &&
|
||||
<small className="ml-2 text-muted font-italic"><T i18nKey="locked">#</T></small>
|
||||
}
|
||||
{post.stickied &&
|
||||
<small className="ml-2 text-muted font-italic"><T i18nKey="stickied">#</T></small>
|
||||
}
|
||||
{post.nsfw &&
|
||||
<small className="ml-2 text-muted font-italic"><T i18nKey="nsfw">#</T></small>
|
||||
}
|
||||
|
@ -202,6 +205,9 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
<li className="list-inline-item">
|
||||
<span class="pointer" onClick={linkEvent(this, this.handleModLock)}>{post.locked ? i18n.t('unlock') : i18n.t('lock')}</span>
|
||||
</li>
|
||||
<li className="list-inline-item">
|
||||
<span class="pointer" onClick={linkEvent(this, this.handleModSticky)}>{post.stickied ? i18n.t('unsticky') : i18n.t('sticky')}</span>
|
||||
</li>
|
||||
</>
|
||||
}
|
||||
{/* Mods can ban from community, and appoint as mods to community */}
|
||||
|
@ -459,6 +465,19 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
|
|||
WebSocketService.Instance.editPost(form);
|
||||
}
|
||||
|
||||
handleModSticky(i: PostListing) {
|
||||
let form: PostFormI = {
|
||||
name: i.props.post.name,
|
||||
community_id: i.props.post.community_id,
|
||||
edit_id: i.props.post.id,
|
||||
creator_id: i.props.post.creator_id,
|
||||
nsfw: i.props.post.nsfw,
|
||||
stickied: !i.props.post.stickied,
|
||||
auth: null,
|
||||
};
|
||||
WebSocketService.Instance.editPost(form);
|
||||
}
|
||||
|
||||
handleModBanFromCommunityShow(i: PostListing) {
|
||||
i.state.showBanDialog = true;
|
||||
i.state.banType = BanType.Community;
|
||||
|
|
15
ui/src/interfaces.ts
vendored
15
ui/src/interfaces.ts
vendored
|
@ -77,6 +77,7 @@ export interface Post {
|
|||
removed: boolean;
|
||||
deleted: boolean;
|
||||
locked: boolean;
|
||||
stickied: boolean;
|
||||
nsfw: boolean;
|
||||
banned: boolean;
|
||||
banned_from_community: boolean;
|
||||
|
@ -235,6 +236,7 @@ export interface GetModlogResponse {
|
|||
op: string;
|
||||
removed_posts: Array<ModRemovePost>,
|
||||
locked_posts: Array<ModLockPost>,
|
||||
stickied_posts: Array<ModStickyPost>,
|
||||
removed_comments: Array<ModRemoveComment>,
|
||||
removed_communities: Array<ModRemoveCommunity>,
|
||||
banned_from_community: Array<ModBanFromCommunity>,
|
||||
|
@ -268,6 +270,18 @@ export interface ModLockPost {
|
|||
community_name: string,
|
||||
}
|
||||
|
||||
export interface ModStickyPost {
|
||||
id: number,
|
||||
mod_user_id: number,
|
||||
post_id: number,
|
||||
stickied?: boolean,
|
||||
when_: string,
|
||||
mod_user_name: string,
|
||||
post_name: string,
|
||||
community_id: number,
|
||||
community_name: string,
|
||||
}
|
||||
|
||||
export interface ModRemoveComment {
|
||||
id: number,
|
||||
mod_user_id: number,
|
||||
|
@ -425,6 +439,7 @@ export interface PostForm {
|
|||
deleted?: boolean;
|
||||
nsfw: boolean;
|
||||
locked?: boolean;
|
||||
stickied?: boolean;
|
||||
reason?: string;
|
||||
auth: string;
|
||||
}
|
||||
|
|
3
ui/src/translations/en.ts
vendored
3
ui/src/translations/en.ts
vendored
|
@ -32,6 +32,8 @@ export const en = {
|
|||
view_source: 'view source',
|
||||
unlock: 'unlock',
|
||||
lock: 'lock',
|
||||
sticky: 'sticky',
|
||||
unsticky: 'unsticky',
|
||||
link: 'link',
|
||||
mod: 'mod',
|
||||
mods: 'mods',
|
||||
|
@ -47,6 +49,7 @@ export const en = {
|
|||
remove: 'remove',
|
||||
removed: 'removed',
|
||||
locked: 'locked',
|
||||
stickied: 'stickied',
|
||||
reason: 'Reason',
|
||||
mark_as_read: 'mark as read',
|
||||
mark_as_unread: 'mark as unread',
|
||||
|
|
Reference in a new issue