Merge branch 'fix/isloading-photos' into 'main'
[ProtonMail-WebClient.git] / packages / components / containers / vpn / gateways / GatewayRow.tsx
blobd79d53f7621eca4eead2f4f6183a9d015a81d654
1 import { c, msgid } from 'ttag';
3 import Copy from '@proton/components/components/button/Copy';
4 import TableRow from '@proton/components/components/table/TableRow';
5 import useNotifications from '@proton/components/hooks/useNotifications';
6 import clsx from '@proton/utils/clsx';
8 import { type CountryOptions, getLocalizedCountryByAbbr } from '../../../helpers/countries';
9 import { CountryFlagAndName } from './CountryFlagAndName';
10 import type { Gateway } from './Gateway';
11 import type { GatewayLogical } from './GatewayLogical';
12 import GatewayManageButton from './GatewayManageButton';
13 import type { GatewayServer } from './GatewayServer';
14 import type { GatewayUser } from './GatewayUser';
15 import { getFormattedLoad, getMembers } from './helpers';
17 interface Props {
18     isAdmin: boolean;
19     showDeleted?: boolean;
20     showIPv4?: boolean;
21     showIPv6?: boolean;
22     showLoad?: boolean;
23     gateway: Gateway;
24     isDeleted: (logical: GatewayLogical) => boolean;
25     users: readonly GatewayUser[];
26     countryOptions: CountryOptions;
27     provisioningDuration: string;
28     deletingLogicals: readonly string[];
29     deletedLogicals: Record<string, boolean>;
30     renameGateway: (id: string, name: string) => () => any;
31     editGatewayServers: (gateway: Gateway, logical: GatewayLogical) => () => any;
32     editGatewayUsers: (gateway: Gateway, logical: GatewayLogical) => () => any;
33     deleteGateway: (gateway: Gateway) => () => any;
36 export const GatewayRow = ({
37     isAdmin,
38     showDeleted,
39     showIPv4,
40     showIPv6,
41     showLoad,
42     gateway,
43     isDeleted,
44     users,
45     countryOptions,
46     provisioningDuration,
47     renameGateway,
48     editGatewayServers,
49     editGatewayUsers,
50     deleteGateway,
51     deletingLogicals,
52     deletedLogicals,
53 }: Props) => {
54     const { createNotification } = useNotifications();
56     let provisioningCounter = 0;
57     const allLogicals = gateway.Logicals || [];
58     const deleted = allLogicals.every(isDeleted);
60     if (deleted && !showDeleted) {
61         return <></>;
62     }
64     const logicals = allLogicals.filter((logical) => {
65         if (isDeleted(logical)) {
66             return false;
67         }
69         if (!logical.Servers?.length) {
70             provisioningCounter++;
72             return false;
73         }
75         return true;
76     });
77     const provisionedLogicals = [...logicals.filter((l) => l.Visible), ...logicals.filter((l) => !l.Visible)];
78     const hasPendingServers = provisioningCounter > 0;
79     const main = provisionedLogicals[0] || allLogicals[0];
80     const [statusClasses, statusText] = provisionedLogicals.length
81         ? ['bg-success', /** translator: status of the gateway: people can connect to it */ c('Info').t`active`]
82         : [
83               'bg-weak color-weak',
84               /** translator: status of the gateway: people cannot connect to it */ c('Info').t`inactive`,
85           ];
87     const getIpsCell = (servers: GatewayServer[]) =>
88         servers[0]
89             ? [
90                   ...(showIPv4 ? [servers[0].ExitIPv4] : []),
91                   ...(showIPv6 ? [servers[0].ExitIPv6] : []),
92                   ...(showLoad ? [getFormattedLoad(servers)] : []),
93               ].join(', ')
94             : c('Action').t`Your server will be provisioned in the next days`;
96     return (
97         <TableRow
98             className={deleted ? 'opacity-50' : undefined}
99             cells={[
100                 gateway.Name,
101                 <span className={clsx(['py-1 px-2 rounded text-uppercase', statusClasses])}>{statusText}</span>,
102                 <div>
103                     {provisionedLogicals.length < 1 && !hasPendingServers && '0'}
104                     {provisionedLogicals.map((logical) => {
105                         const title = getLocalizedCountryByAbbr(logical.ExitCountry, countryOptions);
106                         return (
107                             <div key={'logical-' + logical.ID}>
108                                 <span className="text-nowrap bg-weak py-1 px-2 rounded">
109                                     <CountryFlagAndName
110                                         countryCode={logical.ExitCountry}
111                                         countryName={title}
112                                         className="mb-1"
113                                     />
114                                     <span className="color-weak">&nbsp; • &nbsp;</span>
115                                     {getIpsCell(logical.Servers)}
116                                     <Copy
117                                         value={logical.Servers[0].ExitIPv4}
118                                         shape="ghost"
119                                         onCopy={() => {
120                                             createNotification({
121                                                 text: c('Notification').t`IP Address copied to clipboard`,
122                                             });
123                                         }}
124                                     />
125                                 </span>
126                             </div>
127                         );
128                     })}
129                     {hasPendingServers && (
130                         <div className="color-weak">
131                             {c('Info').ngettext(
132                                 msgid`${provisioningCounter} server is still being set up. This usually takes around ${provisioningDuration}.`,
133                                 `${provisioningCounter} servers are still being set up. This usually takes around ${provisioningDuration}.`,
134                                 provisioningCounter
135                             )}
136                         </div>
137                     )}
138                 </div>,
139                 ...(isAdmin
140                     ? [
141                           getMembers(users, main),
142                           <GatewayManageButton
143                               gateway={gateway}
144                               logical={main}
145                               renameGateway={renameGateway}
146                               editGatewayServers={editGatewayServers}
147                               editGatewayUsers={editGatewayUsers}
148                               deleteGateway={deleteGateway}
149                               deletingLogicals={deletingLogicals}
150                               deletedLogicals={deletedLogicals}
151                               deleted={deleted}
152                           />,
153                       ]
154                     : []),
155             ]}
156         />
157     );
160 export default GatewayRow;