summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/migrations/2019-04-03-155205_create_community_view/up.sql6
-rw-r--r--server/src/actions/community_view.rs46
-rw-r--r--server/src/websocket_server/server.rs22
-rw-r--r--ui/src/components/communities.tsx1
-rw-r--r--ui/src/components/community.tsx8
-rw-r--r--ui/src/components/post.tsx7
-rw-r--r--ui/src/components/sidebar.tsx17
-rw-r--r--ui/src/interfaces.ts11
8 files changed, 105 insertions, 13 deletions
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 d26a313e..f2f4a766 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 03d822ab..eafda161 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<Vec<Self>, Error> {
+ use actions::community_view::community_moderator_view::dsl::*;
+ community_moderator_view.filter(community_id.eq(from_community_id)).load::<Self>(conn)
+ }
+
+ pub fn for_user(conn: &PgConnection, from_user_id: i32) -> Result<Vec<Self>, Error> {
+ use actions::community_view::community_moderator_view::dsl::*;
+ community_moderator_view.filter(user_id.eq(from_user_id)).load::<Self>(conn)
+ }
+}
+
diff --git a/server/src/websocket_server/server.rs b/server/src/websocket_server/server.rs
index e5e117ef..4c13aade 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<CommentView>,
- community: CommunityView
+ community: CommunityView,
+ moderators: Vec<CommunityModeratorView>
}
#[derive(Serialize, Deserialize)]
@@ -179,7 +180,8 @@ pub struct GetCommunity {
#[derive(Serialize, Deserialize)]
pub struct GetCommunityResponse {
op: String,
- community: CommunityView
+ community: CommunityView,
+ moderators: Vec<CommunityModeratorView>
}
#[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 411aebe1..921ef157 100644
--- a/ui/src/components/communities.tsx
+++ b/ui/src/components/communities.tsx
@@ -32,6 +32,7 @@ export class Communities extends Component<any, CommunitiesState> {
render() {
return (
<div class="container-fluid">
+ <h4>Communities</h4>
<div class="table-responsive">
<table class="table table-sm table-hover" data-sortable>
<thead>
diff --git a/ui/src/components/community.tsx b/ui/src/components/community.tsx
index 820db90d..5505e01d 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<CommunityUser>;
posts: Array<Post>;
sortType: ListingSortType;
}
@@ -29,8 +30,10 @@ export class Community extends Component<any, State> {
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<any, State> {
}
</div>
<div class="col-12 col-sm-2 col-lg-3">
- <Sidebar community={this.state.community} />
+ <Sidebar community={this.state.community} moderators={this.state.moderators} />
</div>
</div>
</div>
@@ -126,6 +129,7 @@ export class Community extends Component<any, State> {
} 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 457b286e..f36ad979 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<Comment>;
commentSort: CommentSortType;
community: Community;
+ moderators: Array<CommunityUser>;
}
export class Post extends Component<any, PostState> {
@@ -30,6 +31,7 @@ export class Post extends Component<any, PostState> {
comments: [],
commentSort: CommentSortType.Hot,
community: null,
+ moderators: []
}
constructor(props, context) {
@@ -118,7 +120,7 @@ export class Post extends Component<any, PostState> {
sidebar() {
return (
<div class="sticky-top">
- <Sidebar community={this.state.community} />
+ <Sidebar community={this.state.community} moderators={this.state.moderators} />
</div>
);
}
@@ -188,6 +190,7 @@ export class Post extends Component<any, PostState> {
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 c8e80de6..e8a2f410 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<CommunityUser>;
}
interface SidebarState {
@@ -22,14 +24,23 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
<div>
<h4>{community.title}</h4>
<ul class="list-inline">
- <li className="list-inline-item badge badge-light">{community.category_name}</li>
+ <li className="list-inline-item"><Link className="badge badge-light" to="/communities">{community.category_name}</Link></li>
<li className="list-inline-item badge badge-light">{community.number_of_subscribers} Subscribers</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>
</ul>
<div><button type="button" class="btn btn-secondary mb-2">Subscribe</button></div>
+ {community.description &&
+ <div>
+ <hr />
+ <div className="md-div" dangerouslySetInnerHTML={mdToHtml(community.description)} />
+ </div>
+ }
<hr />
- {community.description && <div className="md-div" dangerouslySetInnerHTML={mdToHtml(community.description)} />}
+ <h5>Moderators</h5>
+ {this.props.moderators.map(mod =>
+ <Link to={`/user/${mod.user_id}`}>{mod.user_name}</Link>
+ )}
</div>
);
}
diff --git a/ui/src/interfaces.ts b/ui/src/interfaces.ts
index 7edcbd8e..f202f7ac 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<CommunityUser>;
}
export interface ListCommunitiesResponse {
@@ -82,6 +92,7 @@ export interface GetPostResponse {
post: Post;
comments: Array<Comment>;
community: Community;
+ moderators: Array<CommunityUser>;
}
export interface PostResponse {