]> Untitled Git - lemmy-ui.git/blob - src/shared/components/person/registration-applications.tsx
aaf3f8f2bd3a0e2fe9d4e02c18ab1cebe2b8bcd0
[lemmy-ui.git] / src / shared / components / person / registration-applications.tsx
1 import { Component, linkEvent } from "inferno";
2 import {
3   ApproveRegistrationApplication,
4   GetSiteResponse,
5   ListRegistrationApplicationsResponse,
6   RegistrationApplicationView,
7 } from "lemmy-js-client";
8 import { i18n } from "../../i18next";
9 import { InitialFetchRequest } from "../../interfaces";
10 import { UserService } from "../../services";
11 import { FirstLoadService } from "../../services/FirstLoadService";
12 import { HttpService, RequestState } from "../../services/HttpService";
13 import {
14   RouteDataResponse,
15   editRegistrationApplication,
16   fetchLimit,
17   myAuthRequired,
18   setIsoData,
19   setupTippy,
20 } from "../../utils";
21 import { HtmlTags } from "../common/html-tags";
22 import { Spinner } from "../common/icon";
23 import { Paginator } from "../common/paginator";
24 import { RegistrationApplication } from "../common/registration-application";
25
26 enum UnreadOrAll {
27   Unread,
28   All,
29 }
30
31 type RegistrationApplicationsData = RouteDataResponse<{
32   listRegistrationApplicationsResponse: ListRegistrationApplicationsResponse;
33 }>;
34
35 interface RegistrationApplicationsState {
36   appsRes: RequestState<ListRegistrationApplicationsResponse>;
37   siteRes: GetSiteResponse;
38   unreadOrAll: UnreadOrAll;
39   page: number;
40   isIsomorphic: boolean;
41 }
42
43 export class RegistrationApplications extends Component<
44   any,
45   RegistrationApplicationsState
46 > {
47   private isoData = setIsoData<RegistrationApplicationsData>(this.context);
48   state: RegistrationApplicationsState = {
49     appsRes: { state: "empty" },
50     siteRes: this.isoData.site_res,
51     unreadOrAll: UnreadOrAll.Unread,
52     page: 1,
53     isIsomorphic: false,
54   };
55
56   constructor(props: any, context: any) {
57     super(props, context);
58
59     this.handlePageChange = this.handlePageChange.bind(this);
60     this.handleApproveApplication = this.handleApproveApplication.bind(this);
61
62     // Only fetch the data if coming from another route
63     if (FirstLoadService.isFirstLoad) {
64       this.state = {
65         ...this.state,
66         appsRes: this.isoData.routeData.listRegistrationApplicationsResponse,
67         isIsomorphic: true,
68       };
69     }
70   }
71
72   async componentDidMount() {
73     if (!this.state.isIsomorphic) {
74       await this.refetch();
75     }
76     setupTippy();
77   }
78
79   get documentTitle(): string {
80     const mui = UserService.Instance.myUserInfo;
81     return mui
82       ? `@${mui.local_user_view.person.name} ${i18n.t(
83           "registration_applications"
84         )} - ${this.state.siteRes.site_view.site.name}`
85       : "";
86   }
87
88   renderApps() {
89     switch (this.state.appsRes.state) {
90       case "loading":
91         return (
92           <h5>
93             <Spinner large />
94           </h5>
95         );
96       case "success": {
97         const apps = this.state.appsRes.data.registration_applications;
98         return (
99           <div className="row">
100             <div className="col-12">
101               <HtmlTags
102                 title={this.documentTitle}
103                 path={this.context.router.route.match.url}
104               />
105               <h5 className="mb-2">{i18n.t("registration_applications")}</h5>
106               {this.selects()}
107               {this.applicationList(apps)}
108               <Paginator
109                 page={this.state.page}
110                 onChange={this.handlePageChange}
111               />
112             </div>
113           </div>
114         );
115       }
116     }
117   }
118
119   render() {
120     return <div className="container-lg">{this.renderApps()}</div>;
121   }
122
123   unreadOrAllRadios() {
124     return (
125       <div className="btn-group btn-group-toggle flex-wrap mb-2">
126         <label
127           className={`btn btn-outline-secondary pointer
128             ${this.state.unreadOrAll == UnreadOrAll.Unread && "active"}
129           `}
130         >
131           <input
132             type="radio"
133             className="btn-check"
134             value={UnreadOrAll.Unread}
135             checked={this.state.unreadOrAll == UnreadOrAll.Unread}
136             onChange={linkEvent(this, this.handleUnreadOrAllChange)}
137           />
138           {i18n.t("unread")}
139         </label>
140         <label
141           className={`btn btn-outline-secondary pointer
142             ${this.state.unreadOrAll == UnreadOrAll.All && "active"}
143           `}
144         >
145           <input
146             type="radio"
147             className="btn-check"
148             value={UnreadOrAll.All}
149             checked={this.state.unreadOrAll == UnreadOrAll.All}
150             onChange={linkEvent(this, this.handleUnreadOrAllChange)}
151           />
152           {i18n.t("all")}
153         </label>
154       </div>
155     );
156   }
157
158   selects() {
159     return (
160       <div className="mb-2">
161         <span className="me-3">{this.unreadOrAllRadios()}</span>
162       </div>
163     );
164   }
165
166   applicationList(apps: RegistrationApplicationView[]) {
167     return (
168       <div>
169         {apps.map(ra => (
170           <>
171             <hr />
172             <RegistrationApplication
173               key={ra.registration_application.id}
174               application={ra}
175               onApproveApplication={this.handleApproveApplication}
176             />
177           </>
178         ))}
179       </div>
180     );
181   }
182
183   handleUnreadOrAllChange(i: RegistrationApplications, event: any) {
184     i.setState({ unreadOrAll: Number(event.target.value), page: 1 });
185     i.refetch();
186   }
187
188   handlePageChange(page: number) {
189     this.setState({ page });
190     this.refetch();
191   }
192
193   static async fetchInitialData({
194     auth,
195     client,
196   }: InitialFetchRequest): Promise<RegistrationApplicationsData> {
197     return {
198       listRegistrationApplicationsResponse: auth
199         ? await client.listRegistrationApplications({
200             unread_only: true,
201             page: 1,
202             limit: fetchLimit,
203             auth: auth as string,
204           })
205         : { state: "empty" },
206     };
207   }
208
209   async refetch() {
210     const unread_only = this.state.unreadOrAll == UnreadOrAll.Unread;
211     this.setState({
212       appsRes: { state: "loading" },
213     });
214     this.setState({
215       appsRes: await HttpService.client.listRegistrationApplications({
216         unread_only: unread_only,
217         page: this.state.page,
218         limit: fetchLimit,
219         auth: myAuthRequired(),
220       }),
221     });
222   }
223
224   async handleApproveApplication(form: ApproveRegistrationApplication) {
225     const approveRes = await HttpService.client.approveRegistrationApplication(
226       form
227     );
228     this.setState(s => {
229       if (s.appsRes.state == "success" && approveRes.state == "success") {
230         s.appsRes.data.registration_applications = editRegistrationApplication(
231           approveRes.data.registration_application,
232           s.appsRes.data.registration_applications
233         );
234       }
235       return s;
236     });
237   }
238 }