]> Untitled Git - lemmy-ui.git/blob - src/shared/components/home/instances.tsx
Merge branch 'main' into remove-i18-circle
[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           <div className="row">
89             <div className="col-md-6">
90               <h5>{I18NextService.i18n.t("linked_instances")}</h5>
91               {this.itemList(instances.linked)}
92             </div>
93             {instances.allowed && instances.allowed.length > 0 && (
94               <div className="col-md-6">
95                 <h5>{I18NextService.i18n.t("allowed_instances")}</h5>
96                 {this.itemList(instances.allowed)}
97               </div>
98             )}
99             {instances.blocked && instances.blocked.length > 0 && (
100               <div className="col-md-6">
101                 <h5>{I18NextService.i18n.t("blocked_instances")}</h5>
102                 {this.itemList(instances.blocked)}
103               </div>
104             )}
105           </div>
106         ) : (
107           <></>
108         );
109       }
110     }
111   }
112
113   render() {
114     return (
115       <div className="home-instances container-lg">
116         <HtmlTags
117           title={this.documentTitle}
118           path={this.context.router.route.match.url}
119         />
120         {this.renderInstances()}
121       </div>
122     );
123   }
124
125   itemList(items: Instance[]) {
126     return items.length > 0 ? (
127       <div className="table-responsive">
128         <table id="instances_table" className="table table-sm table-hover">
129           <thead className="pointer">
130             <tr>
131               <th>{I18NextService.i18n.t("name")}</th>
132               <th>{I18NextService.i18n.t("software")}</th>
133               <th>{I18NextService.i18n.t("version")}</th>
134             </tr>
135           </thead>
136           <tbody>
137             {items.map(i => (
138               <tr key={i.domain}>
139                 <td>
140                   <a href={`https://${i.domain}`} rel={relTags}>
141                     {i.domain}
142                   </a>
143                 </td>
144                 <td>{i.software}</td>
145                 <td>{i.version}</td>
146               </tr>
147             ))}
148           </tbody>
149         </table>
150       </div>
151     ) : (
152       <div>{I18NextService.i18n.t("none_found")}</div>
153     );
154   }
155 }