summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorDessalines <tyhou13@gmx.com>2019-03-29 23:08:02 -0700
committerDessalines <tyhou13@gmx.com>2019-03-29 23:08:02 -0700
commit480b627ff516627c308090b43b4219d8070984a7 (patch)
treefe64ed6e4fc6be14bd2a414668ae8baf896945c4 /ui
parent743390113a7f2f95209acabbdc6c9aeb92b08008 (diff)
Adding comment sorting
- Fixes #15
Diffstat (limited to 'ui')
-rw-r--r--ui/src/components/post.tsx87
-rw-r--r--ui/src/interfaces.ts4
-rw-r--r--ui/src/main.css10
-rw-r--r--ui/src/services/WebSocketService.ts1
-rw-r--r--ui/src/utils.ts15
5 files changed, 96 insertions, 21 deletions
diff --git a/ui/src/components/post.tsx b/ui/src/components/post.tsx
index 1cd61ea3..feb815e5 100644
--- a/ui/src/components/post.tsx
+++ b/ui/src/components/post.tsx
@@ -1,9 +1,9 @@
import { Component, linkEvent } from 'inferno';
import { Subscription } from "rxjs";
import { retryWhen, delay, take } from 'rxjs/operators';
-import { UserOperation, Community, Post as PostI, PostResponse, Comment, CommentForm as CommentFormI, CommentResponse, CommentLikeForm, CreateCommentLikeResponse } from '../interfaces';
+import { UserOperation, Community, Post as PostI, PostResponse, Comment, CommentForm as CommentFormI, CommentResponse, CommentLikeForm, CreateCommentLikeResponse, CommentSortType } from '../interfaces';
import { WebSocketService, UserService } from '../services';
-import { msgOp } from '../utils';
+import { msgOp, hotRank } from '../utils';
import { MomentTime } from './moment-time';
interface CommentNodeI {
@@ -14,6 +14,7 @@ interface CommentNodeI {
interface State {
post: PostI;
comments: Array<Comment>;
+ commentSort: CommentSortType;
}
export class Post extends Component<any, State> {
@@ -27,7 +28,8 @@ export class Post extends Component<any, State> {
id: null,
published: null,
},
- comments: []
+ comments: [],
+ commentSort: CommentSortType.Hot
}
constructor(props, context) {
@@ -59,6 +61,7 @@ export class Post extends Component<any, State> {
<div class="col-12 col-sm-8 col-lg-7 mb-3">
{this.postHeader()}
<CommentForm postId={this.state.post.id} />
+ {this.sortRadios()}
{this.commentsTree()}
</div>
<div class="col-12 col-sm-4 col-lg-3 mb-3">
@@ -88,6 +91,28 @@ export class Post extends Component<any, State> {
)
}
+ sortRadios() {
+ return (
+ <div class="btn-group btn-group-toggle mb-3">
+ <label className={`btn btn-sm btn-secondary ${this.state.commentSort === CommentSortType.Hot && 'active'}`}>Hot
+ <input type="radio" value={CommentSortType.Hot}
+ checked={this.state.commentSort === CommentSortType.Hot}
+ onChange={linkEvent(this, this.handleCommentSortChange)} />
+ </label>
+ <label className={`btn btn-sm btn-secondary ${this.state.commentSort === CommentSortType.Top && 'active'}`}>Top
+ <input type="radio" value={CommentSortType.Top}
+ checked={this.state.commentSort === CommentSortType.Top}
+ onChange={linkEvent(this, this.handleCommentSortChange)} />
+ </label>
+ <label className={`btn btn-sm btn-secondary ${this.state.commentSort === CommentSortType.New && 'active'}`}>New
+ <input type="radio" value={CommentSortType.New}
+ checked={this.state.commentSort === CommentSortType.New}
+ onChange={linkEvent(this, this.handleCommentSortChange)} />
+ </label>
+ </div>
+ )
+ }
+
newComments() {
return (
<div class="sticky-top">
@@ -107,30 +132,52 @@ export class Post extends Component<any, State> {
</div>
);
}
-
- // buildCommentsTree(): Array<CommentNodeI> {
- buildCommentsTree(): any {
- let tree: Array<CommentNodeI> = this.createCommentsTree(this.state.comments);
- console.log(tree); // TODO this is redoing every time and it shouldn't
- return tree;
+
+ handleCommentSortChange(i: Post, event) {
+ i.state.commentSort = Number(event.target.value);
+ i.setState(i.state);
}
- private createCommentsTree(comments: Array<Comment>): Array<CommentNodeI> {
- let hashTable = {};
- for (let comment of comments) {
+ private buildCommentsTree(): Array<CommentNodeI> {
+ let map = new Map<number, CommentNodeI>();
+ for (let comment of this.state.comments) {
let node: CommentNodeI = {
- comment: comment
+ comment: comment,
+ children: []
};
- hashTable[comment.id] = { ...node, children : [] };
+ map.set(comment.id, { ...node });
}
let tree: Array<CommentNodeI> = [];
- for (let comment of comments) {
- if( comment.parent_id ) hashTable[comment.parent_id].children.push(hashTable[comment.id]);
- else tree.push(hashTable[comment.id]);
+ for (let comment of this.state.comments) {
+ if( comment.parent_id ) {
+ map.get(comment.parent_id).children.push(map.get(comment.id));
+ }
+ else {
+ tree.push(map.get(comment.id));
+ }
}
+
+ this.sortTree(tree);
+
return tree;
}
+ sortTree(tree: Array<CommentNodeI>) {
+
+ if (this.state.commentSort == CommentSortType.Top) {
+ tree.sort((a, b) => b.comment.score - a.comment.score);
+ } else if (this.state.commentSort == CommentSortType.New) {
+ tree.sort((a, b) => b.comment.published.localeCompare(a.comment.published));
+ } else if (this.state.commentSort == CommentSortType.Hot) {
+ tree.sort((a, b) => hotRank(b.comment) - hotRank(a.comment));
+ }
+
+ for (let node of tree) {
+ this.sortTree(node.children);
+ }
+
+ }
+
commentsTree() {
let nodes = this.buildCommentsTree();
return (
@@ -280,7 +327,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
}
</div>
{this.state.showReply && <CommentForm node={node} onReplyCancel={this.handleReplyCancel} />}
- {this.props.node.children && <CommentNodes nodes={this.props.node.children}/>}
+ {this.props.node.children && <CommentNodes nodes={this.props.node.children} />}
</div>
)
}
@@ -389,8 +436,8 @@ export class CommentForm extends Component<CommentFormProps, CommentFormState> {
</div>
<div class="row">
<div class="col-sm-12">
- <button type="submit" class="btn btn-secondary mr-2">{this.state.buttonTitle}</button>
- {this.props.node && <button type="button" class="btn btn-secondary" onClick={linkEvent(this, this.handleReplyCancel)}>Cancel</button>}
+ <button type="submit" class="btn btn-sm btn-secondary mr-2">{this.state.buttonTitle}</button>
+ {this.props.node && <button type="button" class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.handleReplyCancel)}>Cancel</button>}
</div>
</div>
</form>
diff --git a/ui/src/interfaces.ts b/ui/src/interfaces.ts
index c89a254e..95ea5e09 100644
--- a/ui/src/interfaces.ts
+++ b/ui/src/interfaces.ts
@@ -112,4 +112,8 @@ export interface LoginResponse {
jwt: string;
}
+export enum CommentSortType {
+ Hot, Top, New
+}
+
diff --git a/ui/src/main.css b/ui/src/main.css
index d0cb8baf..089a53b8 100644
--- a/ui/src/main.css
+++ b/ui/src/main.css
@@ -13,3 +13,13 @@ body {
.downvote:hover {
color: var(--danger);
}
+
+.form-control, .form-control:focus {
+ background-color: var(--secondary);
+ color: #fff;
+}
+
+.custom-select {
+ color: #fff;
+ background-color: var(--secondary);
+}
diff --git a/ui/src/services/WebSocketService.ts b/ui/src/services/WebSocketService.ts
index b35d97a1..1ea207f4 100644
--- a/ui/src/services/WebSocketService.ts
+++ b/ui/src/services/WebSocketService.ts
@@ -88,5 +88,6 @@ export class WebSocketService {
window.onbeforeunload = (e => {
WebSocketService.Instance.subject.unsubscribe();
+ WebSocketService.Instance.subject = null;
});
diff --git a/ui/src/utils.ts b/ui/src/utils.ts
index 02c1afbf..1d490a30 100644
--- a/ui/src/utils.ts
+++ b/ui/src/utils.ts
@@ -1,4 +1,4 @@
-import { UserOperation } from './interfaces';
+import { UserOperation, Comment } from './interfaces';
export let repoUrl = 'https://github.com/dessalines/rust-reddit-fediverse';
export let wsUri = (window.location.protocol=='https:'&&'wss://'||'ws://')+window.location.host + '/service/ws/';
@@ -8,3 +8,16 @@ export function msgOp(msg: any): UserOperation {
return UserOperation[opStr];
}
+export function hotRank(comment: Comment): number {
+ // Rank = ScaleFactor * sign(Score) * log(1 + abs(Score)) / (Time + 2)^Gravity
+
+ let date: Date = new Date(comment.published + 'Z'); // Add Z to convert from UTC date
+ let now: Date = new Date();
+ let hoursElapsed: number = (now.getTime() - date.getTime()) / 36e5;
+
+ let rank = (10000 * Math.sign(comment.score) * Math.log10(1 + Math.abs(comment.score))) / Math.pow(hoursElapsed + 2, 1.8);
+
+ // console.log(`Comment: ${comment.content}\nRank: ${rank}\nScore: ${comment.score}\nHours: ${hoursElapsed}`);
+
+ return rank;
+}