]> Untitled Git - lemmy-ui.git/blob - src/shared/components/user-details.tsx
First pass at v2_api
[lemmy-ui.git] / src / shared / components / user-details.tsx
1 import { Component, linkEvent } from 'inferno';
2 import { i18n } from '../i18next';
3 import {
4   PostView,
5   CommentView,
6   SortType,
7   GetUserDetailsResponse,
8   UserViewSafe,
9 } from 'lemmy-js-client';
10 import { UserDetailsView } from '../interfaces';
11 import { commentsToFlatNodes, setupTippy } from '../utils';
12 import { PostListing } from './post-listing';
13 import { CommentNodes } from './comment-nodes';
14
15 interface UserDetailsProps {
16   userRes: GetUserDetailsResponse;
17   admins: UserViewSafe[];
18   page: number;
19   limit: number;
20   sort: SortType;
21   enableDownvotes: boolean;
22   enableNsfw: boolean;
23   view: UserDetailsView;
24   onPageChange(page: number): number | any;
25 }
26
27 interface UserDetailsState {}
28
29 enum ItemEnum {
30   Comment,
31   Post,
32 }
33 type ItemType = {
34   id: number;
35   type_: ItemEnum;
36   view: CommentView | PostView;
37   published: string;
38   score: number;
39 };
40
41 export class UserDetails extends Component<UserDetailsProps, UserDetailsState> {
42   constructor(props: any, context: any) {
43     super(props, context);
44   }
45
46   // TODO needed here?
47   componentDidMount() {
48     setupTippy();
49   }
50
51   // TODO wut?
52   // componentDidUpdate(lastProps: UserDetailsProps) {
53   //   for (const key of Object.keys(lastProps)) {
54   //     if (lastProps[key] !== this.props[key]) {
55   //       this.fetchUserData();
56   //       break;
57   //     }
58   //   }
59   // }
60
61   render() {
62     return (
63       <div>
64         {this.viewSelector(this.props.view)}
65         {this.paginator()}
66       </div>
67     );
68   }
69
70   viewSelector(view: UserDetailsView) {
71     if (view === UserDetailsView.Overview || view === UserDetailsView.Saved) {
72       return this.overview();
73     } else if (view === UserDetailsView.Comments) {
74       return this.comments();
75     } else if (view === UserDetailsView.Posts) {
76       return this.posts();
77     } else {
78       return null;
79     }
80   }
81
82   renderItemType(i: ItemType) {
83     switch (i.type_) {
84       case ItemEnum.Comment:
85         let c = i.view as CommentView;
86         return (
87           <CommentNodes
88             key={i.id}
89             nodes={[{ comment_view: c }]}
90             admins={this.props.admins}
91             noBorder
92             noIndent
93             showCommunity
94             showContext
95             enableDownvotes={this.props.enableDownvotes}
96           />
97         );
98       case ItemEnum.Post:
99         let p = i.view as PostView;
100         return (
101           <PostListing
102             key={i.id}
103             post_view={p}
104             admins={this.props.admins}
105             showCommunity
106             enableDownvotes={this.props.enableDownvotes}
107             enableNsfw={this.props.enableNsfw}
108           />
109         );
110       default:
111         return <div />;
112     }
113   }
114
115   overview() {
116     let id = 0;
117     let comments: ItemType[] = this.props.userRes.comments.map(r => ({
118       id: id++,
119       type_: ItemEnum.Comment,
120       view: r,
121       published: r.comment.published,
122       score: r.counts.score,
123     }));
124     let posts: ItemType[] = this.props.userRes.posts.map(r => ({
125       id: id++,
126       type_: ItemEnum.Comment,
127       view: r,
128       published: r.post.published,
129       score: r.counts.score,
130     }));
131
132     let combined = [...comments, ...posts];
133
134     // Sort it
135     if (this.props.sort === SortType.New) {
136       combined.sort((a, b) => b.published.localeCompare(a.published));
137     } else {
138       combined.sort((a, b) => b.score - a.score);
139     }
140
141     return (
142       <div>
143         {combined.map(i => [this.renderItemType(i), <hr class="my-3" />])}
144       </div>
145     );
146   }
147
148   comments() {
149     return (
150       <div>
151         <CommentNodes
152           nodes={commentsToFlatNodes(this.props.userRes.comments)}
153           admins={this.props.admins}
154           noIndent
155           showCommunity
156           showContext
157           enableDownvotes={this.props.enableDownvotes}
158         />
159       </div>
160     );
161   }
162
163   posts() {
164     return (
165       <div>
166         {this.props.userRes.posts.map(post => (
167           <>
168             <PostListing
169               post_view={post}
170               admins={this.props.admins}
171               showCommunity
172               enableDownvotes={this.props.enableDownvotes}
173               enableNsfw={this.props.enableNsfw}
174             />
175             <hr class="my-3" />
176           </>
177         ))}
178       </div>
179     );
180   }
181
182   paginator() {
183     return (
184       <div class="my-2">
185         {this.props.page > 1 && (
186           <button
187             class="btn btn-secondary mr-1"
188             onClick={linkEvent(this, this.prevPage)}
189           >
190             {i18n.t('prev')}
191           </button>
192         )}
193         {this.props.userRes.comments.length + this.props.userRes.posts.length >
194           0 && (
195           <button
196             class="btn btn-secondary"
197             onClick={linkEvent(this, this.nextPage)}
198           >
199             {i18n.t('next')}
200           </button>
201         )}
202       </div>
203     );
204   }
205
206   nextPage(i: UserDetails) {
207     i.props.onPageChange(i.props.page + 1);
208   }
209
210   prevPage(i: UserDetails) {
211     i.props.onPageChange(i.props.page - 1);
212   }
213 }