import { Component, linkEvent } from 'inferno'; import { WebSocketService, UserService } from '../services'; import { Subscription } from 'rxjs'; import { retryWhen, delay, take, last } from 'rxjs/operators'; import { i18n } from '../i18next'; import { UserOperation, Post, Comment, CommunityUser, SortType, UserDetailsResponse, UserView, WebSocketJsonResponse, UserDetailsView, CommentResponse, BanUserResponse, PostResponse, AddAdminResponse, } from '../interfaces'; import { wsJsonToRes, toast, commentsToFlatNodes, setupTippy, editCommentRes, saveCommentRes, createCommentLikeRes, createPostLikeFindRes, } from '../utils'; import { PostListing } from './post-listing'; import { CommentNodes } from './comment-nodes'; interface UserDetailsProps { username?: string; user_id?: number; page: number; limit: number; sort: string; enableDownvotes: boolean; enableNsfw: boolean; view: UserDetailsView; onPageChange(page: number): number | any; } interface UserDetailsState { follows: Array; moderates: Array; comments: Array; posts: Array; saved?: Array; admins: Array; } export class UserDetails extends Component { private subscription: Subscription; constructor(props: any, context: any) { super(props, context); this.state = { follows: [], moderates: [], comments: [], posts: [], saved: [], admins: [], }; this.subscription = WebSocketService.Instance.subject .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10)))) .subscribe( msg => this.parseMessage(msg), err => console.error(err), () => console.log('complete') ); } componentWillUnmount() { this.subscription.unsubscribe(); } componentDidMount() { this.fetchUserData(); } componentDidUpdate(lastProps: UserDetailsProps) { for (const key of Object.keys(lastProps)) { if (lastProps[key] !== this.props[key]) { this.fetchUserData(); break; } } setupTippy(); } fetchUserData() { WebSocketService.Instance.getUserDetails({ user_id: this.props.user_id, username: this.props.username, sort: this.props.sort, saved_only: this.props.view === UserDetailsView.Saved, page: this.props.page, limit: this.props.limit, }); } render() { return (
{this.viewSelector(this.props.view)} {this.paginator()}
); } viewSelector(view: UserDetailsView) { if (view === UserDetailsView.Overview || view === UserDetailsView.Saved) { return this.overview(); } if (view === UserDetailsView.Comments) { return this.comments(); } if (view === UserDetailsView.Posts) { return this.posts(); } } overview() { const comments = this.state.comments.map((c: Comment) => { return { type: 'comments', data: c }; }); const posts = this.state.posts.map((p: Post) => { return { type: 'posts', data: p }; }); const combined: Array<{ type: string; data: Comment | Post }> = [ ...comments, ...posts, ]; // Sort it if (SortType[this.props.sort] === SortType.New) { combined.sort((a, b) => b.data.published.localeCompare(a.data.published)); } else { combined.sort((a, b) => b.data.score - a.data.score); } return (
{combined.map(i => (
{i.type === 'posts' ? ( ) : ( )}
))}
); } comments() { return (
); } posts() { return (
{this.state.posts.map(post => ( ))}
); } paginator() { return (
{this.props.page > 1 && ( )} {this.state.comments.length + this.state.posts.length > 0 && ( )}
); } nextPage(i: UserDetails) { i.props.onPageChange(i.props.page + 1); } prevPage(i: UserDetails) { i.props.onPageChange(i.props.page - 1); } parseMessage(msg: WebSocketJsonResponse) { const res = wsJsonToRes(msg); if (msg.error) { toast(i18n.t(msg.error), 'danger'); if (msg.error == 'couldnt_find_that_username_or_email') { this.context.router.history.push('/'); } return; } else if (msg.reconnect) { this.fetchUserData(); } else if (res.op == UserOperation.GetUserDetails) { const data = res.data as UserDetailsResponse; this.setState({ comments: data.comments, follows: data.follows, moderates: data.moderates, posts: data.posts, admins: data.admins, }); } else if (res.op == UserOperation.CreateCommentLike) { const data = res.data as CommentResponse; createCommentLikeRes(data, this.state.comments); this.setState({ comments: this.state.comments, }); } else if (res.op == UserOperation.EditComment) { const data = res.data as CommentResponse; editCommentRes(data, this.state.comments); this.setState({ comments: this.state.comments, }); } else if (res.op == UserOperation.CreateComment) { const 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) { const data = res.data as CommentResponse; saveCommentRes(data, this.state.comments); this.setState({ comments: this.state.comments, }); } else if (res.op == UserOperation.CreatePostLike) { const data = res.data as PostResponse; createPostLikeFindRes(data, this.state.posts); this.setState({ posts: this.state.posts, }); } else if (res.op == UserOperation.BanUser) { const data = res.data as BanUserResponse; this.state.comments .filter(c => c.creator_id == data.user.id) .forEach(c => (c.banned = data.banned)); this.state.posts .filter(c => c.creator_id == data.user.id) .forEach(c => (c.banned = data.banned)); this.setState({ posts: this.state.posts, comments: this.state.comments, }); } else if (res.op == UserOperation.AddAdmin) { const data = res.data as AddAdminResponse; this.setState({ admins: data.admins, }); } } }