]> Untitled Git - lemmy-ui.git/blob - src/shared/components/home/admin-settings.tsx
Fixing nav-link
[lemmy-ui.git] / src / shared / components / home / admin-settings.tsx
1 import autosize from "autosize";
2 import { Component, linkEvent } from "inferno";
3 import {
4   GetSiteConfig,
5   GetSiteConfigResponse,
6   GetSiteResponse,
7   SaveSiteConfig,
8   SiteResponse,
9   UserOperation,
10 } from "lemmy-js-client";
11 import { Subscription } from "rxjs";
12 import { i18n } from "../../i18next";
13 import { InitialFetchRequest } from "../../interfaces";
14 import { WebSocketService } from "../../services";
15 import {
16   authField,
17   capitalizeFirstLetter,
18   isBrowser,
19   randomStr,
20   setIsoData,
21   toast,
22   wsClient,
23   wsJsonToRes,
24   wsSubscribe,
25   wsUserOp,
26 } from "../../utils";
27 import { HtmlTags } from "../common/html-tags";
28 import { Spinner } from "../common/icon";
29 import { PersonListing } from "../person/person-listing";
30 import { SiteForm } from "./site-form";
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 =
69         this.state.siteConfigRes.config_hjson;
70       this.state.siteConfigLoading = false;
71       this.state.loading = false;
72     } else {
73       WebSocketService.Instance.send(
74         wsClient.getSiteConfig({
75           auth: authField(),
76         })
77       );
78     }
79   }
80
81   static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
82     let form: GetSiteConfig = { auth: req.auth };
83     return [req.client.getSiteConfig(form)];
84   }
85
86   componentDidMount() {
87     if (isBrowser()) {
88       var textarea: any = document.getElementById(this.siteConfigTextAreaId);
89       autosize(textarea);
90     }
91   }
92
93   componentWillUnmount() {
94     if (isBrowser()) {
95       this.subscription.unsubscribe();
96     }
97   }
98
99   get documentTitle(): string {
100     return `${i18n.t("admin_settings")} - ${
101       this.state.siteRes.site_view.site.name
102     }`;
103   }
104
105   render() {
106     return (
107       <div class="container">
108         <HtmlTags
109           title={this.documentTitle}
110           path={this.context.router.route.match.url}
111         />
112         {this.state.loading ? (
113           <h5>
114             <Spinner large />
115           </h5>
116         ) : (
117           <div class="row">
118             <div class="col-12 col-md-6">
119               {this.state.siteRes.site_view.site.id && (
120                 <SiteForm site={this.state.siteRes.site_view.site} />
121               )}
122               {this.admins()}
123               {this.bannedUsers()}
124             </div>
125             <div class="col-12 col-md-6">{this.adminSettings()}</div>
126           </div>
127         )}
128       </div>
129     );
130   }
131
132   admins() {
133     return (
134       <>
135         <h5>{capitalizeFirstLetter(i18n.t("admins"))}</h5>
136         <ul class="list-unstyled">
137           {this.state.siteRes.admins.map(admin => (
138             <li class="list-inline-item">
139               <PersonListing person={admin.person} />
140             </li>
141           ))}
142         </ul>
143       </>
144     );
145   }
146
147   bannedUsers() {
148     return (
149       <>
150         <h5>{i18n.t("banned_users")}</h5>
151         <ul class="list-unstyled">
152           {this.state.siteRes.banned.map(banned => (
153             <li class="list-inline-item">
154               <PersonListing person={banned.person} />
155             </li>
156           ))}
157         </ul>
158       </>
159     );
160   }
161
162   adminSettings() {
163     return (
164       <div>
165         <h5>{i18n.t("admin_settings")}</h5>
166         <form onSubmit={linkEvent(this, this.handleSiteConfigSubmit)}>
167           <div class="form-group row">
168             <label
169               class="col-12 col-form-label"
170               htmlFor={this.siteConfigTextAreaId}
171             >
172               {i18n.t("site_config")}
173             </label>
174             <div class="col-12">
175               <textarea
176                 id={this.siteConfigTextAreaId}
177                 value={this.state.siteConfigForm.config_hjson}
178                 onInput={linkEvent(this, this.handleSiteConfigHjsonChange)}
179                 class="form-control text-monospace"
180                 rows={3}
181               />
182             </div>
183           </div>
184           <div class="form-group row">
185             <div class="col-12">
186               <button type="submit" class="btn btn-secondary mr-2">
187                 {this.state.siteConfigLoading ? (
188                   <Spinner />
189                 ) : (
190                   capitalizeFirstLetter(i18n.t("save"))
191                 )}
192               </button>
193             </div>
194           </div>
195         </form>
196       </div>
197     );
198   }
199
200   handleSiteConfigSubmit(i: AdminSettings, event: any) {
201     event.preventDefault();
202     i.state.siteConfigLoading = true;
203     WebSocketService.Instance.send(
204       wsClient.saveSiteConfig(i.state.siteConfigForm)
205     );
206     i.setState(i.state);
207   }
208
209   handleSiteConfigHjsonChange(i: AdminSettings, event: any) {
210     i.state.siteConfigForm.config_hjson = event.target.value;
211     i.setState(i.state);
212   }
213
214   parseMessage(msg: any) {
215     let op = wsUserOp(msg);
216     console.log(msg);
217     if (msg.error) {
218       toast(i18n.t(msg.error), "danger");
219       this.context.router.history.push("/");
220       this.state.loading = false;
221       this.setState(this.state);
222       return;
223     } else if (op == UserOperation.EditSite) {
224       let data = wsJsonToRes<SiteResponse>(msg).data;
225       this.state.siteRes.site_view = data.site_view;
226       this.setState(this.state);
227       toast(i18n.t("site_saved"));
228     } else if (op == UserOperation.GetSiteConfig) {
229       let data = wsJsonToRes<GetSiteConfigResponse>(msg).data;
230       this.state.siteConfigRes = data;
231       this.state.loading = false;
232       this.state.siteConfigForm.config_hjson =
233         this.state.siteConfigRes.config_hjson;
234       this.setState(this.state);
235       var textarea: any = document.getElementById(this.siteConfigTextAreaId);
236       autosize(textarea);
237     } else if (op == UserOperation.SaveSiteConfig) {
238       let data = wsJsonToRes<GetSiteConfigResponse>(msg).data;
239       this.state.siteConfigRes = data;
240       this.state.siteConfigForm.config_hjson =
241         this.state.siteConfigRes.config_hjson;
242       this.state.siteConfigLoading = false;
243       toast(i18n.t("site_saved"));
244       this.setState(this.state);
245     }
246   }
247 }