]> Untitled Git - lemmy-ui.git/blob - src/shared/components/home/admin-settings.tsx
Change for container divs to container-lg (#813)
[lemmy-ui.git] / src / shared / components / home / admin-settings.tsx
1 import { None, Some } from "@sniptt/monads";
2 import autosize from "autosize";
3 import { Component, linkEvent } from "inferno";
4 import {
5   BannedPersonsResponse,
6   GetBannedPersons,
7   GetSiteResponse,
8   PersonViewSafe,
9   SiteResponse,
10   UserOperation,
11   wsJsonToRes,
12   wsUserOp,
13 } from "lemmy-js-client";
14 import { Subscription } from "rxjs";
15 import { i18n } from "../../i18next";
16 import { InitialFetchRequest } from "../../interfaces";
17 import { WebSocketService } from "../../services";
18 import {
19   auth,
20   capitalizeFirstLetter,
21   isBrowser,
22   randomStr,
23   setIsoData,
24   showLocal,
25   toast,
26   wsClient,
27   wsSubscribe,
28 } from "../../utils";
29 import { HtmlTags } from "../common/html-tags";
30 import { Spinner } from "../common/icon";
31 import { PersonListing } from "../person/person-listing";
32 import { SiteForm } from "./site-form";
33
34 interface AdminSettingsState {
35   siteRes: GetSiteResponse;
36   banned: PersonViewSafe[];
37   loading: boolean;
38   leaveAdminTeamLoading: boolean;
39 }
40
41 export class AdminSettings extends Component<any, AdminSettingsState> {
42   private siteConfigTextAreaId = `site-config-${randomStr()}`;
43   private isoData = setIsoData(this.context, BannedPersonsResponse);
44   private subscription: Subscription;
45   private emptyState: AdminSettingsState = {
46     siteRes: this.isoData.site_res,
47     banned: [],
48     loading: true,
49     leaveAdminTeamLoading: null,
50   };
51
52   constructor(props: any, context: any) {
53     super(props, context);
54
55     this.state = this.emptyState;
56
57     this.parseMessage = this.parseMessage.bind(this);
58     this.subscription = wsSubscribe(this.parseMessage);
59
60     // Only fetch the data if coming from another route
61     if (this.isoData.path == this.context.router.route.match.url) {
62       this.state = {
63         ...this.state,
64         banned: (this.isoData.routeData[0] as BannedPersonsResponse).banned,
65         loading: false,
66       };
67     } else {
68       WebSocketService.Instance.send(
69         wsClient.getBannedPersons({
70           auth: auth().unwrap(),
71         })
72       );
73     }
74   }
75
76   static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
77     let promises: Promise<any>[] = [];
78
79     let bannedPersonsForm = new GetBannedPersons({ auth: req.auth.unwrap() });
80     promises.push(req.client.getBannedPersons(bannedPersonsForm));
81
82     return promises;
83   }
84
85   componentDidMount() {
86     if (isBrowser()) {
87       var textarea: any = document.getElementById(this.siteConfigTextAreaId);
88       autosize(textarea);
89     }
90   }
91
92   componentWillUnmount() {
93     if (isBrowser()) {
94       this.subscription.unsubscribe();
95     }
96   }
97
98   get documentTitle(): string {
99     return this.state.siteRes.site_view.match({
100       some: siteView => `${i18n.t("admin_settings")} - ${siteView.site.name}`,
101       none: "",
102     });
103   }
104
105   render() {
106     return (
107       <div className="container-lg">
108         {this.state.loading ? (
109           <h5>
110             <Spinner large />
111           </h5>
112         ) : (
113           <div className="row">
114             <div className="col-12 col-md-6">
115               <HtmlTags
116                 title={this.documentTitle}
117                 path={this.context.router.route.match.url}
118                 description={None}
119                 image={None}
120               />
121               {this.state.siteRes.site_view.match({
122                 some: siteView => (
123                   <SiteForm
124                     site={Some(siteView.site)}
125                     showLocal={showLocal(this.isoData)}
126                   />
127                 ),
128                 none: <></>,
129               })}
130             </div>
131             <div className="col-12 col-md-6">
132               {this.admins()}
133               {this.bannedUsers()}
134             </div>
135           </div>
136         )}
137       </div>
138     );
139   }
140
141   admins() {
142     return (
143       <>
144         <h5>{capitalizeFirstLetter(i18n.t("admins"))}</h5>
145         <ul className="list-unstyled">
146           {this.state.siteRes.admins.map(admin => (
147             <li key={admin.person.id} className="list-inline-item">
148               <PersonListing person={admin.person} />
149             </li>
150           ))}
151         </ul>
152         {this.leaveAdmin()}
153       </>
154     );
155   }
156
157   leaveAdmin() {
158     return (
159       <button
160         onClick={linkEvent(this, this.handleLeaveAdminTeam)}
161         className="btn btn-danger mb-2"
162       >
163         {this.state.leaveAdminTeamLoading ? (
164           <Spinner />
165         ) : (
166           i18n.t("leave_admin_team")
167         )}
168       </button>
169     );
170   }
171
172   bannedUsers() {
173     return (
174       <>
175         <h5>{i18n.t("banned_users")}</h5>
176         <ul className="list-unstyled">
177           {this.state.banned.map(banned => (
178             <li key={banned.person.id} className="list-inline-item">
179               <PersonListing person={banned.person} />
180             </li>
181           ))}
182         </ul>
183       </>
184     );
185   }
186
187   handleLeaveAdminTeam(i: AdminSettings) {
188     i.setState({ leaveAdminTeamLoading: true });
189     WebSocketService.Instance.send(
190       wsClient.leaveAdmin({ auth: auth().unwrap() })
191     );
192   }
193
194   parseMessage(msg: any) {
195     let op = wsUserOp(msg);
196     console.log(msg);
197     if (msg.error) {
198       toast(i18n.t(msg.error), "danger");
199       this.context.router.history.push("/");
200       this.setState({ loading: false });
201       return;
202     } else if (op == UserOperation.EditSite) {
203       let data = wsJsonToRes<SiteResponse>(msg, SiteResponse);
204       this.setState(s => ((s.siteRes.site_view = Some(data.site_view)), s));
205       toast(i18n.t("site_saved"));
206     } else if (op == UserOperation.GetBannedPersons) {
207       let data = wsJsonToRes<BannedPersonsResponse>(msg, BannedPersonsResponse);
208       this.setState({ banned: data.banned, loading: false });
209     } else if (op == UserOperation.LeaveAdmin) {
210       let data = wsJsonToRes<GetSiteResponse>(msg, GetSiteResponse);
211       this.setState(s => ((s.siteRes.site_view = data.site_view), s));
212       this.setState({ leaveAdminTeamLoading: false });
213
214       toast(i18n.t("left_admin_team"));
215       this.context.router.history.push("/");
216     }
217   }
218 }