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