1 import { Component, linkEvent } from 'inferno';
2 import { Helmet } from 'inferno-helmet';
3 import { Subscription } from 'rxjs';
4 import { retryWhen, delay, take } from 'rxjs/operators';
10 GetSiteConfigResponse,
11 WebSocketJsonResponse,
12 } from 'lemmy-js-client';
13 import { WebSocketService } from '../services';
14 import { wsJsonToRes, capitalizeFirstLetter, toast, randomStr } from '../utils';
15 import autosize from 'autosize';
16 import { SiteForm } from './site-form';
17 import { UserListing } from './user-listing';
18 import { i18n } from '../i18next';
20 interface AdminSettingsState {
21 siteRes: GetSiteResponse;
22 siteConfigRes: GetSiteConfigResponse;
23 siteConfigForm: SiteConfigForm;
25 siteConfigLoading: boolean;
28 export class AdminSettings extends Component<any, AdminSettingsState> {
29 private siteConfigTextAreaId = `site-config-${randomStr()}`;
30 private subscription: Subscription;
31 private emptyState: AdminSettingsState = {
39 number_of_users: null,
40 number_of_posts: null,
41 number_of_comments: null,
42 number_of_communities: null,
43 enable_downvotes: null,
44 open_registration: null,
51 federated_instances: null,
61 siteConfigLoading: null,
64 constructor(props: any, context: any) {
65 super(props, context);
67 this.state = this.emptyState;
69 this.subscription = WebSocketService.Instance.subject
70 .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
72 msg => this.parseMessage(msg),
73 err => console.error(err),
74 () => console.log('complete')
77 WebSocketService.Instance.getSite();
78 WebSocketService.Instance.getSiteConfig();
81 componentWillUnmount() {
82 this.subscription.unsubscribe();
85 get documentTitle(): string {
86 if (this.state.siteRes.site.name) {
87 return `${i18n.t('admin_settings')} - ${this.state.siteRes.site.name}`;
95 <div class="container">
96 <Helmet title={this.documentTitle} />
97 {this.state.loading ? (
99 <svg class="icon icon-spinner spin">
100 <use xlinkHref="#icon-spinner"></use>
105 <div class="col-12 col-md-6">
106 {this.state.siteRes.site.id && (
107 <SiteForm site={this.state.siteRes.site} />
112 <div class="col-12 col-md-6">{this.adminSettings()}</div>
122 <h5>{capitalizeFirstLetter(i18n.t('admins'))}</h5>
123 <ul class="list-unstyled">
124 {this.state.siteRes.admins.map(admin => (
125 <li class="list-inline-item">
129 preferred_username: admin.preferred_username,
130 avatar: admin.avatar,
133 actor_id: admin.actor_id,
146 <h5>{i18n.t('banned_users')}</h5>
147 <ul class="list-unstyled">
148 {this.state.siteRes.banned.map(banned => (
149 <li class="list-inline-item">
153 preferred_username: banned.preferred_username,
154 avatar: banned.avatar,
157 actor_id: banned.actor_id,
170 <h5>{i18n.t('admin_settings')}</h5>
171 <form onSubmit={linkEvent(this, this.handleSiteConfigSubmit)}>
172 <div class="form-group row">
174 class="col-12 col-form-label"
175 htmlFor={this.siteConfigTextAreaId}
177 {i18n.t('site_config')}
181 id={this.siteConfigTextAreaId}
182 value={this.state.siteConfigForm.config_hjson}
183 onInput={linkEvent(this, this.handleSiteConfigHjsonChange)}
184 class="form-control text-monospace"
189 <div class="form-group row">
191 <button type="submit" class="btn btn-secondary mr-2">
192 {this.state.siteConfigLoading ? (
193 <svg class="icon icon-spinner spin">
194 <use xlinkHref="#icon-spinner"></use>
197 capitalizeFirstLetter(i18n.t('save'))
207 handleSiteConfigSubmit(i: AdminSettings, event: any) {
208 event.preventDefault();
209 i.state.siteConfigLoading = true;
210 WebSocketService.Instance.saveSiteConfig(i.state.siteConfigForm);
214 handleSiteConfigHjsonChange(i: AdminSettings, event: any) {
215 i.state.siteConfigForm.config_hjson = event.target.value;
219 parseMessage(msg: WebSocketJsonResponse) {
221 let res = wsJsonToRes(msg);
223 toast(i18n.t(msg.error), 'danger');
224 this.context.router.history.push('/');
225 this.state.loading = false;
226 this.setState(this.state);
228 } else if (msg.reconnect) {
229 } else if (res.op == UserOperation.GetSite) {
230 let data = res.data as GetSiteResponse;
232 // This means it hasn't been set up yet
234 this.context.router.history.push('/setup');
236 this.state.siteRes = data;
237 this.setState(this.state);
238 } else if (res.op == UserOperation.EditSite) {
239 let data = res.data as SiteResponse;
240 this.state.siteRes.site = data.site;
241 this.setState(this.state);
242 toast(i18n.t('site_saved'));
243 } else if (res.op == UserOperation.GetSiteConfig) {
244 let data = res.data as GetSiteConfigResponse;
245 this.state.siteConfigRes = data;
246 this.state.loading = false;
247 this.state.siteConfigForm.config_hjson = this.state.siteConfigRes.config_hjson;
248 this.setState(this.state);
249 var textarea: any = document.getElementById(this.siteConfigTextAreaId);
251 } else if (res.op == UserOperation.SaveSiteConfig) {
252 let data = res.data as GetSiteConfigResponse;
253 this.state.siteConfigRes = data;
254 this.state.siteConfigForm.config_hjson = this.state.siteConfigRes.config_hjson;
255 this.state.siteConfigLoading = false;
256 toast(i18n.t('site_saved'));
257 this.setState(this.state);