mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-27 06:41:18 +00:00
Adding subscribe to communities.
- Adding subscribe. Fixes #12. Fixes #27.
This commit is contained in:
parent
4352b24734
commit
4b6b456446
10 changed files with 249 additions and 32 deletions
|
@ -1,11 +1,31 @@
|
||||||
create view community_view as
|
create view community_view as
|
||||||
select *,
|
with all_community as
|
||||||
(select name from user_ u where c.creator_id = u.id) as creator_name,
|
(
|
||||||
(select name from category ct where c.category_id = ct.id) as category_name,
|
select *,
|
||||||
(select count(*) from community_follower cf where cf.community_id = c.id) as number_of_subscribers,
|
(select name from user_ u where c.creator_id = u.id) as creator_name,
|
||||||
(select count(*) from post p where p.community_id = c.id) as number_of_posts,
|
(select name from category ct where c.category_id = ct.id) as category_name,
|
||||||
(select count(*) from comment co, post p where c.id = p.community_id and p.id = co.post_id) as number_of_comments
|
(select count(*) from community_follower cf where cf.community_id = c.id) as number_of_subscribers,
|
||||||
from community c;
|
(select count(*) from post p where p.community_id = c.id) as number_of_posts,
|
||||||
|
(select count(*) from comment co, post p where c.id = p.community_id and p.id = co.post_id) as number_of_comments
|
||||||
|
from community c
|
||||||
|
)
|
||||||
|
|
||||||
|
select
|
||||||
|
ac.*,
|
||||||
|
u.id as user_id,
|
||||||
|
cf.id::boolean as subscribed
|
||||||
|
from user_ u
|
||||||
|
cross join all_community ac
|
||||||
|
left join community_follower cf on u.id = cf.user_id and ac.id = cf.community_id
|
||||||
|
|
||||||
|
union all
|
||||||
|
|
||||||
|
select
|
||||||
|
ac.*,
|
||||||
|
null as user_id,
|
||||||
|
null as subscribed
|
||||||
|
from all_community ac
|
||||||
|
;
|
||||||
|
|
||||||
create view community_moderator_view as
|
create view community_moderator_view as
|
||||||
select *,
|
select *,
|
||||||
|
|
|
@ -18,6 +18,8 @@ table! {
|
||||||
number_of_subscribers -> BigInt,
|
number_of_subscribers -> BigInt,
|
||||||
number_of_posts -> BigInt,
|
number_of_posts -> BigInt,
|
||||||
number_of_comments -> BigInt,
|
number_of_comments -> BigInt,
|
||||||
|
user_id -> Nullable<Int4>,
|
||||||
|
subscribed -> Nullable<Bool>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,18 +60,43 @@ pub struct CommunityView {
|
||||||
pub category_name: String,
|
pub category_name: String,
|
||||||
pub number_of_subscribers: i64,
|
pub number_of_subscribers: i64,
|
||||||
pub number_of_posts: i64,
|
pub number_of_posts: i64,
|
||||||
pub number_of_comments: i64
|
pub number_of_comments: i64,
|
||||||
|
pub user_id: Option<i32>,
|
||||||
|
pub subscribed: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommunityView {
|
impl CommunityView {
|
||||||
pub fn read(conn: &PgConnection, from_community_id: i32) -> Result<Self, Error> {
|
pub fn read(conn: &PgConnection, from_community_id: i32, from_user_id: Option<i32>) -> Result<Self, Error> {
|
||||||
use actions::community_view::community_view::dsl::*;
|
use actions::community_view::community_view::dsl::*;
|
||||||
community_view.find(from_community_id).first::<Self>(conn)
|
|
||||||
|
let mut query = community_view.into_boxed();
|
||||||
|
|
||||||
|
query = query.filter(id.eq(from_community_id));
|
||||||
|
|
||||||
|
// The view lets you pass a null user_id, if you're not logged in
|
||||||
|
if let Some(from_user_id) = from_user_id {
|
||||||
|
query = query.filter(user_id.eq(from_user_id));
|
||||||
|
} else {
|
||||||
|
query = query.filter(user_id.is_null());
|
||||||
|
};
|
||||||
|
|
||||||
|
query.first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_all(conn: &PgConnection) -> Result<Vec<Self>, Error> {
|
pub fn list_all(conn: &PgConnection, from_user_id: Option<i32>) -> Result<Vec<Self>, Error> {
|
||||||
use actions::community_view::community_view::dsl::*;
|
use actions::community_view::community_view::dsl::*;
|
||||||
community_view.load::<Self>(conn)
|
let mut query = community_view.into_boxed();
|
||||||
|
|
||||||
|
// The view lets you pass a null user_id, if you're not logged in
|
||||||
|
if let Some(from_user_id) = from_user_id {
|
||||||
|
query = query.filter(user_id.eq(from_user_id))
|
||||||
|
.order_by((subscribed.desc(), number_of_subscribers.desc()));
|
||||||
|
} else {
|
||||||
|
query = query.filter(user_id.is_null())
|
||||||
|
.order_by(number_of_subscribers.desc());
|
||||||
|
};
|
||||||
|
|
||||||
|
query.load::<Self>(conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ impl PostView {
|
||||||
query = query.filter(user_id.eq(from_user_id));
|
query = query.filter(user_id.eq(from_user_id));
|
||||||
} else {
|
} else {
|
||||||
query = query.filter(user_id.is_null());
|
query = query.filter(user_id.is_null());
|
||||||
}
|
};
|
||||||
|
|
||||||
query.first::<Self>(conn)
|
query.first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ use actions::community_view::*;
|
||||||
|
|
||||||
#[derive(EnumString,ToString,Debug)]
|
#[derive(EnumString,ToString,Debug)]
|
||||||
pub enum UserOperation {
|
pub enum UserOperation {
|
||||||
Login, Register, CreateCommunity, CreatePost, ListCommunities, ListCategories, GetPost, GetCommunity, CreateComment, EditComment, CreateCommentLike, GetPosts, CreatePostLike, EditPost, EditCommunity
|
Login, Register, CreateCommunity, CreatePost, ListCommunities, ListCategories, GetPost, GetCommunity, CreateComment, EditComment, CreateCommentLike, GetPosts, CreatePostLike, EditPost, EditCommunity, FollowCommunity
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
@ -109,7 +109,9 @@ pub struct CommunityResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct ListCommunities;
|
pub struct ListCommunities {
|
||||||
|
auth: Option<String>
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct ListCommunitiesResponse {
|
pub struct ListCommunitiesResponse {
|
||||||
|
@ -174,7 +176,8 @@ pub struct GetPostsResponse {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct GetCommunity {
|
pub struct GetCommunity {
|
||||||
id: i32
|
id: i32,
|
||||||
|
auth: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
@ -251,6 +254,13 @@ pub struct EditCommunity {
|
||||||
auth: String
|
auth: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct FollowCommunity {
|
||||||
|
community_id: i32,
|
||||||
|
follow: bool,
|
||||||
|
auth: String
|
||||||
|
}
|
||||||
|
|
||||||
/// `ChatServer` manages chat rooms and responsible for coordinating chat
|
/// `ChatServer` manages chat rooms and responsible for coordinating chat
|
||||||
/// session. implementation is super primitive
|
/// session. implementation is super primitive
|
||||||
pub struct ChatServer {
|
pub struct ChatServer {
|
||||||
|
@ -389,7 +399,7 @@ impl Handler<StandardMessage> for ChatServer {
|
||||||
create_community.perform(self, msg.id)
|
create_community.perform(self, msg.id)
|
||||||
},
|
},
|
||||||
UserOperation::ListCommunities => {
|
UserOperation::ListCommunities => {
|
||||||
let list_communities: ListCommunities = ListCommunities;
|
let list_communities: ListCommunities = serde_json::from_str(&data.to_string()).unwrap();
|
||||||
list_communities.perform(self, msg.id)
|
list_communities.perform(self, msg.id)
|
||||||
},
|
},
|
||||||
UserOperation::ListCategories => {
|
UserOperation::ListCategories => {
|
||||||
|
@ -436,6 +446,10 @@ impl Handler<StandardMessage> for ChatServer {
|
||||||
let edit_community: EditCommunity = serde_json::from_str(&data.to_string()).unwrap();
|
let edit_community: EditCommunity = serde_json::from_str(&data.to_string()).unwrap();
|
||||||
edit_community.perform(self, msg.id)
|
edit_community.perform(self, msg.id)
|
||||||
},
|
},
|
||||||
|
UserOperation::FollowCommunity => {
|
||||||
|
let follow_community: FollowCommunity = serde_json::from_str(&data.to_string()).unwrap();
|
||||||
|
follow_community.perform(self, msg.id)
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let e = ErrorMessage {
|
let e = ErrorMessage {
|
||||||
op: "Unknown".to_string(),
|
op: "Unknown".to_string(),
|
||||||
|
@ -599,7 +613,7 @@ impl Perform for CreateCommunity {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let community_view = CommunityView::read(&conn, inserted_community.id).unwrap();
|
let community_view = CommunityView::read(&conn, inserted_community.id, Some(user_id)).unwrap();
|
||||||
|
|
||||||
serde_json::to_string(
|
serde_json::to_string(
|
||||||
&CommunityResponse {
|
&CommunityResponse {
|
||||||
|
@ -620,7 +634,20 @@ impl Perform for ListCommunities {
|
||||||
|
|
||||||
let conn = establish_connection();
|
let conn = establish_connection();
|
||||||
|
|
||||||
let communities: Vec<CommunityView> = CommunityView::list_all(&conn).unwrap();
|
let user_id: Option<i32> = match &self.auth {
|
||||||
|
Some(auth) => {
|
||||||
|
match Claims::decode(&auth) {
|
||||||
|
Ok(claims) => {
|
||||||
|
let user_id = claims.claims.id;
|
||||||
|
Some(user_id)
|
||||||
|
}
|
||||||
|
Err(_e) => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => None
|
||||||
|
};
|
||||||
|
|
||||||
|
let communities: Vec<CommunityView> = CommunityView::list_all(&conn, user_id).unwrap();
|
||||||
|
|
||||||
// Return the jwt
|
// Return the jwt
|
||||||
serde_json::to_string(
|
serde_json::to_string(
|
||||||
|
@ -767,7 +794,7 @@ impl Perform for GetPost {
|
||||||
|
|
||||||
let comments = CommentView::list(&conn, self.id, user_id).unwrap();
|
let comments = CommentView::list(&conn, self.id, user_id).unwrap();
|
||||||
|
|
||||||
let community = CommunityView::read(&conn, post_view.community_id).unwrap();
|
let community = CommunityView::read(&conn, post_view.community_id, user_id).unwrap();
|
||||||
|
|
||||||
let moderators = CommunityModeratorView::for_community(&conn, post_view.community_id).unwrap();
|
let moderators = CommunityModeratorView::for_community(&conn, post_view.community_id).unwrap();
|
||||||
|
|
||||||
|
@ -794,7 +821,20 @@ impl Perform for GetCommunity {
|
||||||
|
|
||||||
let conn = establish_connection();
|
let conn = establish_connection();
|
||||||
|
|
||||||
let community_view = match CommunityView::read(&conn, self.id) {
|
let user_id: Option<i32> = match &self.auth {
|
||||||
|
Some(auth) => {
|
||||||
|
match Claims::decode(&auth) {
|
||||||
|
Ok(claims) => {
|
||||||
|
let user_id = claims.claims.id;
|
||||||
|
Some(user_id)
|
||||||
|
}
|
||||||
|
Err(_e) => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => None
|
||||||
|
};
|
||||||
|
|
||||||
|
let community_view = match CommunityView::read(&conn, self.id, user_id) {
|
||||||
Ok(community) => community,
|
Ok(community) => community,
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
return self.error("Couldn't find Community");
|
return self.error("Couldn't find Community");
|
||||||
|
@ -917,7 +957,7 @@ impl Perform for EditComment {
|
||||||
// Verify its the creator
|
// Verify its the creator
|
||||||
let orig_comment = Comment::read(&conn, self.edit_id).unwrap();
|
let orig_comment = Comment::read(&conn, self.edit_id).unwrap();
|
||||||
if user_id != orig_comment.creator_id {
|
if user_id != orig_comment.creator_id {
|
||||||
return self.error("Incorrect creator.");
|
return self.error("Incorrect creator.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let comment_form = CommentForm {
|
let comment_form = CommentForm {
|
||||||
|
@ -1158,7 +1198,7 @@ impl Perform for EditPost {
|
||||||
// Verify its the creator
|
// Verify its the creator
|
||||||
let orig_post = Post::read(&conn, self.edit_id).unwrap();
|
let orig_post = Post::read(&conn, self.edit_id).unwrap();
|
||||||
if user_id != orig_post.creator_id {
|
if user_id != orig_post.creator_id {
|
||||||
return self.error("Incorrect creator.");
|
return self.error("Incorrect creator.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let post_form = PostForm {
|
let post_form = PostForm {
|
||||||
|
@ -1227,7 +1267,7 @@ impl Perform for EditCommunity {
|
||||||
let moderator_view = CommunityModeratorView::for_community(&conn, self.edit_id).unwrap();
|
let moderator_view = CommunityModeratorView::for_community(&conn, self.edit_id).unwrap();
|
||||||
let mod_ids: Vec<i32> = moderator_view.into_iter().map(|m| m.user_id).collect();
|
let mod_ids: Vec<i32> = moderator_view.into_iter().map(|m| m.user_id).collect();
|
||||||
if !mod_ids.contains(&user_id) {
|
if !mod_ids.contains(&user_id) {
|
||||||
return self.error("Incorrect creator.");
|
return self.error("Incorrect creator.");
|
||||||
};
|
};
|
||||||
|
|
||||||
let community_form = CommunityForm {
|
let community_form = CommunityForm {
|
||||||
|
@ -1246,7 +1286,7 @@ impl Perform for EditCommunity {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let community_view = CommunityView::read(&conn, self.edit_id).unwrap();
|
let community_view = CommunityView::read(&conn, self.edit_id, Some(user_id)).unwrap();
|
||||||
|
|
||||||
// Do the subscriber stuff here
|
// Do the subscriber stuff here
|
||||||
// let mut community_sent = post_view.clone();
|
// let mut community_sent = post_view.clone();
|
||||||
|
@ -1273,6 +1313,61 @@ impl Perform for EditCommunity {
|
||||||
community_out
|
community_out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Perform for FollowCommunity {
|
||||||
|
fn op_type(&self) -> UserOperation {
|
||||||
|
UserOperation::FollowCommunity
|
||||||
|
}
|
||||||
|
|
||||||
|
fn perform(&self, _chat: &mut ChatServer, _addr: usize) -> String {
|
||||||
|
|
||||||
|
let conn = establish_connection();
|
||||||
|
|
||||||
|
let claims = match Claims::decode(&self.auth) {
|
||||||
|
Ok(claims) => claims.claims,
|
||||||
|
Err(_e) => {
|
||||||
|
return self.error("Not logged in.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let user_id = claims.id;
|
||||||
|
|
||||||
|
let community_follower_form = CommunityFollowerForm {
|
||||||
|
community_id: self.community_id,
|
||||||
|
user_id: user_id
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.follow {
|
||||||
|
|
||||||
|
match CommunityFollower::follow(&conn, &community_follower_form) {
|
||||||
|
Ok(user) => user,
|
||||||
|
Err(_e) => {
|
||||||
|
return self.error("Community follower already exists.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
match CommunityFollower::ignore(&conn, &community_follower_form) {
|
||||||
|
Ok(user) => user,
|
||||||
|
Err(_e) => {
|
||||||
|
return self.error("Community follower already exists.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let community_view = CommunityView::read(&conn, self.community_id, Some(user_id)).unwrap();
|
||||||
|
|
||||||
|
serde_json::to_string(
|
||||||
|
&CommunityResponse {
|
||||||
|
op: self.op_type().to_string(),
|
||||||
|
community: community_view
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// impl Handler<Login> for ChatServer {
|
// impl Handler<Login> for ChatServer {
|
||||||
|
|
||||||
// type Result = MessageResult<Login>;
|
// type Result = MessageResult<Login>;
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Component, linkEvent } from 'inferno';
|
||||||
import { Link } from 'inferno-router';
|
import { Link } from 'inferno-router';
|
||||||
import { Subscription } from "rxjs";
|
import { Subscription } from "rxjs";
|
||||||
import { retryWhen, delay, take } from 'rxjs/operators';
|
import { retryWhen, delay, take } from 'rxjs/operators';
|
||||||
import { UserOperation, Community, Post as PostI, GetPostResponse, PostResponse, Comment, CommentForm as CommentFormI, CommentResponse, CommentLikeForm, CommentSortType, CreatePostLikeResponse, ListCommunitiesResponse } from '../interfaces';
|
import { UserOperation, Community, Post as PostI, GetPostResponse, PostResponse, Comment, CommentForm as CommentFormI, CommentResponse, CommentLikeForm, CommentSortType, CreatePostLikeResponse, ListCommunitiesResponse, CommunityResponse, FollowCommunityForm } from '../interfaces';
|
||||||
import { WebSocketService, UserService } from '../services';
|
import { WebSocketService, UserService } from '../services';
|
||||||
import { msgOp, hotRank,mdToHtml } from '../utils';
|
import { msgOp, hotRank,mdToHtml } from '../utils';
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ export class Communities extends Component<any, CommunitiesState> {
|
||||||
() => console.log('complete')
|
() => console.log('complete')
|
||||||
);
|
);
|
||||||
WebSocketService.Instance.listCommunities();
|
WebSocketService.Instance.listCommunities();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -50,6 +51,7 @@ export class Communities extends Component<any, CommunitiesState> {
|
||||||
<th class="text-right">Subscribers</th>
|
<th class="text-right">Subscribers</th>
|
||||||
<th class="text-right">Posts</th>
|
<th class="text-right">Posts</th>
|
||||||
<th class="text-right">Comments</th>
|
<th class="text-right">Comments</th>
|
||||||
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -61,6 +63,12 @@ export class Communities extends Component<any, CommunitiesState> {
|
||||||
<td class="text-right">{community.number_of_subscribers}</td>
|
<td class="text-right">{community.number_of_subscribers}</td>
|
||||||
<td class="text-right">{community.number_of_posts}</td>
|
<td class="text-right">{community.number_of_posts}</td>
|
||||||
<td class="text-right">{community.number_of_comments}</td>
|
<td class="text-right">{community.number_of_comments}</td>
|
||||||
|
<td class="text-right">
|
||||||
|
{community.subscribed
|
||||||
|
? <button class="btn btn-sm btn-secondary" onClick={linkEvent(community.id, this.handleUnsubscribe)}>Unsubscribe</button>
|
||||||
|
: <button class="btn btn-sm btn-secondary" onClick={linkEvent(community.id, this.handleSubscribe)}>Subscribe</button>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -70,8 +78,23 @@ export class Communities extends Component<any, CommunitiesState> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleUnsubscribe(communityId: number) {
|
||||||
|
let form: FollowCommunityForm = {
|
||||||
|
community_id: communityId,
|
||||||
|
follow: false
|
||||||
|
};
|
||||||
|
WebSocketService.Instance.followCommunity(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
handleSubscribe(communityId: number) {
|
||||||
|
let form: FollowCommunityForm = {
|
||||||
|
community_id: communityId,
|
||||||
|
follow: true
|
||||||
|
};
|
||||||
|
WebSocketService.Instance.followCommunity(form);
|
||||||
|
}
|
||||||
|
|
||||||
parseMessage(msg: any) {
|
parseMessage(msg: any) {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
let op: UserOperation = msgOp(msg);
|
let op: UserOperation = msgOp(msg);
|
||||||
|
@ -83,6 +106,12 @@ export class Communities extends Component<any, CommunitiesState> {
|
||||||
this.state.communities = res.communities;
|
this.state.communities = res.communities;
|
||||||
this.state.communities.sort((a, b) => b.number_of_subscribers - a.number_of_subscribers);
|
this.state.communities.sort((a, b) => b.number_of_subscribers - a.number_of_subscribers);
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
} else if (op == UserOperation.FollowCommunity) {
|
||||||
|
let res: CommunityResponse = msg;
|
||||||
|
let found = this.state.communities.find(c => c.id == res.community.id);
|
||||||
|
found.subscribed = res.community.subscribed;
|
||||||
|
found.number_of_subscribers = res.community.number_of_subscribers;
|
||||||
|
this.setState(this.state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,6 +147,11 @@ export class Community extends Component<any, State> {
|
||||||
let res: CommunityResponse = msg;
|
let res: CommunityResponse = msg;
|
||||||
this.state.community = res.community;
|
this.state.community = res.community;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
} else if (op == UserOperation.FollowCommunity) {
|
||||||
|
let res: CommunityResponse = msg;
|
||||||
|
this.state.community.subscribed = res.community.subscribed;
|
||||||
|
this.state.community.number_of_subscribers = res.community.number_of_subscribers;
|
||||||
|
this.setState(this.state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,6 +229,11 @@ export class Post extends Component<any, PostState> {
|
||||||
this.state.post.community_id = res.community.id;
|
this.state.post.community_id = res.community.id;
|
||||||
this.state.post.community_name = res.community.name;
|
this.state.post.community_name = res.community.name;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
|
} else if (op == UserOperation.FollowCommunity) {
|
||||||
|
let res: CommunityResponse = msg;
|
||||||
|
this.state.community.subscribed = res.community.subscribed;
|
||||||
|
this.state.community.number_of_subscribers = res.community.number_of_subscribers;
|
||||||
|
this.setState(this.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Component, linkEvent } from 'inferno';
|
import { Component, linkEvent } from 'inferno';
|
||||||
import { Link } from 'inferno-router';
|
import { Link } from 'inferno-router';
|
||||||
import { Community, CommunityUser } from '../interfaces';
|
import { Community, CommunityUser, FollowCommunityForm } from '../interfaces';
|
||||||
import { WebSocketService, UserService } from '../services';
|
import { WebSocketService, UserService } from '../services';
|
||||||
import { mdToHtml } from '../utils';
|
import { mdToHtml } from '../utils';
|
||||||
import { CommunityForm } from './community-form';
|
import { CommunityForm } from './community-form';
|
||||||
|
@ -61,7 +61,12 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
<li className="list-inline-item badge badge-light">{community.number_of_posts} Posts</li>
|
<li className="list-inline-item badge badge-light">{community.number_of_posts} Posts</li>
|
||||||
<li className="list-inline-item badge badge-light">{community.number_of_comments} Comments</li>
|
<li className="list-inline-item badge badge-light">{community.number_of_comments} Comments</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div><button type="button" class="btn btn-secondary mb-2">Subscribe</button></div>
|
<div>
|
||||||
|
{community.subscribed
|
||||||
|
? <button class="btn btn-sm btn-secondary" onClick={linkEvent(community.id, this.handleUnsubscribe)}>Unsubscribe</button>
|
||||||
|
: <button class="btn btn-sm btn-secondary" onClick={linkEvent(community.id, this.handleSubscribe)}>Subscribe</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
{community.description &&
|
{community.description &&
|
||||||
<div>
|
<div>
|
||||||
<hr />
|
<hr />
|
||||||
|
@ -96,6 +101,22 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
|
||||||
handleDeleteClick(i: Sidebar, event) {
|
handleDeleteClick(i: Sidebar, event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleUnsubscribe(communityId: number) {
|
||||||
|
let form: FollowCommunityForm = {
|
||||||
|
community_id: communityId,
|
||||||
|
follow: false
|
||||||
|
};
|
||||||
|
WebSocketService.Instance.followCommunity(form);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSubscribe(communityId: number) {
|
||||||
|
let form: FollowCommunityForm = {
|
||||||
|
community_id: communityId,
|
||||||
|
follow: true
|
||||||
|
};
|
||||||
|
WebSocketService.Instance.followCommunity(form);
|
||||||
|
}
|
||||||
|
|
||||||
private get amCreator(): boolean {
|
private get amCreator(): boolean {
|
||||||
return UserService.Instance.loggedIn && this.props.community.creator_id == UserService.Instance.user.id;
|
return UserService.Instance.loggedIn && this.props.community.creator_id == UserService.Instance.user.id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export enum UserOperation {
|
export enum UserOperation {
|
||||||
Login, Register, CreateCommunity, CreatePost, ListCommunities, ListCategories, GetPost, GetCommunity, CreateComment, EditComment, CreateCommentLike, GetPosts, CreatePostLike, EditPost, EditCommunity
|
Login, Register, CreateCommunity, CreatePost, ListCommunities, ListCategories, GetPost, GetCommunity, CreateComment, EditComment, CreateCommentLike, GetPosts, CreatePostLike, EditPost, EditCommunity, FollowCommunity
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface User {
|
export interface User {
|
||||||
|
@ -18,6 +18,8 @@ export interface CommunityUser {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Community {
|
export interface Community {
|
||||||
|
user_id?: number;
|
||||||
|
subscribed?: boolean;
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -171,6 +173,12 @@ export interface Category {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FollowCommunityForm {
|
||||||
|
community_id: number;
|
||||||
|
follow: boolean;
|
||||||
|
auth?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface LoginForm {
|
export interface LoginForm {
|
||||||
username_or_email: string;
|
username_or_email: string;
|
||||||
password: string;
|
password: string;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { wsUri } from '../env';
|
import { wsUri } from '../env';
|
||||||
import { LoginForm, RegisterForm, UserOperation, CommunityForm, PostForm, CommentForm, CommentLikeForm, GetPostsForm, CreatePostLikeForm } from '../interfaces';
|
import { LoginForm, RegisterForm, UserOperation, CommunityForm, PostForm, CommentForm, CommentLikeForm, GetPostsForm, CreatePostLikeForm, FollowCommunityForm } from '../interfaces';
|
||||||
import { webSocket } from 'rxjs/webSocket';
|
import { webSocket } from 'rxjs/webSocket';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { retryWhen, delay, take } from 'rxjs/operators';
|
import { retryWhen, delay, take } from 'rxjs/operators';
|
||||||
|
@ -42,8 +42,14 @@ export class WebSocketService {
|
||||||
this.subject.next(this.wsSendWrapper(UserOperation.EditCommunity, communityForm));
|
this.subject.next(this.wsSendWrapper(UserOperation.EditCommunity, communityForm));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public followCommunity(followCommunityForm: FollowCommunityForm) {
|
||||||
|
this.setAuth(followCommunityForm);
|
||||||
|
this.subject.next(this.wsSendWrapper(UserOperation.FollowCommunity, followCommunityForm));
|
||||||
|
}
|
||||||
|
|
||||||
public listCommunities() {
|
public listCommunities() {
|
||||||
this.subject.next(this.wsSendWrapper(UserOperation.ListCommunities, undefined));
|
let data = {auth: UserService.Instance.auth };
|
||||||
|
this.subject.next(this.wsSendWrapper(UserOperation.ListCommunities, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
public listCategories() {
|
public listCategories() {
|
||||||
|
@ -61,7 +67,8 @@ export class WebSocketService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public getCommunity(communityId: number) {
|
public getCommunity(communityId: number) {
|
||||||
this.subject.next(this.wsSendWrapper(UserOperation.GetCommunity, {id: communityId}));
|
let data = {id: communityId, auth: UserService.Instance.auth };
|
||||||
|
this.subject.next(this.wsSendWrapper(UserOperation.GetCommunity, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
public createComment(commentForm: CommentForm) {
|
public createComment(commentForm: CommentForm) {
|
||||||
|
|
Loading…
Reference in a new issue