]> Untitled Git - lemmy-ui.git/blob - src/shared/components/home/instances.tsx
component classes v2
[lemmy-ui.git] / src / shared / components / home / instances.tsx
1 import { Component } from "inferno";
2 import {
3   GetFederatedInstancesResponse,
4   GetSiteResponse,
5   Instance,
6 } from "lemmy-js-client";
7 import { i18n } from "../../i18next";
8 import { InitialFetchRequest } from "../../interfaces";
9 import { FirstLoadService } from "../../services/FirstLoadService";
10 import { HttpService, RequestState } from "../../services/HttpService";
11 import { RouteDataResponse, relTags, setIsoData } from "../../utils";
12 import { HtmlTags } from "../common/html-tags";
13 import { Spinner } from "../common/icon";
14
15 type InstancesData = RouteDataResponse<{
16   federatedInstancesResponse: GetFederatedInstancesResponse;
17 }>;
18
19 interface InstancesState {
20   instancesRes: RequestState<GetFederatedInstancesResponse>;
21   siteRes: GetSiteResponse;
22   isIsomorphic: boolean;
23 }
24
25 export class Instances extends Component<any, InstancesState> {
26   private isoData = setIsoData<InstancesData>(this.context);
27   state: InstancesState = {
28     instancesRes: { state: "empty" },
29     siteRes: this.isoData.site_res,
30     isIsomorphic: false,
31   };
32
33   constructor(props: any, context: any) {
34     super(props, context);
35
36     // Only fetch the data if coming from another route
37     if (FirstLoadService.isFirstLoad) {
38       this.state = {
39         ...this.state,
40         instancesRes: this.isoData.routeData.federatedInstancesResponse,
41         isIsomorphic: true,
42       };
43     }
44   }
45
46   async componentDidMount() {
47     if (!this.state.isIsomorphic) {
48       await this.fetchInstances();
49     }
50   }
51
52   async fetchInstances() {
53     this.setState({
54       instancesRes: { state: "loading" },
55     });
56
57     this.setState({
58       instancesRes: await HttpService.client.getFederatedInstances({}),
59     });
60   }
61
62   static async fetchInitialData({
63     client,
64   }: InitialFetchRequest): Promise<InstancesData> {
65     return {
66       federatedInstancesResponse: await client.getFederatedInstances({}),
67     };
68   }
69
70   get documentTitle(): string {
71     return `${i18n.t("instances")} - ${this.state.siteRes.site_view.site.name}`;
72   }
73
74   renderInstances() {
75     switch (this.state.instancesRes.state) {
76       case "loading":
77         return (
78           <h5>
79             <Spinner large />
80           </h5>
81         );
82       case "success": {
83         const instances = this.state.instancesRes.data.federated_instances;
84         return instances ? (
85           <div className="row">
86             <div className="col-md-6">
87               <h5>{i18n.t("linked_instances")}</h5>
88               {this.itemList(instances.linked)}
89             </div>
90             {instances.allowed && instances.allowed.length > 0 && (
91               <div className="col-md-6">
92                 <h5>{i18n.t("allowed_instances")}</h5>
93                 {this.itemList(instances.allowed)}
94               </div>
95             )}
96             {instances.blocked && instances.blocked.length > 0 && (
97               <div className="col-md-6">
98                 <h5>{i18n.t("blocked_instances")}</h5>
99                 {this.itemList(instances.blocked)}
100               </div>
101             )}
102           </div>
103         ) : (
104           <></>
105         );
106       }
107     }
108   }
109
110   render() {
111     return (
112       <div className="home-instances container-lg">
113         <HtmlTags
114           title={this.documentTitle}
115           path={this.context.router.route.match.url}
116         />
117         {this.renderInstances()}
118       </div>
119     );
120   }
121
122   itemList(items: Instance[]) {
123     return items.length > 0 ? (
124       <div className="table-responsive">
125         <table id="instances_table" className="table table-sm table-hover">
126           <thead className="pointer">
127             <tr>
128               <th>{i18n.t("name")}</th>
129               <th>{i18n.t("software")}</th>
130               <th>{i18n.t("version")}</th>
131             </tr>
132           </thead>
133           <tbody>
134             {items.map(i => (
135               <tr key={i.domain}>
136                 <td>
137                   <a href={`https://${i.domain}`} rel={relTags}>
138                     {i.domain}
139                   </a>
140                 </td>
141                 <td>{i.software}</td>
142                 <td>{i.version}</td>
143               </tr>
144             ))}
145           </tbody>
146         </table>
147       </div>
148     ) : (
149       <div>{i18n.t("none_found")}</div>
150     );
151   }
152 }