diff options
author | Dessalines <tyhou13@gmx.com> | 2020-02-07 23:05:15 -0500 |
---|---|---|
committer | Dessalines <tyhou13@gmx.com> | 2020-02-07 23:05:15 -0500 |
commit | ecd10482a6815fc3b51b2da7cd5f494c01c385e6 (patch) | |
tree | 16d25467ba4224bfd807122806d1f77ddfaee6e8 /ui/src | |
parent | 779a72581c4c1dee846296cd0f3ea761914aedc6 (diff) |
Add new comments views to main and community pages. Fixes #480
Diffstat (limited to 'ui/src')
-rw-r--r-- | ui/src/components/comment-node.tsx | 10 | ||||
-rw-r--r-- | ui/src/components/comment-nodes.tsx | 2 | ||||
-rw-r--r-- | ui/src/components/community.tsx | 165 | ||||
-rw-r--r-- | ui/src/components/data-type-select.tsx | 65 | ||||
-rw-r--r-- | ui/src/components/main.tsx | 209 | ||||
-rw-r--r-- | ui/src/components/user.tsx | 30 | ||||
-rw-r--r-- | ui/src/index.tsx | 4 | ||||
-rw-r--r-- | ui/src/interfaces.ts | 22 | ||||
-rw-r--r-- | ui/src/services/WebSocketService.ts | 6 | ||||
-rw-r--r-- | ui/src/translations/en.ts | 1 | ||||
-rw-r--r-- | ui/src/utils.ts | 32 |
11 files changed, 435 insertions, 111 deletions
diff --git a/ui/src/components/comment-node.tsx b/ui/src/components/comment-node.tsx index 3296a5c8..a67b1c35 100644 --- a/ui/src/components/comment-node.tsx +++ b/ui/src/components/comment-node.tsx @@ -58,7 +58,9 @@ interface CommentNodeProps { markable?: boolean; moderators: Array<CommunityUser>; admins: Array<UserView>; + // TODO is this necessary, can't I get it from the node itself? postCreatorId?: number; + showCommunity?: boolean; } export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { @@ -205,6 +207,14 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> { <span>) </span> </span> </li> + {this.props.showCommunity && ( + <li className="list-inline-item"> + <span> {i18n.t('to')} </span> + <Link to={`/c/${node.comment.community_name}`}> + {node.comment.community_name} + </Link> + </li> + )} <li className="list-inline-item"> <span> <MomentTime data={node.comment} /> diff --git a/ui/src/components/comment-nodes.tsx b/ui/src/components/comment-nodes.tsx index 18faf1ac..fb700cc4 100644 --- a/ui/src/components/comment-nodes.tsx +++ b/ui/src/components/comment-nodes.tsx @@ -17,6 +17,7 @@ interface CommentNodesProps { viewOnly?: boolean; locked?: boolean; markable?: boolean; + showCommunity?: boolean; } export class CommentNodes extends Component< @@ -40,6 +41,7 @@ export class CommentNodes extends Component< admins={this.props.admins} postCreatorId={this.props.postCreatorId} markable={this.props.markable} + showCommunity={this.props.showCommunity} /> ))} </div> diff --git a/ui/src/components/community.tsx b/ui/src/components/community.tsx index 069f9158..3e04a8bf 100644 --- a/ui/src/components/community.tsx +++ b/ui/src/components/community.tsx @@ -13,17 +13,31 @@ import { GetPostsForm, GetCommunityForm, ListingType, + DataType, GetPostsResponse, PostResponse, AddModToCommunityResponse, BanFromCommunityResponse, + Comment, + GetCommentsForm, + GetCommentsResponse, + CommentResponse, WebSocketJsonResponse, } from '../interfaces'; -import { WebSocketService, UserService } from '../services'; +import { WebSocketService } from '../services'; import { PostListings } from './post-listings'; +import { CommentNodes } from './comment-nodes'; import { SortSelect } from './sort-select'; +import { DataTypeSelect } from './data-type-select'; import { Sidebar } from './sidebar'; -import { wsJsonToRes, routeSortTypeToEnum, fetchLimit, toast } from '../utils'; +import { + wsJsonToRes, + fetchLimit, + toast, + getPageFromProps, + getSortTypeFromProps, + getDataTypeFromProps, +} from '../utils'; import { i18n } from '../i18next'; interface State { @@ -35,6 +49,8 @@ interface State { online: number; loading: boolean; posts: Array<Post>; + comments: Array<Comment>; + dataType: DataType; sort: SortType; page: number; } @@ -65,27 +81,18 @@ export class Community extends Component<any, State> { online: null, loading: true, posts: [], - sort: this.getSortTypeFromProps(this.props), - page: this.getPageFromProps(this.props), + comments: [], + dataType: getDataTypeFromProps(this.props), + sort: getSortTypeFromProps(this.props), + page: getPageFromProps(this.props), }; - getSortTypeFromProps(props: any): SortType { - return props.match.params.sort - ? routeSortTypeToEnum(props.match.params.sort) - : UserService.Instance.user - ? UserService.Instance.user.default_sort_type - : SortType.Hot; - } - - getPageFromProps(props: any): number { - return props.match.params.page ? Number(props.match.params.page) : 1; - } - constructor(props: any, context: any) { super(props, context); this.state = this.emptyState; this.handleSortChange = this.handleSortChange.bind(this); + this.handleDataTypeChange = this.handleDataTypeChange.bind(this); this.subscription = WebSocketService.Instance.subject .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10)))) @@ -112,10 +119,11 @@ export class Community extends Component<any, State> { nextProps.history.action == 'POP' || nextProps.history.action == 'PUSH' ) { - this.state.sort = this.getSortTypeFromProps(nextProps); - this.state.page = this.getPageFromProps(nextProps); + this.state.dataType = getDataTypeFromProps(nextProps); + this.state.sort = getSortTypeFromProps(nextProps); + this.state.page = getPageFromProps(nextProps); this.setState(this.state); - this.fetchPosts(); + this.fetchData(); } } @@ -145,7 +153,7 @@ export class Community extends Component<any, State> { )} </h5> {this.selects()} - <PostListings posts={this.state.posts} removeDuplicates /> + {this.listings()} {this.paginator()} </div> <div class="col-12 col-md-4"> @@ -162,10 +170,31 @@ export class Community extends Component<any, State> { ); } + listings() { + return this.state.dataType == DataType.Post ? ( + <PostListings posts={this.state.posts} removeDuplicates /> + ) : ( + this.state.comments.map(comment => ( + <div class="row"> + <div class="col-12"> + <CommentNodes nodes={[{ comment: comment }]} noIndent /> + </div> + </div> + )) + ); + } + selects() { return ( <div class="mb-2"> - <SortSelect sort={this.state.sort} onChange={this.handleSortChange} /> + <DataTypeSelect + type_={this.state.dataType} + onChange={this.handleDataTypeChange} + /> + + <span class="mx-2"> + <SortSelect sort={this.state.sort} onChange={this.handleSortChange} /> + </span> <a href={`/feeds/c/${this.state.communityName}.xml?sort=${ SortType[this.state.sort] @@ -207,7 +236,7 @@ export class Community extends Component<any, State> { i.state.page++; i.setState(i.state); i.updateUrl(); - i.fetchPosts(); + i.fetchData(); window.scrollTo(0, 0); } @@ -215,7 +244,7 @@ export class Community extends Component<any, State> { i.state.page--; i.setState(i.state); i.updateUrl(); - i.fetchPosts(); + i.fetchData(); window.scrollTo(0, 0); } @@ -225,26 +254,48 @@ export class Community extends Component<any, State> { this.state.loading = true; this.setState(this.state); this.updateUrl(); - this.fetchPosts(); + this.fetchData(); + window.scrollTo(0, 0); + } + + handleDataTypeChange(val: DataType) { + this.state.dataType = val; + this.state.page = 1; + this.state.loading = true; + this.setState(this.state); + this.updateUrl(); + this.fetchData(); window.scrollTo(0, 0); } updateUrl() { + let dataTypeStr = DataType[this.state.dataType].toLowerCase(); let sortStr = SortType[this.state.sort].toLowerCase(); this.props.history.push( - `/c/${this.state.community.name}/sort/${sortStr}/page/${this.state.page}` + `/c/${this.state.community.name}/data_type/${dataTypeStr}/sort/${sortStr}/page/${this.state.page}` ); } - fetchPosts() { - let getPostsForm: GetPostsForm = { - page: this.state.page, - limit: fetchLimit, - sort: SortType[this.state.sort], - type_: ListingType[ListingType.Community], - community_id: this.state.community.id, - }; - WebSocketService.Instance.getPosts(getPostsForm); + fetchData() { + if (this.state.dataType == DataType.Post) { + let getPostsForm: GetPostsForm = { + page: this.state.page, + limit: fetchLimit, + sort: SortType[this.state.sort], + type_: ListingType[ListingType.Community], + community_id: this.state.community.id, + }; + WebSocketService.Instance.getPosts(getPostsForm); + } else { + let getCommentsForm: GetCommentsForm = { + page: this.state.page, + limit: fetchLimit, + sort: SortType[this.state.sort], + type_: ListingType[ListingType.Community], + community_id: this.state.community.id, + }; + WebSocketService.Instance.getComments(getCommentsForm); + } } parseMessage(msg: WebSocketJsonResponse) { @@ -255,7 +306,7 @@ export class Community extends Component<any, State> { this.context.router.history.push('/'); return; } else if (msg.reconnect) { - this.fetchPosts(); + this.fetchData(); } else if (res.op == UserOperation.GetCommunity) { let data = res.data as GetCommunityResponse; this.state.community = data.community; @@ -264,7 +315,7 @@ export class Community extends Component<any, State> { this.state.online = data.online; document.title = `/c/${this.state.community.name} - ${WebSocketService.Instance.site.name}`; this.setState(this.state); - this.fetchPosts(); + this.fetchData(); } else if (res.op == UserOperation.EditCommunity) { let data = res.data as CommunityResponse; this.state.community = data.community; @@ -319,6 +370,48 @@ export class Community extends Component<any, State> { .forEach(p => (p.banned = data.banned)); this.setState(this.state); + } else if (res.op == UserOperation.GetComments) { + let data = res.data as GetCommentsResponse; + this.state.comments = data.comments; + this.state.loading = false; + this.setState(this.state); + } else if (res.op == UserOperation.EditComment) { + let data = res.data as CommentResponse; + + let found = this.state.comments.find(c => c.id == data.comment.id); + if (found) { + found.content = data.comment.content; + found.updated = data.comment.updated; + found.removed = data.comment.removed; + found.deleted = data.comment.deleted; + found.upvotes = data.comment.upvotes; + found.downvotes = data.comment.downvotes; + found.score = data.comment.score; + this.setState(this.state); + } + } else if (res.op == UserOperation.CreateComment) { + let data = res.data as CommentResponse; + + // Necessary since it might be a user reply + if (data.recipient_ids.length == 0) { + this.state.comments.unshift(data.comment); + this.setState(this.state); + } + } else if (res.op == UserOperation.SaveComment) { + let data = res.data as CommentResponse; + let found = this.state.comments.find(c => c.id == data.comment.id); + found.saved = data.comment.saved; + this.setState(this.state); + } else if (res.op == UserOperation.CreateCommentLike) { + let data = res.data as CommentResponse; + let found: Comment = this.state.comments.find( + c => c.id === data.comment.id + ); + found.score = data.comment.score; + found.upvotes = data.comment.upvotes; + found.downvotes = data.comment.downvotes; + if (data.comment.my_vote !== null) found.my_vote = data.comment.my_vote; + this.setState(this.state); } } } diff --git a/ui/src/components/data-type-select.tsx b/ui/src/components/data-type-select.tsx new file mode 100644 index 00000000..f2539c81 --- /dev/null +++ b/ui/src/components/data-type-select.tsx @@ -0,0 +1,65 @@ +import { Component, linkEvent } from 'inferno'; +import { DataType } from '../interfaces'; + +import { i18n } from '../i18next'; + +interface DataTypeSelectProps { + type_: DataType; + onChange?(val: DataType): any; +} + +interface DataTypeSelectState { + type_: DataType; +} + +export class DataTypeSelect extends Component< + DataTypeSelectProps, + DataTypeSelectState +> { + private emptyState: DataTypeSelectState = { + type_: this.props.type_, + }; + + constructor(props: any, context: any) { + super(props, context); + this.state = this.emptyState; + } + + render() { + return ( + <div class="btn-group btn-group-toggle"> + <label + className={`pointer btn btn-sm btn-secondary + ${this.state.type_ == DataType.Post && 'active'} + `} + > + <input + type="radio" + value={DataType.Post} + checked={this.state.type_ == DataType.Post} + onChange={linkEvent(this, this.handleTypeChange)} + /> + {i18n.t('posts')} + </label> + <label + className={`pointer btn btn-sm btn-secondary ${this.state.type_ == + DataType.Comment && 'active'}`} + > + <input + type="radio" + value={DataType.Comment} + checked={this.state.type_ == DataType.Comment} + onChange={linkEvent(this, this.handleTypeChange)} + /> + {i18n.t('comments')} + </label> + </div> + ); + } + + handleTypeChange(i: DataTypeSelect, event: any) { + i.state.type_ = Number(event.target.value); + i.setState(i.state); + i.props.onChange(i.state.type_); + } +} diff --git a/ui/src/components/main.tsx b/ui/src/components/main.tsx index 161f5df4..92434360 100644 --- a/ui/src/components/main.tsx +++ b/ui/src/components/main.tsx @@ -12,30 +12,39 @@ import { SortType, GetSiteResponse, ListingType, + DataType, SiteResponse, GetPostsResponse, PostResponse, Post, GetPostsForm, + Comment, + GetCommentsForm, + GetCommentsResponse, + CommentResponse, AddAdminResponse, BanUserResponse, WebSocketJsonResponse, } from '../interfaces'; import { WebSocketService, UserService } from '../services'; import { PostListings } from './post-listings'; +import { CommentNodes } from './comment-nodes'; import { SortSelect } from './sort-select'; import { ListingTypeSelect } from './listing-type-select'; +import { DataTypeSelect } from './data-type-select'; import { SiteForm } from './site-form'; import { wsJsonToRes, repoUrl, mdToHtml, fetchLimit, - routeSortTypeToEnum, - routeListingTypeToEnum, pictshareAvatarThumbnail, showAvatars, toast, + getListingTypeFromProps, + getPageFromProps, + getSortTypeFromProps, + getDataTypeFromProps, } from '../utils'; import { i18n } from '../i18next'; import { T } from 'inferno-i18next'; @@ -47,7 +56,9 @@ interface MainState { showEditSite: boolean; loading: boolean; posts: Array<Post>; - type_: ListingType; + comments: Array<Comment>; + listingType: ListingType; + dataType: DataType; sort: SortType; page: number; } @@ -79,38 +90,21 @@ export class Main extends Component<any, MainState> { showEditSite: false, loading: true, posts: [], - type_: this.getListingTypeFromProps(this.props), - sort: this.getSortTypeFromProps(this.props), - page: this.getPageFromProps(this.props), + comments: [], + listingType: getListingTypeFromProps(this.props), + dataType: getDataTypeFromProps(this.props), + sort: getSortTypeFromProps(this.props), + page: getPageFromProps(this.props), }; - getListingTypeFromProps(props: any): ListingType { - return props.match.params.type - ? routeListingTypeToEnum(props.match.params.type) - : UserService.Instance.user - ? UserService.Instance.user.default_listing_type - : ListingType.All; - } - - getSortTypeFromProps(props: any): SortType { - return props.match.params.sort - ? routeSortTypeToEnum(props.match.params.sort) - : UserService.Instance.user - ? UserService.Instance.user.default_sort_type - : SortType.Hot; - } - - getPageFromProps(props: any): number { - return props.match.params.page ? Number(props.match.params.page) : 1; - } - constructor(props: any, context: any) { super(props, context); this.state = this.emptyState; this.handleEditCancel = this.handleEditCancel.bind(this); this.handleSortChange = this.handleSortChange.bind(this); - this.handleTypeChange = this.handleTypeChange.bind(this); + this.handleListingTypeChange = this.handleListingTypeChange.bind(this); + this.handleDataTypeChange = this.handleDataTypeChange.bind(this); this.subscription = WebSocketService.Instance.subject .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10)))) @@ -133,7 +127,7 @@ export class Main extends Component<any, MainState> { WebSocketService.Instance.listCommunities(listCommunitiesForm); - this.fetchPosts(); + this.fetchData(); } componentWillUnmount() { @@ -146,11 +140,12 @@ export class Main extends Component<any, MainState> { nextProps.history.action == 'POP' || nextProps.history.action == 'PUSH' ) { - this.state.type_ = this.getListingTypeFromProps(nextProps); - this.state.sort = this.getSortTypeFromProps(nextProps); - this.state.page = this.getPageFromProps(nextProps); + this.state.listingType = getListingTypeFromProps(nextProps); + this.state.dataType = getDataTypeFromProps(nextProps); + this.state.sort = getSortTypeFromProps(nextProps); + this.state.page = getPageFromProps(nextProps); this.setState(this.state); - this.fetchPosts(); + this.fetchData(); } } @@ -251,10 +246,11 @@ export class Main extends Component<any, MainState> { } updateUrl() { - let typeStr = ListingType[this.state.type_].toLowerCase(); + let listingTypeStr = ListingType[this.state.listingType].toLowerCase(); + let dataTypeStr = DataType[this.state.dataType].toLowerCase(); let sortStr = SortType[this.state.sort].toLowerCase(); this.props.history.push( - `/home/type/${typeStr}/sort/${sortStr}/page/${this.state.page}` + `/home/data_type/${dataTypeStr}/listing_type/${listingTypeStr}/sort/${sortStr}/page/${this.state.page}` ); } @@ -392,11 +388,7 @@ export class Main extends Component<any, MainState> { ) : ( <div> {this.selects()} - <PostListings - posts={this.state.posts} - showCommunity - removeDuplicates - /> + {this.listings()} {this.paginator()} </div> )} @@ -404,17 +396,41 @@ export class Main extends Component<any, MainState> { ); } + listings() { + return this.state.dataType == DataType.Post ? ( + <PostListings posts={this.state.posts} showCommunity removeDuplicates /> + ) : ( + this.state.comments.map(comment => ( + <div class="row"> + <div class="col-12"> + <CommentNodes + nodes={[{ comment: comment }]} + noIndent + showCommunity + /> + </div> + </div> + )) + ); + } + selects() { return ( <div className="mb-3"> - <ListingTypeSelect - type_={this.state.type_} - onChange={this.handleTypeChange} + <DataTypeSelect + type_={this.state.dataType} + onChange={this.handleDataTypeChange} /> <span class="mx-2"> + <ListingTypeSelect + type_={this.state.listingType} + onChange={this.handleListingTypeChange} + /> + </span> + <span class="mr-2"> <SortSelect sort={this.state.sort} onChange={this.handleSortChange} /> </span> - {this.state.type_ == ListingType.All && ( + {this.state.listingType == ListingType.All && ( <a href={`/feeds/all.xml?sort=${SortType[this.state.sort]}`} target="_blank" @@ -425,7 +441,7 @@ export class Main extends Component<any, MainState> { </a> )} {UserService.Instance.user && - this.state.type_ == ListingType.Subscribed && ( + this.state.listingType == ListingType.Subscribed && ( <a href={`/feeds/front/${UserService.Instance.auth}.xml?sort=${ SortType[this.state.sort] @@ -488,7 +504,7 @@ export class Main extends Component<any, MainState> { i.state.loading = true; i.setState(i.state); i.updateUrl(); - i.fetchPosts(); + i.fetchData(); window.scrollTo(0, 0); } @@ -497,7 +513,7 @@ export class Main extends Component<any, MainState> { i.state.loading = true; i.setState(i.state); i.updateUrl(); - i.fetchPosts(); + i.fetchData(); window.scrollTo(0, 0); } @@ -507,28 +523,48 @@ export class Main extends Component<any, MainState> { this.state.loading = true; this.setState(this.state); this.updateUrl(); - this.fetchPosts(); + this.fetchData(); window.scrollTo(0, 0); } - handleTypeChange(val: ListingType) { - this.state.type_ = val; + handleListingTypeChange(val: ListingType) { + this.state.listingType = val; this.state.page = 1; this.state.loading = true; this.setState(this.state); this.updateUrl(); - this.fetchPosts(); + this.fetchData(); window.scrollTo(0, 0); } - fetchPosts() { - let getPostsForm: GetPostsForm = { - page: this.state.page, - limit: fetchLimit, - sort: SortType[this.state.sort], - type_: ListingType[this.state.type_], - }; - WebSocketService.Instance.getPosts(getPostsForm); + handleDataTypeChange(val: DataType) { + this.state.dataType = val; + this.state.page = 1; + this.state.loading = true; + this.setState(this.state); + this.updateUrl(); + this.fetchData(); + window.scrollTo(0, 0); + } + + fetchData() { + if (this.state.dataType == DataType.Post) { + let getPostsForm: GetPostsForm = { + page: this.state.page, + limit: fetchLimit, + sort: SortType[this.state.sort], + type_: ListingType[this.state.listingType], + }; + WebSocketService.Instance.getPosts(getPostsForm); + } else { + let getCommentsForm: GetCommentsForm = { + page: this.state.page, + limit: fetchLimit, + sort: SortType[this.state.sort], + type_: ListingType[this.state.listingType], + }; + WebSocketService.Instance.getComments(getCommentsForm); + } } parseMessage(msg: WebSocketJsonResponse) { @@ -538,7 +574,7 @@ export class Main extends Component<any, MainState> { toast(i18n.t(msg.error), 'danger'); return; } else if (msg.reconnect) { - this.fetchPosts(); + this.fetchData(); } else if (res.op == UserOperation.GetFollowedCommunities) { let data = res.data as GetFollowedCommunitiesResponse; this.state.subscribedCommunities = data.communities; @@ -574,7 +610,7 @@ export class Main extends Component<any, MainState> { let data = res.data as PostResponse; // If you're on subscribed, only push it if you're subscribed. - if (this.state.type_ == ListingType.Subscribed) { + if (this.state.listingType == ListingType.Subscribed) { if ( this.state.subscribedCommunities .map(c => c.community_id) @@ -633,6 +669,59 @@ export class Main extends Component<any, MainState> { .forEach(p => (p.banned = data.banned)); this.setState(this.state); + } else if (res.op == UserOperation.GetComments) { + let data = res.data as GetCommentsResponse; + this.state.comments = data.comments; + this.state.loading = false; + this.setState(this.state); + } else if (res.op == UserOperation.EditComment) { + let data = res.data as CommentResponse; + + let found = this.state.comments.find(c => c.id == data.comment.id); + if (found) { + found.content = data.comment.content; + found.updated = data.comment.updated; + found.removed = data.comment.removed; + found.deleted = data.comment.deleted; + found.upvotes = data.comment.upvotes; + found.downvotes = data.comment.downvotes; + found.score = data.comment.score; + this.setState(this.state); + } + } else if (res.op == UserOperation.CreateComment) { + let data = res.data as CommentResponse; + + // Necessary since it might be a user reply + if (data.recipient_ids.length == 0) { + // If you're on subscribed, only push it if you're subscribed. + if (this.state.listingType == ListingType.Subscribed) { + if ( + this.state.subscribedCommunities + .map(c => c.community_id) + .includes(data.comment.community_id) + ) { + this.state.comments.unshift(data.comment); + } + } else { + this.state.comments.unshift(data.comment); + } + this.setState(this.state); + } + } else if (res.op == UserOperation.SaveComment) { + let data = res.data as CommentResponse; + let found = this.state.comments.find(c => c.id == data.comment.id); + found.saved = data.comment.saved; + this.setState(this.state); + } else if (res.op == UserOperation.CreateCommentLike) { + let data = res.data as CommentResponse; + let found: Comment = this.state.comments.find( + c => c.id === data.comment.id + ); + found.score = data.comment.score; + found.upvotes = data.comment.upvotes; + found.downvotes = data.comment.downvotes; + if (data.comment.my_vote !== null) found.my_vote = data.comment.my_vote; + this.setState(this.state); } } } diff --git a/ui/src/components/user.tsx b/ui/src/components/user.tsx index da6aa8ce..effc9e1d 100644 --- a/ui/src/components/user.tsx +++ b/ui/src/components/user.tsx @@ -1034,20 +1034,24 @@ export class User extends Component<any, UserState> { let data = res.data as CommentResponse; let found = this.state.comments.find(c => c.id == data.comment.id); - found.content = data.comment.content; - found.updated = data.comment.updated; - found.removed = data.comment.removed; - found.deleted = data.comment.deleted; - found.upvotes = data.comment.upvotes; - found.downvotes = data.comment.downvotes; - found.score = data.comment.score; - - this.setState(this.state); + if (found) { + found.content = data.comment.content; + found.updated = data.comment.updated; + found.removed = data.comment.removed; + found.deleted = data.comment.deleted; + found.upvotes = data.comment.upvotes; + found.downvotes = data.comment.downvotes; + found.score = data.comment.score; + this.setState(this.state); + } } else if (res.op == UserOperation.CreateComment) { - // let res: CommentResponse = msg; - toast(i18n.t('reply_sent')); - // this.state.comments.unshift(res.comment); // TODO do this right - // this.setState(this.state); + let data = res.data as CommentResponse; + if ( + UserService.Instance.user && + data.comment.creator_id == UserService.Instance.user.id + ) { + toast(i18n.t('reply_sent')); + } } else if (res.op == UserOperation.SaveComment) { let data = res.data as CommentResponse; let found = this.state.comments.find(c => c.id == data.comment.id); diff --git a/ui/src/index.tsx b/ui/src/index.tsx index 8a9aa3c3..c56f6c4e 100644 --- a/ui/src/index.tsx +++ b/ui/src/index.tsx @@ -41,7 +41,7 @@ class Index extends Component<any, any> { <Switch> <Route exact path={`/`} component={Main} /> <Route - path={`/home/type/:type/sort/:sort/page/:page`} + path={`/home/data_type/:data_type/listing_type/:listing_type/sort/:sort/page/:page`} component={Main} /> <Route path={`/login`} component={Login} /> @@ -56,7 +56,7 @@ class Index extends Component<any, any> { <Route path={`/post/:id/comment/:comment_id`} component={Post} /> <Route path={`/post/:id`} component={Post} /> <Route - path={`/c/:name/sort/:sort/page/:page`} + path={`/c/:name/data_type/:data_type/sort/:sort/page/:page`} component={Community} /> <Route path={`/community/:id`} component={Community} /> diff --git a/ui/src/interfaces.ts b/ui/src/interfaces.ts index 02c108aa..5736d375 100644 --- a/ui/src/interfaces.ts +++ b/ui/src/interfaces.ts @@ -42,6 +42,7 @@ export enum UserOperation { EditPrivateMessage, GetPrivateMessages, UserJoin, + GetComments, } export enum CommentSortType { @@ -57,6 +58,11 @@ export enum ListingType { Community, } +export enum DataType { + Post, + Comment, +} + export enum SortType { Hot, New, @@ -187,6 +193,7 @@ export interface Comment { published: string; updated?: string; community_id: number; + community_name: string; banned: boolean; banned_from_community: boolean; creator_name: string; @@ -194,8 +201,10 @@ export interface Comment { score: number; upvotes: number; downvotes: number; + hot_rank: number; user_id?: number; my_vote?: number; + subscribed?: number; saved?: boolean; user_mention_id?: number; // For mention type recipient_id?: number; @@ -659,6 +668,19 @@ export interface GetPostsResponse { posts: Array<Post>; } +export interface GetCommentsForm { + type_: string; + sort: string; + page?: number; + limit: number; + community_id?: number; + auth?: string; +} + +export interface GetCommentsResponse { + comments: Array<Comment>; +} + export interface CreatePostLikeForm { post_id: number; score: number; diff --git a/ui/src/services/WebSocketService.ts b/ui/src/services/WebSocketService.ts index 6d951618..3df69457 100644 --- a/ui/src/services/WebSocketService.ts +++ b/ui/src/services/WebSocketService.ts @@ -38,6 +38,7 @@ import { PrivateMessageForm, EditPrivateMessageForm, GetPrivateMessagesForm, + GetCommentsForm, UserJoinForm, MessageType, WebSocketJsonResponse, @@ -172,6 +173,11 @@ export class WebSocketService { this.ws.send(this.wsSendWrapper(UserOperation.GetPosts, form)); } + public getComments(form: GetCommentsForm) { + this.setAuth(form, false); + this.ws.send(this.wsSendWrapper(UserOperation.GetComments, form)); + } + public likePost(form: CreatePostLikeForm) { this.setAuth(form); this.ws.send(this.wsSendWrapper(UserOperation.CreatePostLike, form)); diff --git a/ui/src/translations/en.ts b/ui/src/translations/en.ts index f71c203b..788bce79 100644 --- a/ui/src/translations/en.ts +++ b/ui/src/translations/en.ts @@ -201,6 +201,7 @@ export const en = { couldnt_like_comment: "Couldn't like comment.", couldnt_update_comment: "Couldn't update comment.", couldnt_save_comment: "Couldn't save comment.", + couldnt_get_comments: "Couldn't get comments.", no_comment_edit_allowed: 'Not allowed to edit comment.', no_post_edit_allowed: 'Not allowed to edit post.', no_community_edit_allowed: 'Not allowed to edit community.', diff --git a/ui/src/utils.ts b/ui/src/utils.ts index 9ad0920f..51836c6f 100644 --- a/ui/src/utils.ts +++ b/ui/src/utils.ts @@ -19,6 +19,7 @@ import { User, SortType, ListingType, + DataType, SearchType, WebSocketResponse, WebSocketJsonResponse, @@ -198,6 +199,10 @@ export function routeListingTypeToEnum(type: string): ListingType { return ListingType[capitalizeFirstLetter(type)]; } +export function routeDataTypeToEnum(type: string): DataType { + return DataType[capitalizeFirstLetter(type)]; +} + export function routeSearchTypeToEnum(type: string): SearchType { return SearchType[capitalizeFirstLetter(type)]; } @ |