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