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