]> Untitled Git - lemmy-ui.git/blob - src/shared/components/home/admin-settings.tsx
Lint fix (#1035)
[lemmy-ui.git] / src / shared / components / home / admin-settings.tsx
1 import autosize from "autosize";
2 import { Component, linkEvent } from "inferno";
3 import {
4   BannedPersonsResponse,
5   GetBannedPersons,
6   GetFederatedInstancesResponse,
7   GetSiteResponse,
8   PersonView,
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   capitalizeFirstLetter,
20   isBrowser,
21   myAuth,
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 { EmojiForm } from "./emojis-form";
33 import { SiteForm } from "./site-form";
34 import { TaglineForm } from "./tagline-form";
35
36 interface AdminSettingsState {
37   siteRes: GetSiteResponse;
38   instancesRes?: GetFederatedInstancesResponse;
39   banned: PersonView[];
40   loading: boolean;
41   leaveAdminTeamLoading: boolean;
42   currentTab: string;
43 }
44
45 export class AdminSettings extends Component<any, AdminSettingsState> {
46   private siteConfigTextAreaId = `site-config-${randomStr()}`;
47   private isoData = setIsoData(this.context);
48   private subscription?: Subscription;
49   state: AdminSettingsState = {
50     siteRes: this.isoData.site_res,
51     banned: [],
52     loading: true,
53     leaveAdminTeamLoading: false,
54     currentTab: "site",
55   };
56
57   constructor(props: any, context: any) {
58     super(props, context);
59
60     this.parseMessage = this.parseMessage.bind(this);
61     this.subscription = wsSubscribe(this.parseMessage);
62
63     // Only fetch the data if coming from another route
64     if (this.isoData.path == this.context.router.route.match.url) {
65       this.state = {
66         ...this.state,
67         banned: (this.isoData.routeData[0] as BannedPersonsResponse).banned,
68         instancesRes: this.isoData
69           .routeData[1] as GetFederatedInstancesResponse,
70         loading: false,
71       };
72     } else {
73       let cAuth = myAuth();
74       if (cAuth) {
75         WebSocketService.Instance.send(
76           wsClient.getBannedPersons({
77             auth: cAuth,
78           })
79         );
80         WebSocketService.Instance.send(
81           wsClient.getFederatedInstances({ auth: cAuth })
82         );
83       }
84     }
85   }
86
87   static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
88     let promises: Promise<any>[] = [];
89
90     let auth = req.auth;
91     if (auth) {
92       let bannedPersonsForm: GetBannedPersons = { auth };
93       promises.push(req.client.getBannedPersons(bannedPersonsForm));
94       promises.push(req.client.getFederatedInstances({ auth }));
95     }
96
97     return promises;
98   }
99
100   componentDidMount() {
101     if (isBrowser()) {
102       var textarea: any = document.getElementById(this.siteConfigTextAreaId);
103       autosize(textarea);
104     }
105   }
106
107   componentWillUnmount() {
108     if (isBrowser()) {
109       this.subscription?.unsubscribe();
110     }
111   }
112
113   get documentTitle(): string {
114     return `${i18n.t("admin_settings")} - ${
115       this.state.siteRes.site_view.site.name
116     }`;
117   }
118
119   render() {
120     return (
121       <div className="container-lg">
122         {this.state.loading ? (
123           <h5>
124             <Spinner large />
125           </h5>
126         ) : (
127           <div>
128             <HtmlTags
129               title={this.documentTitle}
130               path={this.context.router.route.match.url}
131             />
132             <ul className="nav nav-tabs mb-2">
133               <li className="nav-item">
134                 <button
135                   className={`nav-link btn ${
136                     this.state.currentTab == "site" && "active"
137                   }`}
138                   onClick={linkEvent(
139                     { ctx: this, tab: "site" },
140                     this.handleSwitchTab
141                   )}
142                 >
143                   {i18n.t("site")}
144                 </button>
145               </li>
146               <li className="nav-item">
147                 <button
148                   className={`nav-link btn ${
149                     this.state.currentTab == "taglines" && "active"
150                   }`}
151                   onClick={linkEvent(
152                     { ctx: this, tab: "taglines" },
153                     this.handleSwitchTab
154                   )}
155                 >
156                   {i18n.t("taglines")}
157                 </button>
158               </li>
159               <li className="nav-item">
160                 <button
161                   className={`nav-link btn ${
162                     this.state.currentTab == "emojis" && "active"
163                   }`}
164                   onClick={linkEvent(
165                     { ctx: this, tab: "emojis" },
166                     this.handleSwitchTab
167                   )}
168                 >
169                   {i18n.t("emojis")}
170                 </button>
171               </li>
172             </ul>
173             {this.state.currentTab == "site" && (
174               <div className="row">
175                 <div className="col-12 col-md-6">
176                   <SiteForm
177                     siteRes={this.state.siteRes}
178                     instancesRes={this.state.instancesRes}
179                     showLocal={showLocal(this.isoData)}
180                   />
181                 </div>
182                 <div className="col-12 col-md-6">
183                   {this.admins()}
184                   {this.bannedUsers()}
185                 </div>
186               </div>
187             )}
188             {this.state.currentTab == "taglines" && (
189               <div className="row">
190                 <TaglineForm siteRes={this.state.siteRes}></TaglineForm>
191               </div>
192             )}
193             {this.state.currentTab == "emojis" && (
194               <div className="row">
195                 <EmojiForm></EmojiForm>
196               </div>
197             )}
198           </div>
199         )}
200       </div>
201     );
202   }
203
204   admins() {
205     return (
206       <>
207         <h5>{capitalizeFirstLetter(i18n.t("admins"))}</h5>
208         <ul className="list-unstyled">
209           {this.state.siteRes.admins.map(admin => (
210             <li key={admin.person.id} className="list-inline-item">
211               <PersonListing person={admin.person} />
212             </li>
213           ))}
214         </ul>
215         {this.leaveAdmin()}
216       </>
217     );
218   }
219
220   leaveAdmin() {
221     return (
222       <button
223         onClick={linkEvent(this, this.handleLeaveAdminTeam)}
224         className="btn btn-danger mb-2"
225       >
226         {this.state.leaveAdminTeamLoading ? (
227           <Spinner />
228         ) : (
229           i18n.t("leave_admin_team")
230         )}
231       </button>
232     );
233   }
234
235   bannedUsers() {
236     return (
237       <>
238         <h5>{i18n.t("banned_users")}</h5>
239         <ul className="list-unstyled">
240           {this.state.banned.map(banned => (
241             <li key={banned.person.id} className="list-inline-item">
242               <PersonListing person={banned.person} />
243             </li>
244           ))}
245         </ul>
246       </>
247     );
248   }
249
250   handleSwitchTab(i: { ctx: AdminSettings; tab: string }) {
251     i.ctx.setState({ currentTab: i.tab });
252   }
253
254   handleLeaveAdminTeam(i: AdminSettings) {
255     let auth = myAuth();
256     if (auth) {
257       i.setState({ leaveAdminTeamLoading: true });
258       WebSocketService.Instance.send(wsClient.leaveAdmin({ auth }));
259     }
260   }
261
262   parseMessage(msg: any) {
263     let op = wsUserOp(msg);
264     console.log(msg);
265     if (msg.error) {
266       toast(i18n.t(msg.error), "danger");
267       this.context.router.history.push("/");
268       this.setState({ loading: false });
269       return;
270     } else if (op == UserOperation.EditSite) {
271       let data = wsJsonToRes<SiteResponse>(msg);
272       this.setState(s => ((s.siteRes.site_view = data.site_view), s));
273       toast(i18n.t("site_saved"));
274     } else if (op == UserOperation.GetBannedPersons) {
275       let data = wsJsonToRes<BannedPersonsResponse>(msg);
276       this.setState({ banned: data.banned, loading: false });
277     } else if (op == UserOperation.LeaveAdmin) {
278       let data = wsJsonToRes<GetSiteResponse>(msg);
279       this.setState(s => ((s.siteRes.site_view = data.site_view), s));
280       this.setState({ leaveAdminTeamLoading: false });
281       toast(i18n.t("left_admin_team"));
282       this.context.router.history.push("/");
283     } else if (op == UserOperation.GetFederatedInstances) {
284       let data = wsJsonToRes<GetFederatedInstancesResponse>(msg);
285       this.setState({ instancesRes: data });
286     }
287   }
288 }