]> Untitled Git - lemmy-ui.git/blob - src/shared/components/home/site-sidebar.tsx
Adding private message reporting. Fixes #782 (#806)
[lemmy-ui.git] / src / shared / components / home / site-sidebar.tsx
1 import { None, Option, Some } from "@sniptt/monads";
2 import { Component, linkEvent } from "inferno";
3 import { Link } from "inferno-router";
4 import { PersonViewSafe, Site, SiteAggregates } from "lemmy-js-client";
5 import { i18n } from "../../i18next";
6 import { amAdmin, 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: Option<SiteAggregates>;
16   admins: Option<PersonViewSafe[]>;
17   online: Option<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 className="card border-secondary mb-3">
42         <div className="card-body">
43           {!this.state.showEdit ? (
44             <div>
45               <div className="mb-2">
46                 {this.siteName()}
47                 {this.props.admins.isSome() && this.adminButtons()}
48               </div>
49               {!this.state.collapsed && (
50                 <>
51                   <BannerIconHeader banner={site.banner} icon={None} />
52                   {this.siteInfo()}
53                 </>
54               )}
55             </div>
56           ) : (
57             <SiteForm
58               site={Some(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       <h5 className="mb-0 d-inline">
73         {site.name}
74         <button
75           className="btn btn-sm text-muted"
76           onClick={linkEvent(this, this.handleCollapseSidebar)}
77           aria-label={i18n.t("collapse")}
78           data-tippy-content={i18n.t("collapse")}
79         >
80           {this.state.collapsed ? (
81             <Icon icon="plus-square" classes="icon-inline" />
82           ) : (
83             <Icon icon="minus-square" classes="icon-inline" />
84           )}
85         </button>
86       </h5>
87     );
88   }
89
90   siteInfo() {
91     let site = this.props.site;
92     return (
93       <div>
94         {site.description.match({
95           some: description => <h6>{description}</h6>,
96           none: <></>,
97         })}
98         {site.sidebar.match({
99           some: sidebar => this.siteSidebar(sidebar),
100           none: <></>,
101         })}
102         {this.props.counts.match({
103           some: counts => this.badges(counts),
104           none: <></>,
105         })}
106         {this.props.admins.match({
107           some: admins => this.admins(admins),
108           none: <></>,
109         })}
110       </div>
111     );
112   }
113
114   adminButtons() {
115     return (
116       amAdmin() && (
117         <ul className="list-inline mb-1 text-muted font-weight-bold">
118           <li className="list-inline-item-action">
119             <button
120               className="btn btn-link d-inline-block text-muted"
121               onClick={linkEvent(this, this.handleEditClick)}
122               aria-label={i18n.t("edit")}
123               data-tippy-content={i18n.t("edit")}
124             >
125               <Icon icon="edit" classes="icon-inline" />
126             </button>
127           </li>
128         </ul>
129       )
130     );
131   }
132
133   siteSidebar(sidebar: string) {
134     return (
135       <div className="md-div" dangerouslySetInnerHTML={mdToHtml(sidebar)} />
136     );
137   }
138
139   admins(admins: PersonViewSafe[]) {
140     return (
141       <ul className="mt-1 list-inline small mb-0">
142         <li className="list-inline-item">{i18n.t("admins")}:</li>
143         {admins.map(av => (
144           <li key={av.person.id} className="list-inline-item">
145             <PersonListing person={av.person} />
146           </li>
147         ))}
148       </ul>
149     );
150   }
151
152   badges(siteAggregates: SiteAggregates) {
153     let counts = siteAggregates;
154     let online = this.props.online.unwrapOr(1);
155     return (
156       <ul className="my-2 list-inline">
157         <li className="list-inline-item badge badge-secondary">
158           {i18n.t("number_online", {
159             count: online,
160             formattedCount: numToSI(online),
161           })}
162         </li>
163         <li
164           className="list-inline-item badge badge-secondary pointer"
165           data-tippy-content={i18n.t("active_users_in_the_last_day", {
166             count: counts.users_active_day,
167             formattedCount: numToSI(counts.users_active_day),
168           })}
169         >
170           {i18n.t("number_of_users", {
171             count: counts.users_active_day,
172             formattedCount: numToSI(counts.users_active_day),
173           })}{" "}
174           / {i18n.t("day")}
175         </li>
176         <li
177           className="list-inline-item badge badge-secondary pointer"
178           data-tippy-content={i18n.t("active_users_in_the_last_week", {
179             count: counts.users_active_week,
180             formattedCount: counts.users_active_week,
181           })}
182         >
183           {i18n.t("number_of_users", {
184             count: counts.users_active_week,
185             formattedCount: numToSI(counts.users_active_week),
186           })}{" "}
187           / {i18n.t("week")}
188         </li>
189         <li
190           className="list-inline-item badge badge-secondary pointer"
191           data-tippy-content={i18n.t("active_users_in_the_last_month", {
192             count: counts.users_active_month,
193             formattedCount: counts.users_active_month,
194           })}
195         >
196           {i18n.t("number_of_users", {
197             count: counts.users_active_month,
198             formattedCount: numToSI(counts.users_active_month),
199           })}{" "}
200           / {i18n.t("month")}
201         </li>
202         <li
203           className="list-inline-item badge badge-secondary pointer"
204           data-tippy-content={i18n.t("active_users_in_the_last_six_months", {
205             count: counts.users_active_half_year,
206             formattedCount: counts.users_active_half_year,
207           })}
208         >
209           {i18n.t("number_of_users", {
210             count: counts.users_active_half_year,
211             formattedCount: numToSI(counts.users_active_half_year),
212           })}{" "}
213           / {i18n.t("number_of_months", { count: 6, formattedCount: 6 })}
214         </li>
215         <li className="list-inline-item badge badge-secondary">
216           {i18n.t("number_of_users", {
217             count: counts.users,
218             formattedCount: numToSI(counts.users),
219           })}
220         </li>
221         <li className="list-inline-item badge badge-secondary">
222           {i18n.t("number_of_communities", {
223             count: counts.communities,
224             formattedCount: numToSI(counts.communities),
225           })}
226         </li>
227         <li className="list-inline-item badge badge-secondary">
228           {i18n.t("number_of_posts", {
229             count: counts.posts,
230             formattedCount: numToSI(counts.posts),
231           })}
232         </li>
233         <li className="list-inline-item badge badge-secondary">
234           {i18n.t("number_of_comments", {
235             count: counts.comments,
236             formattedCount: numToSI(counts.comments),
237           })}
238         </li>
239         <li className="list-inline-item">
240           <Link className="badge badge-primary" to="/modlog">
241             {i18n.t("modlog")}
242           </Link>
243         </li>
244       </ul>
245     );
246   }
247
248   handleCollapseSidebar(i: SiteSidebar) {
249     i.setState({ collapsed: !i.state.collapsed });
250   }
251
252   handleEditClick(i: SiteSidebar) {
253     i.setState({ showEdit: true });
254   }
255
256   handleEditSite() {
257     this.setState({ showEdit: false });
258   }
259
260   handleEditCancel() {
261     this.setState({ showEdit: false });
262   }
263 }