1 import { Component, linkEvent } from 'inferno';
2 import { WebSocketService, UserService } from '../services';
3 import { Subscription } from 'rxjs';
4 import { retryWhen, delay, take, last } from 'rxjs/operators';
5 import { i18n } from '../i18next';
14 WebSocketJsonResponse,
20 } from '../interfaces';
29 createPostLikeFindRes,
31 import { PostListing } from './post-listing';
32 import { CommentNodes } from './comment-nodes';
34 interface UserDetailsProps {
40 enableDownvotes: boolean;
42 view: UserDetailsView;
43 onPageChange(page: number): number | any;
46 interface UserDetailsState {
47 follows: Array<CommunityUser>;
48 moderates: Array<CommunityUser>;
49 comments: Array<Comment>;
52 admins: Array<UserView>;
55 export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
56 private subscription: Subscription;
57 constructor(props: any, context: any) {
58 super(props, context);
69 this.subscription = WebSocketService.Instance.subject
70 .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
72 msg => this.parseMessage(msg),
73 err => console.error(err),
74 () => console.log('complete')
78 componentWillUnmount() {
79 this.subscription.unsubscribe();
86 componentDidUpdate(lastProps: UserDetailsProps) {
87 for (const key of Object.keys(lastProps)) {
88 if (lastProps[key] !== this.props[key]) {
97 WebSocketService.Instance.getUserDetails({
98 user_id: this.props.user_id,
99 username: this.props.username,
100 sort: this.props.sort,
101 saved_only: this.props.view === UserDetailsView.Saved,
102 page: this.props.page,
103 limit: this.props.limit,
110 {this.viewSelector(this.props.view)}
116 viewSelector(view: UserDetailsView) {
117 if (view === UserDetailsView.Overview || view === UserDetailsView.Saved) {
118 return this.overview();
120 if (view === UserDetailsView.Comments) {
121 return this.comments();
123 if (view === UserDetailsView.Posts) {
129 const comments = this.state.comments.map((c: Comment) => {
130 return { type: 'comments', data: c };
132 const posts = this.state.posts.map((p: Post) => {
133 return { type: 'posts', data: p };
136 const combined: Array<{ type: string; data: Comment | Post }> = [
142 if (SortType[this.props.sort] === SortType.New) {
143 combined.sort((a, b) => b.data.published.localeCompare(a.data.published));
145 combined.sort((a, b) => b.data.score - a.data.score);
152 {i.type === 'posts' ? (
154 post={i.data as Post}
155 admins={this.state.admins}
157 enableDownvotes={this.props.enableDownvotes}
158 enableNsfw={this.props.enableNsfw}
162 nodes={[{ comment: i.data as Comment }]}
163 admins={this.state.admins}
166 enableDownvotes={this.props.enableDownvotes}
179 nodes={commentsToFlatNodes(this.state.comments)}
180 admins={this.state.admins}
183 enableDownvotes={this.props.enableDownvotes}
192 {this.state.posts.map(post => (
195 admins={this.state.admins}
197 enableDownvotes={this.props.enableDownvotes}
198 enableNsfw={this.props.enableNsfw}
208 {this.props.page > 1 && (
210 class="btn btn-sm btn-secondary mr-1"
211 onClick={linkEvent(this, this.prevPage)}
216 {this.state.comments.length + this.state.posts.length > 0 && (
218 class="btn btn-sm btn-secondary"
219 onClick={linkEvent(this, this.nextPage)}
228 nextPage(i: UserDetails) {
229 i.props.onPageChange(i.props.page + 1);
232 prevPage(i: UserDetails) {
233 i.props.onPageChange(i.props.page - 1);
236 parseMessage(msg: WebSocketJsonResponse) {
237 const res = wsJsonToRes(msg);
240 toast(i18n.t(msg.error), 'danger');
241 if (msg.error == 'couldnt_find_that_username_or_email') {
242 this.context.router.history.push('/');
245 } else if (msg.reconnect) {
246 this.fetchUserData();
247 } else if (res.op == UserOperation.GetUserDetails) {
248 const data = res.data as UserDetailsResponse;
250 comments: data.comments,
251 follows: data.follows,
252 moderates: data.moderates,
256 } else if (res.op == UserOperation.CreateCommentLike) {
257 const data = res.data as CommentResponse;
258 createCommentLikeRes(data, this.state.comments);
260 comments: this.state.comments,
262 } else if (res.op == UserOperation.EditComment) {
263 const data = res.data as CommentResponse;
264 editCommentRes(data, this.state.comments);
266 comments: this.state.comments,
268 } else if (res.op == UserOperation.CreateComment) {
269 const data = res.data as CommentResponse;
271 UserService.Instance.user &&
272 data.comment.creator_id == UserService.Instance.user.id
274 toast(i18n.t('reply_sent'));
276 } else if (res.op == UserOperation.SaveComment) {
277 const data = res.data as CommentResponse;
278 saveCommentRes(data, this.state.comments);
280 comments: this.state.comments,
282 } else if (res.op == UserOperation.CreatePostLike) {
283 const data = res.data as PostResponse;
284 createPostLikeFindRes(data, this.state.posts);
286 posts: this.state.posts,
288 } else if (res.op == UserOperation.BanUser) {
289 const data = res.data as BanUserResponse;
291 .filter(c => c.creator_id == data.user.id)
292 .forEach(c => (c.banned = data.banned));
294 .filter(c => c.creator_id == data.user.id)
295 .forEach(c => (c.banned = data.banned));
297 posts: this.state.posts,
298 comments: this.state.comments,
300 } else if (res.op == UserOperation.AddAdmin) {
301 const data = res.data as AddAdminResponse;