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";
12 interface SiteSidebarProps {
15 counts: Option<SiteAggregates>;
16 admins: Option<PersonViewSafe[]>;
17 online: Option<number>;
20 interface SiteSidebarState {
25 export class SiteSidebar extends Component<SiteSidebarProps, SiteSidebarState> {
26 private emptyState: SiteSidebarState = {
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);
39 let site = this.props.site;
41 <div className="card border-secondary mb-3">
42 <div className="card-body">
43 {!this.state.showEdit ? (
45 <div className="mb-2">
47 {this.props.admins.isSome() && this.adminButtons()}
49 {!this.state.collapsed && (
51 <BannerIconHeader banner={site.banner} icon={None} />
59 showLocal={this.props.showLocal}
60 onEdit={this.handleEditSite}
61 onCancel={this.handleEditCancel}
70 let site = this.props.site;
72 <h5 className="mb-0 d-inline">
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")}
80 {this.state.collapsed ? (
81 <Icon icon="plus-square" classes="icon-inline" />
83 <Icon icon="minus-square" classes="icon-inline" />
91 let site = this.props.site;
94 {site.description.match({
95 some: description => <h6>{description}</h6>,
99 some: sidebar => this.siteSidebar(sidebar),
102 {this.props.counts.match({
103 some: counts => this.badges(counts),
106 {this.props.admins.match({
107 some: admins => this.admins(admins),
117 <ul className="list-inline mb-1 text-muted font-weight-bold">
118 <li className="list-inline-item-action">
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")}
125 <Icon icon="edit" classes="icon-inline" />
133 siteSidebar(sidebar: string) {
135 <div className="md-div" dangerouslySetInnerHTML={mdToHtml(sidebar)} />
139 admins(admins: PersonViewSafe[]) {
141 <ul className="mt-1 list-inline small mb-0">
142 <li className="list-inline-item">{i18n.t("admins")}:</li>
144 <li key={av.person.id} className="list-inline-item">
145 <PersonListing person={av.person} />
152 badges(siteAggregates: SiteAggregates) {
153 let counts = siteAggregates;
154 let online = this.props.online.unwrapOr(1);
156 <ul className="my-2 list-inline">
157 <li className="list-inline-item badge badge-secondary">
158 {i18n.t("number_online", {
160 formattedCount: numToSI(online),
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),
170 {i18n.t("number_of_users", {
171 count: counts.users_active_day,
172 formattedCount: numToSI(counts.users_active_day),
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,
183 {i18n.t("number_of_users", {
184 count: counts.users_active_week,
185 formattedCount: numToSI(counts.users_active_week),
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,
196 {i18n.t("number_of_users", {
197 count: counts.users_active_month,
198 formattedCount: numToSI(counts.users_active_month),
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,
209 {i18n.t("number_of_users", {
210 count: counts.users_active_half_year,
211 formattedCount: numToSI(counts.users_active_half_year),
213 / {i18n.t("number_of_months", { count: 6, formattedCount: 6 })}
215 <li className="list-inline-item badge badge-secondary">
216 {i18n.t("number_of_users", {
218 formattedCount: numToSI(counts.users),
221 <li className="list-inline-item badge badge-secondary">
222 {i18n.t("number_of_communities", {
223 count: counts.communities,
224 formattedCount: numToSI(counts.communities),
227 <li className="list-inline-item badge badge-secondary">
228 {i18n.t("number_of_posts", {
230 formattedCount: numToSI(counts.posts),
233 <li className="list-inline-item badge badge-secondary">
234 {i18n.t("number_of_comments", {
235 count: counts.comments,
236 formattedCount: numToSI(counts.comments),
239 <li className="list-inline-item">
240 <Link className="badge badge-primary" to="/modlog">
248 handleCollapseSidebar(i: SiteSidebar) {
249 i.setState({ collapsed: !i.state.collapsed });
252 handleEditClick(i: SiteSidebar) {
253 i.setState({ showEdit: true });
257 this.setState({ showEdit: false });
261 this.setState({ showEdit: false });