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