1 import { Component, linkEvent } from 'inferno';
2 import { WebSocketService, UserService } from '../services';
3 import { Subscription } from 'rxjs';
4 import { retryWhen, delay, take } from 'rxjs/operators';
5 import { i18n } from '../i18next';
14 WebSocketJsonResponse,
19 } from '../interfaces';
28 createPostLikeFindRes,
30 import { PostListing } from './post-listing';
31 import { CommentNodes } from './comment-nodes';
33 interface UserDetailsProps {
39 enableDownvotes: boolean;
41 view: UserDetailsView;
42 onPageChange(page: number): number | any;
43 admins: Array<UserView>;
46 interface UserDetailsState {
47 follows: Array<CommunityUser>;
48 moderates: Array<CommunityUser>;
49 comments: Array<Comment>;
54 export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
55 private subscription: Subscription;
56 constructor(props: any, context: any) {
57 super(props, context);
67 this.subscription = WebSocketService.Instance.subject
68 .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
70 msg => this.parseMessage(msg),
71 err => console.error(err),
72 () => console.log('complete')
76 componentWillUnmount() {
77 this.subscription.unsubscribe();
85 componentDidUpdate(lastProps: UserDetailsProps) {
86 for (const key of Object.keys(lastProps)) {
87 if (lastProps[key] !== this.props[key]) {
95 WebSocketService.Instance.getUserDetails({
96 user_id: this.props.user_id,
97 username: this.props.username,
98 sort: this.props.sort,
99 saved_only: this.props.view === UserDetailsView.Saved,
100 page: this.props.page,
101 limit: this.props.limit,
108 {this.viewSelector(this.props.view)}
114 viewSelector(view: UserDetailsView) {
115 if (view === UserDetailsView.Overview || view === UserDetailsView.Saved) {
116 return this.overview();
118 if (view === UserDetailsView.Comments) {
119 return this.comments();
121 if (view === UserDetailsView.Posts) {
127 const comments = this.state.comments.map((c: Comment) => {
128 return { type: 'comments', data: c };
130 const posts = this.state.posts.map((p: Post) => {
131 return { type: 'posts', data: p };
134 const combined: Array<{ type: string; data: Comment | Post }> = [
140 if (SortType[this.props.sort] === SortType.New) {
141 combined.sort((a, b) => b.data.published.localeCompare(a.data.published));
143 combined.sort((a, b) => b.data.score - a.data.score);
151 {i.type === 'posts' ? (
153 key={(i.data as Post).id}
154 post={i.data as Post}
155 admins={this.props.admins}
157 enableDownvotes={this.props.enableDownvotes}
158 enableNsfw={this.props.enableNsfw}
162 key={(i.data as Comment).id}
163 nodes={[{ comment: i.data as Comment }]}
164 admins={this.props.admins}
169 enableDownvotes={this.props.enableDownvotes}
184 nodes={commentsToFlatNodes(this.state.comments)}
185 admins={this.props.admins}
189 enableDownvotes={this.props.enableDownvotes}
198 {this.state.posts.map(post => (
202 admins={this.props.admins}
204 enableDownvotes={this.props.enableDownvotes}
205 enableNsfw={this.props.enableNsfw}
217 {this.props.page > 1 && (
219 class="btn btn-secondary mr-1"
220 onClick={linkEvent(this, this.prevPage)}
225 {this.state.comments.length + this.state.posts.length > 0 && (
227 class="btn btn-secondary"
228 onClick={linkEvent(this, this.nextPage)}
237 nextPage(i: UserDetails) {
238 i.props.onPageChange(i.props.page + 1);
241 prevPage(i: UserDetails) {
242 i.props.onPageChange(i.props.page - 1);
245 parseMessage(msg: WebSocketJsonResponse) {
247 const res = wsJsonToRes(msg);
250 toast(i18n.t(msg.error), 'danger');
251 if (msg.error == 'couldnt_find_that_username_or_email') {
252 this.context.router.history.push('/');
255 } else if (msg.reconnect) {
256 this.fetchUserData();
257 } else if (res.op == UserOperation.GetUserDetails) {
258 const data = res.data as UserDetailsResponse;
260 comments: data.comments,
261 follows: data.follows,
262 moderates: data.moderates,
265 } else if (res.op == UserOperation.CreateCommentLike) {
266 const data = res.data as CommentResponse;
267 createCommentLikeRes(data, this.state.comments);
269 comments: this.state.comments,
272 res.op == UserOperation.EditComment ||
273 res.op == UserOperation.DeleteComment ||
274 res.op == UserOperation.RemoveComment
276 const data = res.data as CommentResponse;
277 editCommentRes(data, this.state.comments);
279 comments: this.state.comments,
281 } else if (res.op == UserOperation.CreateComment) {
282 const data = res.data as CommentResponse;
284 UserService.Instance.user &&
285 data.comment.creator_id == UserService.Instance.user.id
287 toast(i18n.t('reply_sent'));
289 } else if (res.op == UserOperation.SaveComment) {
290 const data = res.data as CommentResponse;
291 saveCommentRes(data, this.state.comments);
293 comments: this.state.comments,
295 } else if (res.op == UserOperation.CreatePostLike) {
296 const data = res.data as PostResponse;
297 createPostLikeFindRes(data, this.state.posts);
299 posts: this.state.posts,
301 } else if (res.op == UserOperation.BanUser) {
302 const data = res.data as BanUserResponse;
304 .filter(c => c.creator_id == data.user.id)
305 .forEach(c => (c.banned = data.banned));
307 .filter(c => c.creator_id == data.user.id)
308 .forEach(c => (c.banned = data.banned));
310 posts: this.state.posts,
311 comments: this.state.comments,