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