summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/src/components/community.tsx14
-rw-r--r--ui/src/components/create-community.tsx65
-rw-r--r--ui/src/components/post.tsx19
-rw-r--r--ui/src/components/sidebar.tsx33
-rw-r--r--ui/src/interfaces.ts24
-rw-r--r--ui/src/services/WebSocketService.ts4
6 files changed, 137 insertions, 22 deletions
diff --git a/ui/src/components/community.tsx b/ui/src/components/community.tsx
index 5bef29bb..820db90d 100644
--- a/ui/src/components/community.tsx
+++ b/ui/src/components/community.tsx
@@ -6,7 +6,8 @@ import { UserOperation, Community as CommunityI, CommunityResponse, Post, GetPos
import { WebSocketService, UserService } from '../services';
import { MomentTime } from './moment-time';
import { PostListing } from './post-listing';
-import { msgOp } from '../utils';
+import { Sidebar } from './sidebar';
+import { msgOp, mdToHtml } from '../utils';
interface State {
community: CommunityI;
@@ -21,6 +22,13 @@ export class Community extends Component<any, State> {
community: {
id: null,
name: null,
+ title: null,
+ category_id: null,
+ category_name: null,
+ creator_id: null,
+ creator_name: null,
+ number_of_subscribers: null,
+ number_of_posts: null,
published: null
},
posts: [],
@@ -70,10 +78,8 @@ export class Community extends Component<any, State> {
}
</div>
<div class="col-12 col-sm-2 col-lg-3">
- Sidebar
+ <Sidebar community={this.state.community} />
</div>
-
-
</div>
</div>
)
diff --git a/ui/src/components/create-community.tsx b/ui/src/components/create-community.tsx
index 7e56fcda..c5149f0a 100644
--- a/ui/src/components/create-community.tsx
+++ b/ui/src/components/create-community.tsx
@@ -1,7 +1,7 @@
import { Component, linkEvent } from 'inferno';
import { Subscription } from "rxjs";
import { retryWhen, delay, take } from 'rxjs/operators';
-import { CommunityForm, UserOperation } from '../interfaces';
+import { CommunityForm, UserOperation, Category, ListCategoriesResponse } from '../interfaces';
import { WebSocketService, UserService } from '../services';
import { msgOp } from '../utils';
@@ -9,6 +9,7 @@ import { Community } from '../interfaces';
interface State {
communityForm: CommunityForm;
+ categories: Array<Category>;
}
export class CreateCommunity extends Component<any, State> {
@@ -17,14 +18,17 @@ export class CreateCommunity extends Component<any, State> {
private emptyState: State = {
communityForm: {
name: null,
- }
+ title: null,
+ category_id: null
+ },
+ categories: []
}
constructor(props, context) {
super(props, context);
this.state = this.emptyState;
-
+
this.subscription = WebSocketService.Instance.subject
.pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
.subscribe(
@@ -32,6 +36,8 @@ export class CreateCommunity extends Component<any, State> {
(err) => console.error(err),
() => console.log("complete")
);
+
+ WebSocketService.Instance.listCategories();
}
componentWillUnmount() {
@@ -62,6 +68,28 @@ export class CreateCommunity extends Component<any, State> {
</div>
</div>
<div class="form-group row">
+ <label class="col-sm-2 col-form-label">Title / Headline</label>
+ <div class="col-sm-10">
+ <input type="text" value={this.state.communityForm.title} onInput={linkEvent(this, this.handleCommunityTitleChange)} class="form-control" required minLength={3} />
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-2 col-form-label">Description / Sidebar</label>
+ <div class="col-sm-10">
+ <textarea value={this.state.communityForm.description} onInput={linkEvent(this, this.handleCommunityDescriptionChange)} class="form-control" rows={6} />
+ </div>
+ </div>
+ <div class="form-group row">
+ <label class="col-sm-2 col-form-label">Category</label>
+ <div class="col-sm-10">
+ <select class="form-control" value={this.state.communityForm.category_id} onInput={linkEvent(this, this.handleCommunityCategoryChange)}>
+ {this.state.categories.map(category =>
+ <option value={category.id}>{category.name}</option>
+ )}
+ </select>
+ </div>
+ </div>
+ <div class="form-group row">
<div class="col-sm-10">
<button type="submit" class="btn btn-secondary">Create</button>
</div>
@@ -70,7 +98,7 @@ export class CreateCommunity extends Component<any, State> {
</div>
);
}
-
+
handleCreateCommunitySubmit(i: CreateCommunity, event) {
event.preventDefault();
WebSocketService.Instance.createCommunity(i.state.communityForm);
@@ -78,6 +106,22 @@ export class CreateCommunity extends Component<any, State> {
handleCommunityNameChange(i: CreateCommunity, event) {
i.state.communityForm.name = event.target.value;
+ i.setState(i.state);
+ }
+
+ handleCommunityTitleChange(i: CreateCommunity, event) {
+ i.state.communityForm.title = event.target.value;
+ i.setState(i.state);
+ }
+
+ handleCommunityDescriptionChange(i: CreateCommunity, event) {
+ i.state.communityForm.description = event.target.value;
+ i.setState(i.state);
+ }
+
+ handleCommunityCategoryChange(i: CreateCommunity, event) {
+ i.state.communityForm.category_id = Number(event.target.value);
+ i.setState(i.state);
}
parseMessage(msg: any) {
@@ -86,11 +130,14 @@ export class CreateCommunity extends Component<any, State> {
if (msg.error) {
alert(msg.error);
return;
- } else {
- if (op == UserOperation.CreateCommunity) {
- let community: Community = msg.community;
- this.props.history.push(`/community/${community.id}`);
- }
+ } else if (op == UserOperation.ListCategories){
+ let res: ListCategoriesResponse = msg;
+ this.state.categories = res.categories;
+ this.state.communityForm.category_id = res.categories[0].id;
+ this.setState(this.state);
+ } else if (op == UserOperation.CreateCommunity) {
+ let community: Community = msg.community;
+ this.props.history.push(`/community/${community.id}`);
}
}
diff --git a/ui/src/components/post.tsx b/ui/src/components/post.tsx
index 68ba9634..457b286e 100644
--- a/ui/src/components/post.tsx
+++ b/ui/src/components/post.tsx
@@ -2,11 +2,12 @@ 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, CreateCommentLikeResponse, CommentSortType, CreatePostLikeResponse } from '../interfaces';
+import { UserOperation, Community, Post as PostI, GetPostResponse, PostResponse, Comment, CommentForm as CommentFormI, CommentResponse, CommentLikeForm, CommentSortType, CreatePostLikeResponse } from '../interfaces';
import { WebSocketService, UserService } from '../services';
import { msgOp, hotRank,mdToHtml } from '../utils';
import { MomentTime } from './moment-time';
import { PostListing } from './post-listing';
+import { Sidebar } from './sidebar';
import * as autosize from 'autosize';
interface CommentNodeI {
@@ -14,19 +15,21 @@ interface CommentNodeI {
children?: Array<CommentNodeI>;
};
-interface State {
+interface PostState {
post: PostI;
comments: Array<Comment>;
commentSort: CommentSortType;
+ community: Community;
}
-export class Post extends Component<any, State> {
+export class Post extends Component<any, PostState> {
private subscription: Subscription;
- private emptyState: State = {
+ private emptyState: PostState = {
post: null,
comments: [],
- commentSort: CommentSortType.Hot
+ commentSort: CommentSortType.Hot,
+ community: null,
}
constructor(props, context) {
@@ -115,8 +118,7 @@ export class Post extends Component<any, State> {
sidebar() {
return (
<div class="sticky-top">
- <h5>Sidebar</h5>
- <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+ <Sidebar community={this.state.community} />
</div>
);
}
@@ -185,6 +187,7 @@ export class Post extends Component<any, State> {
let res: GetPostResponse = msg;
this.state.post = res.post;
this.state.comments = res.comments;
+ this.state.community = res.community;
this.setState(this.state);
} else if (op == UserOperation.CreateComment) {
let res: CommentResponse = msg;
@@ -198,7 +201,7 @@ export class Post extends Component<any, State> {
this.setState(this.state);
}
else if (op == UserOperation.CreateCommentLike) {
- let res: CreateCommentLikeResponse = msg;
+ let res: CommentResponse = msg;
let found: Comment = this.state.comments.find(c => c.id === res.comment.id);
found.score = res.comment.score;
found.upvotes = res.comment.upvotes;
diff --git a/ui/src/components/sidebar.tsx b/ui/src/components/sidebar.tsx
new file mode 100644
index 00000000..8a88b870
--- /dev/null
+++ b/ui/src/components/sidebar.tsx
@@ -0,0 +1,33 @@
+import { Component, linkEvent } from 'inferno';
+import { Community } from '../interfaces';
+import { mdToHtml } from '../utils';
+
+interface SidebarProps {
+ community: Community;
+}
+
+interface SidebarState {
+}
+
+export class Sidebar extends Component<SidebarProps, SidebarState> {
+
+ constructor(props, context) {
+ super(props, context);
+ }
+
+
+ render() {
+ let community = this.props.community;
+ return (
+ <div>
+ <h4>{community.title}</h4>
+ <div><button type="button" class="btn btn-secondary mb-2">Subscribe</button></div>
+ <div className="badge badge-light">{community.category_name}</div>
+ <div>{community.number_of_subscribers} Subscribers</div>
+ <div>{community.number_of_posts} Posts</div>
+ <hr />
+ {community.description && <div className="md-div" dangerouslySetInnerHTML={mdToHtml(community.description)} />}
+ </div>
+ );
+ }
+}
diff --git a/ui/src/interfaces.ts b/ui/src/interfaces.ts
index e21edf77..5d5ea12a 100644
--- a/ui/src/interfaces.ts
+++ b/ui/src/interfaces.ts
@@ -1,5 +1,5 @@
export enum UserOperation {
- Login, Register, CreateCommunity, CreatePost, ListCommunities, GetPost, GetCommunity, CreateComment, EditComment, CreateCommentLike, GetPosts, CreatePostLike, EditPost, EditCommunity
+ Login, Register, CreateCommunity, CreatePost, ListCommunities, ListCategories, GetPost, GetCommunity, CreateComment, EditComment, CreateCommentLike, GetPosts, CreatePostLike, EditPost, EditCommunity
}
export interface User {
@@ -11,12 +11,23 @@ export interface User {
export interface Community {
id: number;
name: string;
+ title: string;
+ description?: string;
+ creator_id: number;
+ creator_name: string;
+ category_id: number;
+ category_name: string;
+ number_of_subscribers: number;
+ number_of_posts: number;
published: string;
updated?: string;
}
export interface CommunityForm {
name: string;
+ title: string;
+ description?: string,
+ category_id: number,
auth?: string;
}
@@ -30,6 +41,11 @@ export interface ListCommunitiesResponse {
communities: Array<Community>;
}
+export interface ListCategoriesResponse {
+ op: string;
+ categories: Array<Category>;
+}
+
export interface Post {
user_id?: number;
my_vote?: number;
@@ -64,6 +80,7 @@ export interface GetPostResponse {
op: string;
post: Post;
comments: Array<Comment>;
+ community: Community;
}
export interface PostResponse {
@@ -130,6 +147,11 @@ export interface CreatePostLikeResponse {
post: Post;
}
+export interface Category {
+ id: number;
+ name: string;
+}
+
export interface LoginForm {
username_or_email: string;
password: string;
diff --git a/ui/src/services/WebSocketService.ts b/ui/src/services/WebSocketService.ts
index c1fdb73b..c99cfcfa 100644
--- a/ui/src/services/WebSocketService.ts
+++ b/ui/src/services/WebSocketService.ts
@@ -41,6 +41,10 @@ export class WebSocketService {
this.subject.next(this.wsSendWrapper(UserOperation.ListCommunities, undefined));
}
+ public listCategories() {
+ this.subject.next(this.wsSendWrapper(UserOperation.ListCategories, undefined));
+ }
+
public createPost(postForm: PostForm) {
this.setAuth(postForm);
this.subject.next(this.wsSendWrapper(UserOperation.CreatePost, postForm));