]> Untitled Git - lemmy-ui.git/blob - src/shared/components/home/site-sidebar.tsx
Add default post listing (#645)
[lemmy-ui.git] / src / shared / components / home / site-sidebar.tsx
1 import { Component, linkEvent } from "inferno";
2 import { Link } from "inferno-router";
3 import { PersonViewSafe, Site, SiteAggregates } from "lemmy-js-client";
4 import { i18n } from "../../i18next";
5 import { UserService } from "../../services";
6 import { mdToHtml, numToSI } from "../../utils";
7 import { BannerIconHeader } from "../common/banner-icon-header";
8 import { Icon } from "../common/icon";
9 import { PersonListing } from "../person/person-listing";
10 import { SiteForm } from "./site-form";
11
12 interface SiteSidebarProps {
13   site: Site;
14   showLocal: boolean;
15   counts?: SiteAggregates;
16   admins?: PersonViewSafe[];
17   online?: number;
18 }
19
20 interface SiteSidebarState {
21   collapsed: boolean;
22   showEdit: boolean;
23 }
24
25 export class SiteSidebar extends Component<SiteSidebarProps, SiteSidebarState> {
26   private emptyState: SiteSidebarState = {
27     collapsed: false,
28     showEdit: false,
29   };
30
31   constructor(props: any, context: any) {
32     super(props, context);
33     this.state = this.emptyState;
34     this.handleEditCancel = this.handleEditCancel.bind(this);
35     this.handleEditSite = this.handleEditSite.bind(this);
36   }
37
38   render() {
39     let site = this.props.site;
40     return (
41       <div class="card border-secondary mb-3">
42         <div class="card-body">
43           {!this.state.showEdit ? (
44             <div>
45               <div class="mb-2">
46                 {this.siteName()}
47                 {this.props.admins && this.adminButtons()}
48               </div>
49               {!this.state.collapsed && (
50                 <>
51                   <BannerIconHeader banner={site.banner} />
52                   {this.siteInfo()}
53                 </>
54               )}
55             </div>
56           ) : (
57             <SiteForm
58               site={site}
59               showLocal={this.props.showLocal}
60               onEdit={this.handleEditSite}
61               onCancel={this.handleEditCancel}
62             />
63           )}
64         </div>
65       </div>
66     );
67   }
68
69   siteName() {
70     let site = this.props.site;
71     return (
72       site.name && (
73         <h5 class="mb-0 d-inline">
74           {site.name}
75           <button
76             class="btn btn-sm text-muted"
77             onClick={linkEvent(this, this.handleCollapseSidebar)}
78             aria-label={i18n.t("collapse")}
79             data-tippy-content={i18n.t("collapse")}
80           >
81             {this.state.collapsed ? (
82               <Icon icon="plus-square" classes="icon-inline" />
83             ) : (
84               <Icon icon="minus-square" classes="icon-inline" />
85             )}
86           </button>
87         </h5>
88       )
89     );
90   }
91
92   siteInfo() {
93     let site = this.props.site;
94     return (
95       <div>
96         {site.description && <h6>{site.description}</h6>}
97         {site.sidebar && this.siteSidebar()}
98         {this.props.counts && this.badges()}
99         {this.props.admins && this.admins()}
100       </div>
101     );
102   }
103
104   adminButtons() {
105     return (
106       this.canAdmin && (
107         <ul class="list-inline mb-1 text-muted font-weight-bold">
108           <li className="list-inline-item-action">
109             <button
110               class="btn btn-link d-inline-block text-muted"
111               onClick={linkEvent(this, this.handleEditClick)}
112               aria-label={i18n.t("edit")}
113               data-tippy-content={i18n.t("edit")}
114             >
115               <Icon icon="edit" classes="icon-inline" />
116             </button>
117           </li>
118         </ul>
119       )
120     );
121   }
122
123   siteSidebar() {
124     return (
125       <div
126         className="md-div"
127         dangerouslySetInnerHTML={mdToHtml(this.props.site.sidebar)}
128       />
129     );
130   }
131
132   admins() {
133     return (
134       <ul class="mt-1 list-inline small mb-0">
135         <li class="list-inline-item">{i18n.t("admins")}:</li>
136         {this.props.admins?.map(av => (
137           <li class="list-inline-item">
138             <PersonListing person={av.person} />
139           </li>
140         ))}
141       </ul>
142     );
143   }
144
145   badges() {
146     let counts = this.props.counts;
147     let online = this.props.online;
148     return (
149       <ul class="my-2 list-inline">
150         <li className="list-inline-item badge badge-secondary">
151           {i18n.t("number_online", {
152             count: online,
153             formattedCount: numToSI(online),
154           })}
155         </li>
156         <li
157           className="list-inline-item badge badge-secondary pointer"
158           data-tippy-content={i18n.t("active_users_in_the_last_day", {
159             count: counts.users_active_day,
160             formattedCount: numToSI(counts.users_active_day),
161           })}
162         >
163           {i18n.t("number_of_users", {
164             count: counts.users_active_day,
165             formattedCount: numToSI(counts.users_active_day),
166           })}{" "}
167           / {i18n.t("day")}
168         </li>
169         <li
170           className="list-inline-item badge badge-secondary pointer"
171           data-tippy-content={i18n.t("active_users_in_the_last_week", {
172             count: counts.users_active_week,
173             formattedCount: counts.users_active_week,
174           })}
175         >
176           {i18n.t("number_of_users", {
177             count: counts.users_active_week,
178             formattedCount: numToSI(counts.users_active_week),
179           })}{" "}
180           / {i18n.t("week")}
181         </li>
182         <li
183           className="list-inline-item badge badge-secondary pointer"
184           data-tippy-content={i18n.t("active_users_in_the_last_month", {
185             count: counts.users_active_month,
186             formattedCount: counts.users_active_month,
187           })}
188         >
189           {i18n.t("number_of_users", {
190             count: counts.users_active_month,
191             formattedCount: numToSI(counts.users_active_month),
192           })}{" "}
193           / {i18n.t("month")}
194         </li>
195         <li
196           className="list-inline-item badge badge-secondary pointer"
197           data-tippy-content={i18n.t("active_users_in_the_last_six_months", {
198             count: counts.users_active_half_year,
199             formattedCount: counts.users_active_half_year,
200           })}
201         >
202           {i18n.t("number_of_users", {
203             count: counts.users_active_half_year,
204             formattedCount: numToSI(counts.users_active_half_year),
205           })}{" "}
206           / {i18n.t("number_of_months", { count: 6, formattedCount: 6 })}
207         </li>
208         <li className="list-inline-item badge badge-secondary">
209           {i18n.t("number_of_users", {
210             count: counts.users,
211             formattedCount: numToSI(counts.users),
212           })}
213         </li>
214         <li className="list-inline-item badge badge-secondary">
215           {i18n.t("number_of_communities", {
216             count: counts.communities,
217             formattedCount: numToSI(counts.communities),
218           })}
219         </li>
220         <li className="list-inline-item badge badge-secondary">
221           {i18n.t("number_of_posts", {
222             count: counts.posts,
223             formattedCount: numToSI(counts.posts),
224           })}
225         </li>
226         <li className="list-inline-item badge badge-secondary">
227           {i18n.t("number_of_comments", {
228             count: counts.comments,
229             formattedCount: numToSI(counts.comments),
230           })}
231         </li>
232         <li className="list-inline-item">
233           <Link className="badge badge-primary" to="/modlog">
234             {i18n.t("modlog")}
235           </Link>
236         </li>
237       </ul>
238     );
239   }
240
241   get canAdmin(): boolean {
242     return (
243       UserService.Instance.myUserInfo &&
244       this.props.admins
245         .map(a => a.person.id)
246         .includes(UserService.Instance.myUserInfo.local_user_view.person.id)
247     );
248   }
249
250   handleCollapseSidebar(i: SiteSidebar) {
251     i.state.collapsed = !i.state.collapsed;
252     i.setState(i.state);
253   }
254
255   handleEditClick(i: SiteSidebar) {
256     i.state.showEdit = true;
257     i.setState(i.state);
258   }
259
260   handleEditSite() {
261     this.state.showEdit = false;
262     this.setState(this.state);
263   }
264
265   handleEditCancel() {
266     this.state.showEdit = false;
267     this.setState(this.state);
268   }
269 }