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();
84 componentDidUpdate(lastProps: UserDetailsProps) {
85 for (const key of Object.keys(lastProps)) {
86 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);
150 {i.type === 'posts' ? (
152 post={i.data as Post}
153 admins={this.props.admins}
155 enableDownvotes={this.props.enableDownvotes}
156 enableNsfw={this.props.enableNsfw}
160 nodes={[{ comment: i.data as Comment }]}
161 admins={this.props.admins}
164 enableDownvotes={this.props.enableDownvotes}
177 nodes={commentsToFlatNodes(this.state.comments)}
178 admins={this.props.admins}
181 enableDownvotes={this.props.enableDownvotes}
190 {this.state.posts.map(post => (
193 admins={this.props.admins}
195 enableDownvotes={this.props.enableDownvotes}
196 enableNsfw={this.props.enableNsfw}
206 {this.props.page > 1 && (
208 class="btn btn-secondary mr-1"
209 onClick={linkEvent(this, this.prevPage)}
214 {this.state.comments.length + this.state.posts.length > 0 && (
216 class="btn btn-secondary"
217 onClick={linkEvent(this, this.nextPage)}
226 nextPage(i: UserDetails) {
227 i.props.onPageChange(i.props.page + 1);
230 prevPage(i: UserDetails) {
231 i.props.onPageChange(i.props.page - 1);
234 parseMessage(msg: WebSocketJsonResponse) {
236 const res = wsJsonToRes(msg);
239 toast(i18n.t(msg.error), 'danger');
240 if (msg.error == 'couldnt_find_that_username_or_email') {
241 this.context.router.history.push('/');
244 } else if (msg.reconnect) {
245 this.fetchUserData();
246 } else if (res.op == UserOperation.GetUserDetails) {
247 const data = res.data as UserDetailsResponse;
249 comments: data.comments,
250 follows: data.follows,
251 moderates: data.moderates,
254 } else if (res.op == UserOperation.CreateCommentLike) {
255 const data = res.data as CommentResponse;
256 createCommentLikeRes(data, this.state.comments);
258 comments: this.state.comments,
261 res.op == UserOperation.EditComment ||
262 res.op == UserOperation.DeleteComment ||
263 res.op == UserOperation.RemoveComment
265 const data = res.data as CommentResponse;
266 editCommentRes(data, this.state.comments);
268 comments: this.state.comments,
270 } else if (res.op == UserOperation.CreateComment) {
271 const data = res.data as CommentResponse;
273 UserService.Instance.user &&
274 data.comment.creator_id == UserService.Instance.user.id
276 toast(i18n.t('reply_sent'));
278 } else if (res.op == UserOperation.SaveComment) {
279 const data = res.data as CommentResponse;
280 saveCommentRes(data, this.state.comments);
282 comments: this.state.comments,
284 } else if (res.op == UserOperation.CreatePostLike) {
285 const data = res.data as PostResponse;
286 createPostLikeFindRes(data, this.state.posts);
288 posts: this.state.posts,
290 } else if (res.op == UserOperation.BanUser) {
291 const data = res.data as BanUserResponse;
293 .filter(c => c.creator_id == data.user.id)
294 .forEach(c => (c.banned = data.banned));
296 .filter(c => c.creator_id == data.user.id)
297 .forEach(c => (c.banned = data.banned));
299 posts: this.state.posts,
300 comments: this.state.comments,