]> Untitled Git - lemmy-ui.git/blob - src/shared/components/person/person-details.tsx
Comment Tree paging (#726)
[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 { CommentViewType, 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, children: [], depth: 0 }]}
93             viewType={CommentViewType.Flat}
94             admins={Some(this.props.admins)}
95             moderators={None}
96             maxCommentsShown={None}
97             noBorder
98             noIndent
99             showCommunity
100             showContext
101             enableDownvotes={this.props.enableDownvotes}
102           />
103         );
104       }
105       case ItemEnum.Post: {
106         let p = i.view as PostView;
107         return (
108           <PostListing
109             key={i.id}
110             post_view={p}
111             admins={Some(this.props.admins)}
112             duplicates={None}
113             moderators={None}
114             showCommunity
115             enableDownvotes={this.props.enableDownvotes}
116             enableNsfw={this.props.enableNsfw}
117           />
118         );
119       }
120       default:
121         return <div />;
122     }
123   }
124
125   overview() {
126     let id = 0;
127     let comments: ItemType[] = this.props.personRes.comments.map(r => ({
128       id: id++,
129       type_: ItemEnum.Comment,
130       view: r,
131       published: r.comment.published,
132       score: r.counts.score,
133     }));
134     let posts: ItemType[] = this.props.personRes.posts.map(r => ({
135       id: id++,
136       type_: ItemEnum.Post,
137       view: r,
138       published: r.post.published,
139       score: r.counts.score,
140     }));
141
142     let combined = [...comments, ...posts];
143
144     // Sort it
145     if (this.props.sort === SortType.New) {
146       combined.sort((a, b) => b.published.localeCompare(a.published));
147     } else {
148       combined.sort((a, b) => b.score - a.score);
149     }
150
151     return (
152       <div>
153         {combined.map(i => [this.renderItemType(i), <hr class="my-3" />])}
154       </div>
155     );
156   }
157
158   comments() {
159     return (
160       <div>
161         <CommentNodes
162           nodes={commentsToFlatNodes(this.props.personRes.comments)}
163           viewType={CommentViewType.Flat}
164           admins={Some(this.props.admins)}
165           moderators={None}
166           maxCommentsShown={None}
167           noIndent
168           showCommunity
169           showContext
170           enableDownvotes={this.props.enableDownvotes}
171         />
172       </div>
173     );
174   }
175
176   posts() {
177     return (
178       <div>
179         {this.props.personRes.posts.map(post => (
180           <>
181             <PostListing
182               post_view={post}
183               admins={Some(this.props.admins)}
184               showCommunity
185               duplicates={None}
186               moderators={None}
187               enableDownvotes={this.props.enableDownvotes}
188               enableNsfw={this.props.enableNsfw}
189             />
190             <hr class="my-3" />
191           </>
192         ))}
193       </div>
194     );
195   }
196
197   handlePageChange(val: number) {
198     this.props.onPageChange(val);
199   }
200 }