]> Untitled Git - lemmy-ui.git/blob - src/shared/components/admin-settings.tsx
Running newer prettier.
[lemmy-ui.git] / src / shared / components / admin-settings.tsx
1 import { Component, linkEvent } from "inferno";
2 import { Subscription } from "rxjs";
3 import {
4   UserOperation,
5   SiteResponse,
6   GetSiteResponse,
7   SaveSiteConfig,
8   GetSiteConfigResponse,
9   GetSiteConfig,
10 } from "lemmy-js-client";
11 import { WebSocketService } from "../services";
12 import {
13   wsJsonToRes,
14   capitalizeFirstLetter,
15   toast,
16   randomStr,
17   setIsoData,
18   wsSubscribe,
19   isBrowser,
20   wsUserOp,
21   wsClient,
22   authField,
23 } from "../utils";
24 import autosize from "autosize";
25 import { SiteForm } from "./site-form";
26 import { UserListing } from "./user-listing";
27 import { HtmlTags } from "./html-tags";
28 import { Spinner } from "./icon";
29 import { i18n } from "../i18next";
30 import { InitialFetchRequest } from "shared/interfaces";
31
32 interface AdminSettingsState {
33   siteRes: GetSiteResponse;
34   siteConfigRes: GetSiteConfigResponse;
35   siteConfigForm: SaveSiteConfig;
36   loading: boolean;
37   siteConfigLoading: boolean;
38 }
39
40 export class AdminSettings extends Component<any, AdminSettingsState> {
41   private siteConfigTextAreaId = `site-config-${randomStr()}`;
42   private isoData = setIsoData(this.context);
43   private subscription: Subscription;
44   private emptyState: AdminSettingsState = {
45     siteRes: this.isoData.site_res,
46     siteConfigForm: {
47       config_hjson: null,
48       auth: authField(),
49     },
50     siteConfigRes: {
51       config_hjson: null,
52     },
53     loading: true,
54     siteConfigLoading: null,
55   };
56
57   constructor(props: any, context: any) {
58     super(props, context);
59
60     this.state = this.emptyState;
61
62     this.parseMessage = this.parseMessage.bind(this);
63     this.subscription = wsSubscribe(this.parseMessage);
64
65     // Only fetch the data if coming from another route
66     if (this.isoData.path == this.context.router.route.match.url) {
67       this.state.siteConfigRes = this.isoData.routeData[0];
68       this.state.siteConfigForm.config_hjson = this.state.siteConfigRes.config_hjson;
69       this.state.siteConfigLoading = false;
70       this.state.loading = false;
71     } else {
72       WebSocketService.Instance.send(
73         wsClient.getSiteConfig({
74           auth: authField(),
75         })
76       );
77     }
78   }
79
80   static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
81     let form: GetSiteConfig = { auth: req.auth };
82     return [req.client.getSiteConfig(form)];
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 `${i18n.t("admin_settings")} - ${
100       this.state.siteRes.site_view.site.name
101     }`;
102   }
103
104   render() {
105     return (
106       <div class="container">
107         <HtmlTags
108           title={this.documentTitle}
109           path={this.context.router.route.match.url}
110         />
111         {this.state.loading ? (
112           <h5>
113             <Spinner />
114           </h5>
115         ) : (
116           <div class="row">
117             <div class="col-12 col-md-6">
118               {this.state.siteRes.site_view.site.id && (
119                 <SiteForm site={this.state.siteRes.site_view.site} />
120               )}
121               {this.admins()}
122               {this.bannedUsers()}
123             </div>
124             <div class="col-12 col-md-6">{this.adminSettings()}</div>
125           </div>
126         )}
127       </div>
128     );
129   }
130
131   admins() {
132     return (
133       <>
134         <h5>{capitalizeFirstLetter(i18n.t("admins"))}</h5>
135         <ul class="list-unstyled">
136           {this.state.siteRes.admins.map(admin => (
137             <li class="list-inline-item">
138               <UserListing user={admin.user} />
139             </li>
140           ))}
141         </ul>
142       </>
143     );
144   }
145
146   bannedUsers() {
147     return (
148       <>
149         <h5>{i18n.t("banned_users")}</h5>
150         <ul class="list-unstyled">
151           {this.state.siteRes.banned.map(banned => (
152             <li class="list-inline-item">
153               <UserListing user={banned.user} />
154             </li>
155           ))}
156         </ul>
157       </>
158     );
159   }
160
161   adminSettings() {
162     return (
163       <div>
164         <h5>{i18n.t("admin_settings")}</h5>
165         <form onSubmit={linkEvent(this, this.handleSiteConfigSubmit)}>
166           <div class="form-group row">
167             <label
168               class="col-12 col-form-label"
169               htmlFor={this.siteConfigTextAreaId}
170             >
171               {i18n.t("site_config")}
172             </label>
173             <div class="col-12">
174               <textarea
175                 id={this.siteConfigTextAreaId}
176                 value={this.state.siteConfigForm.config_hjson}
177                 onInput={linkEvent(this, this.handleSiteConfigHjsonChange)}
178                 class="form-control text-monospace"
179                 rows={3}
180               />
181             </div>
182           </div>
183           <div class="form-group row">
184             <div class="col-12">
185               <button type="submit" class="btn btn-secondary mr-2">
186                 {this.state.siteConfigLoading ? (
187                   <Spinner />
188                 ) : (
189                   capitalizeFirstLetter(i18n.t("save"))
190                 )}
191               </button>
192             </div>
193           </div>
194         </form>
195       </div>
196     );
197   }
198
199   handleSiteConfigSubmit(i: AdminSettings, event: any) {
200     event.preventDefault();
201     i.state.siteConfigLoading = true;
202     WebSocketService.Instance.send(
203       wsClient.saveSiteConfig(i.state.siteConfigForm)
204     );
205     i.setState(i.state);
206   }
207
208   handleSiteConfigHjsonChange(i: AdminSettings, event: any) {
209     i.state.siteConfigForm.config_hjson = event.target.value;
210     i.setState(i.state);
211   }
212
213   parseMessage(msg: any) {
214     let op = wsUserOp(msg);
215     if (msg.error) {
216       toast(i18n.t(msg.error), "danger");
217       this.context.router.history.push("/");
218       this.state.loading = false;
219       this.setState(this.state);
220       return;
221     } else if (op == UserOperation.EditSite) {
222       let data = wsJsonToRes<SiteResponse>(msg).data;
223       this.state.siteRes.site_view = data.site_view;
224       this.setState(this.state);
225       toast(i18n.t("site_saved"));
226     } else if (op == UserOperation.GetSiteConfig) {
227       let data = wsJsonToRes<GetSiteConfigResponse>(msg).data;
228       this.state.siteConfigRes = data;
229       this.state.loading = false;
230       this.state.siteConfigForm.config_hjson = this.state.siteConfigRes.config_hjson;
231       this.setState(this.state);
232       var textarea: any = document.getElementById(this.siteConfigTextAreaId);
233       autosize(textarea);
234     } else if (op == UserOperation.SaveSiteConfig) {
235       let data = wsJsonToRes<GetSiteConfigResponse>(msg).data;
236       this.state.siteConfigRes = data;
237       this.state.siteConfigForm.config_hjson = this.state.siteConfigRes.config_hjson;
238       this.state.siteConfigLoading = false;
239       toast(i18n.t("site_saved"));
240       this.setState(this.state);
241     }
242   }
243 }