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