diff --git a/server/migrations/2019-04-03-155205_create_community_view/up.sql b/server/migrations/2019-04-03-155205_create_community_view/up.sql index d26a313e4..f2f4a7664 100644 --- a/server/migrations/2019-04-03-155205_create_community_view/up.sql +++ b/server/migrations/2019-04-03-155205_create_community_view/up.sql @@ -9,10 +9,12 @@ from community c; create view community_moderator_view as select *, -(select name from user_ u where cm.user_id = u.id) as user_name +(select name from user_ u where cm.user_id = u.id) as user_name, +(select name from community c where cm.community_id = c.id) as community_name from community_moderator cm; create view community_follower_view as select *, -(select name from user_ u where cf.user_id = u.id) as user_name +(select name from user_ u where cf.user_id = u.id) as user_name, +(select name from community c where cf.community_id = c.id) as community_name from community_follower cf; diff --git a/server/src/actions/community_view.rs b/server/src/actions/community_view.rs index 03d822abf..eafda161d 100644 --- a/server/src/actions/community_view.rs +++ b/server/src/actions/community_view.rs @@ -21,6 +21,28 @@ table! { } } +table! { + community_moderator_view (id) { + id -> Int4, + community_id -> Int4, + user_id -> Int4, + published -> Timestamp, + user_name -> Varchar, + community_name -> Varchar, + } +} + +table! { + community_follower_view (id) { + id -> Int4, + community_id -> Int4, + user_id -> Int4, + published -> Timestamp, + user_name -> Varchar, + community_name -> Varchar, + } +} + #[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize,QueryableByName,Clone)] #[table_name="community_view"] pub struct CommunityView { @@ -51,3 +73,27 @@ impl CommunityView { } } + +#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize,QueryableByName,Clone)] +#[table_name="community_moderator_view"] +pub struct CommunityModeratorView { + pub id: i32, + pub community_id: i32, + pub user_id: i32, + pub published: chrono::NaiveDateTime, + pub user_name : String, + pub community_name: String, +} + +impl CommunityModeratorView { + pub fn for_community(conn: &PgConnection, from_community_id: i32) -> Result, Error> { + use actions::community_view::community_moderator_view::dsl::*; + community_moderator_view.filter(community_id.eq(from_community_id)).load::(conn) + } + + pub fn for_user(conn: &PgConnection, from_user_id: i32) -> Result, Error> { + use actions::community_view::community_moderator_view::dsl::*; + community_moderator_view.filter(user_id.eq(from_user_id)).load::(conn) + } +} + diff --git a/server/src/websocket_server/server.rs b/server/src/websocket_server/server.rs index e5e117ef1..4c13aadee 100644 --- a/server/src/websocket_server/server.rs +++ b/server/src/websocket_server/server.rs @@ -153,7 +153,8 @@ pub struct GetPostResponse { op: String, post: PostView, comments: Vec, - community: CommunityView + community: CommunityView, + moderators: Vec } #[derive(Serialize, Deserialize)] @@ -179,7 +180,8 @@ pub struct GetCommunity { #[derive(Serialize, Deserialize)] pub struct GetCommunityResponse { op: String, - community: CommunityView + community: CommunityView, + moderators: Vec } #[derive(Serialize, Deserialize)] @@ -762,13 +764,16 @@ impl Perform for GetPost { let community = CommunityView::read(&conn, post_view.community_id).unwrap(); + let moderators = CommunityModeratorView::for_community(&conn, post_view.community_id).unwrap(); + // Return the jwt serde_json::to_string( &GetPostResponse { op: self.op_type().to_string(), post: post_view, comments: comments, - community: community + community: community, + moderators: moderators } ) .unwrap() @@ -791,11 +796,20 @@ impl Perform for GetCommunity { } }; + + let moderators = match CommunityModeratorView::for_community(&conn, self.id) { + Ok(moderators) => moderators, + Err(_e) => { + return self.error("Couldn't find Community"); + } + }; + // Return the jwt serde_json::to_string( &GetCommunityResponse { op: self.op_type().to_string(), - community: community_view + community: community_view, + moderators: moderators } ) .unwrap() diff --git a/ui/src/components/communities.tsx b/ui/src/components/communities.tsx index 411aebe16..921ef157f 100644 --- a/ui/src/components/communities.tsx +++ b/ui/src/components/communities.tsx @@ -32,6 +32,7 @@ export class Communities extends Component { render() { return (
+

Communities

diff --git a/ui/src/components/community.tsx b/ui/src/components/community.tsx index 820db90d6..5505e01d6 100644 --- a/ui/src/components/community.tsx +++ b/ui/src/components/community.tsx @@ -2,7 +2,7 @@ import { Component, linkEvent } from 'inferno'; import { Link } from 'inferno-router'; import { Subscription } from "rxjs"; import { retryWhen, delay, take } from 'rxjs/operators'; -import { UserOperation, Community as CommunityI, CommunityResponse, Post, GetPostsForm, ListingSortType, ListingType, GetPostsResponse, CreatePostLikeForm, CreatePostLikeResponse} from '../interfaces'; +import { UserOperation, Community as CommunityI, CommunityResponse, Post, GetPostsForm, ListingSortType, ListingType, GetPostsResponse, CreatePostLikeForm, CreatePostLikeResponse, CommunityUser} from '../interfaces'; import { WebSocketService, UserService } from '../services'; import { MomentTime } from './moment-time'; import { PostListing } from './post-listing'; @@ -11,6 +11,7 @@ import { msgOp, mdToHtml } from '../utils'; interface State { community: CommunityI; + moderators: Array; posts: Array; sortType: ListingSortType; } @@ -29,8 +30,10 @@ export class Community extends Component { creator_name: null, number_of_subscribers: null, number_of_posts: null, + number_of_comments: null, published: null }, + moderators: [], posts: [], sortType: ListingSortType.Hot, } @@ -78,7 +81,7 @@ export class Community extends Component { }
- +
@@ -126,6 +129,7 @@ export class Community extends Component { } else if (op == UserOperation.GetCommunity) { let res: CommunityResponse = msg; this.state.community = res.community; + this.state.moderators = res.moderators; this.setState(this.state); } else if (op == UserOperation.GetPosts) { let res: GetPostsResponse = msg; diff --git a/ui/src/components/post.tsx b/ui/src/components/post.tsx index 457b286e0..f36ad9796 100644 --- a/ui/src/components/post.tsx +++ b/ui/src/components/post.tsx @@ -2,7 +2,7 @@ import { Component, linkEvent } from 'inferno'; import { Link } from 'inferno-router'; import { Subscription } from "rxjs"; import { retryWhen, delay, take } from 'rxjs/operators'; -import { UserOperation, Community, Post as PostI, GetPostResponse, PostResponse, Comment, CommentForm as CommentFormI, CommentResponse, CommentLikeForm, CommentSortType, CreatePostLikeResponse } from '../interfaces'; +import { UserOperation, Community, Post as PostI, GetPostResponse, PostResponse, Comment, CommentForm as CommentFormI, CommentResponse, CommentLikeForm, CommentSortType, CreatePostLikeResponse, CommunityUser } from '../interfaces'; import { WebSocketService, UserService } from '../services'; import { msgOp, hotRank,mdToHtml } from '../utils'; import { MomentTime } from './moment-time'; @@ -20,6 +20,7 @@ interface PostState { comments: Array; commentSort: CommentSortType; community: Community; + moderators: Array; } export class Post extends Component { @@ -30,6 +31,7 @@ export class Post extends Component { comments: [], commentSort: CommentSortType.Hot, community: null, + moderators: [] } constructor(props, context) { @@ -118,7 +120,7 @@ export class Post extends Component { sidebar() { return (
- +
); } @@ -188,6 +190,7 @@ export class Post extends Component { this.state.post = res.post; this.state.comments = res.comments; this.state.community = res.community; + this.state.moderators = res.moderators; this.setState(this.state); } else if (op == UserOperation.CreateComment) { let res: CommentResponse = msg; diff --git a/ui/src/components/sidebar.tsx b/ui/src/components/sidebar.tsx index c8e80de62..e8a2f4106 100644 --- a/ui/src/components/sidebar.tsx +++ b/ui/src/components/sidebar.tsx @@ -1,9 +1,11 @@ import { Component, linkEvent } from 'inferno'; -import { Community } from '../interfaces'; +import { Link } from 'inferno-router'; +import { Community, CommunityUser } from '../interfaces'; import { mdToHtml } from '../utils'; interface SidebarProps { community: Community; + moderators: Array; } interface SidebarState { @@ -22,14 +24,23 @@ export class Sidebar extends Component {

{community.title}

    -
  • {community.category_name}
  • +
  • {community.category_name}
  • {community.number_of_subscribers} Subscribers
  • {community.number_of_posts} Posts
  • {community.number_of_comments} Comments
+ {community.description && +
+
+
+
+ }
- {community.description &&
} +
Moderators
+ {this.props.moderators.map(mod => + {mod.user_name} + )}
); } diff --git a/ui/src/interfaces.ts b/ui/src/interfaces.ts index 7edcbd8eb..f202f7ac5 100644 --- a/ui/src/interfaces.ts +++ b/ui/src/interfaces.ts @@ -8,6 +8,15 @@ export interface User { username: string; } +export interface CommunityUser { + id: number; + user_id: number; + user_name: string; + community_id: number; + community_name: string; + published: string; +} + export interface Community { id: number; name: string; @@ -35,6 +44,7 @@ export interface CommunityForm { export interface CommunityResponse { op: string; community: Community; + moderators: Array; } export interface ListCommunitiesResponse { @@ -82,6 +92,7 @@ export interface GetPostResponse { post: Post; comments: Array; community: Community; + moderators: Array; } export interface PostResponse {