mirror of
https://github.com/apotdevin/thunderhub.git
synced 2025-02-23 14:40:27 +01:00
feat: test connection before hand
This commit is contained in:
parent
e91d5f156f
commit
37ec4a78d3
6 changed files with 275 additions and 166 deletions
|
@ -1,13 +1,16 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Input, SingleLine, Sub4Title } from '../../components/generic/Styled';
|
import { Input, SingleLine, Sub4Title } from '../../components/generic/Styled';
|
||||||
import { useAccount } from '../../context/AccountContext';
|
import { useAccount } from '../../context/AccountContext';
|
||||||
import { getConfigLnd, saveUserAuth } from '../../utils/auth';
|
import { getConfigLnd, saveUserAuth, getAuthString } from '../../utils/auth';
|
||||||
import CryptoJS from 'crypto-js';
|
import CryptoJS from 'crypto-js';
|
||||||
import { LoginButton, PasswordInput } from './Password';
|
import { LoginButton, PasswordInput } from './Password';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
import { useLazyQuery } from '@apollo/react-hooks';
|
||||||
|
import { GET_CAN_CONNECT } from '../../graphql/query';
|
||||||
|
import { getErrorContent } from '../../utils/error';
|
||||||
|
|
||||||
interface AuthProps {
|
interface AuthProps {
|
||||||
available?: number;
|
available: number;
|
||||||
callback?: () => void;
|
callback?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,9 +23,54 @@ export const BTCLoginForm = ({ available, callback }: AuthProps) => {
|
||||||
const [hasInfo, setHasInfo] = useState(false);
|
const [hasInfo, setHasInfo] = useState(false);
|
||||||
const [isPass, setPass] = useState('');
|
const [isPass, setPass] = useState('');
|
||||||
|
|
||||||
if (!available) return null;
|
const [tryToConnect, { data, loading }] = useLazyQuery(GET_CAN_CONNECT, {
|
||||||
|
onError: error => toast.error(getErrorContent(error)),
|
||||||
|
});
|
||||||
|
|
||||||
const canConnect = isJson !== '' && !!available;
|
useEffect(() => {
|
||||||
|
if (!loading && data && data.getNodeInfo && data.getNodeInfo.alias) {
|
||||||
|
const { cert, macaroon, readMacaroon, host } = getConfigLnd(isJson);
|
||||||
|
|
||||||
|
if (!host) {
|
||||||
|
toast.error('Invalid connection credentials');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const encryptedAdmin =
|
||||||
|
macaroon && isPass !== ''
|
||||||
|
? CryptoJS.AES.encrypt(macaroon, isPass).toString()
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
saveUserAuth({
|
||||||
|
available,
|
||||||
|
name: isName,
|
||||||
|
host,
|
||||||
|
admin: encryptedAdmin,
|
||||||
|
read: readMacaroon,
|
||||||
|
cert,
|
||||||
|
});
|
||||||
|
|
||||||
|
setAccount({
|
||||||
|
loggedIn: true,
|
||||||
|
host,
|
||||||
|
admin: macaroon,
|
||||||
|
read: readMacaroon,
|
||||||
|
cert,
|
||||||
|
});
|
||||||
|
|
||||||
|
toast.success('Connected!');
|
||||||
|
callback && callback();
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
data,
|
||||||
|
loading,
|
||||||
|
available,
|
||||||
|
callback,
|
||||||
|
isJson,
|
||||||
|
isName,
|
||||||
|
isPass,
|
||||||
|
setAccount,
|
||||||
|
]);
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
try {
|
try {
|
||||||
|
@ -34,66 +82,50 @@ export const BTCLoginForm = ({ available, callback }: AuthProps) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleConnect = () => {
|
const handleConnect = () => {
|
||||||
const { cert, macaroon, readMacaroon, host } = getConfigLnd(isJson);
|
const { cert, readMacaroon, host } = getConfigLnd(isJson);
|
||||||
|
|
||||||
const encryptedAdmin =
|
|
||||||
macaroon && isPass !== ''
|
|
||||||
? CryptoJS.AES.encrypt(macaroon, isPass).toString()
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
if (!host) {
|
if (!host) {
|
||||||
toast.error('Invalid connection credentials');
|
toast.error('Invalid connection credentials');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
saveUserAuth({
|
tryToConnect({
|
||||||
available,
|
variables: { auth: getAuthString(host, readMacaroon, cert) },
|
||||||
name: isName,
|
|
||||||
host,
|
|
||||||
admin: encryptedAdmin,
|
|
||||||
read: readMacaroon,
|
|
||||||
cert,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
setAccount({
|
|
||||||
loggedIn: true,
|
|
||||||
host,
|
|
||||||
admin: macaroon,
|
|
||||||
read: readMacaroon,
|
|
||||||
cert,
|
|
||||||
});
|
|
||||||
|
|
||||||
callback && callback();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderContent = () => (
|
const renderContent = () => {
|
||||||
<>
|
const canConnect = isJson !== '' && !!available;
|
||||||
<SingleLine>
|
return (
|
||||||
<Sub4Title>Name:</Sub4Title>
|
<>
|
||||||
<Input onChange={e => setName(e.target.value)} />
|
<SingleLine>
|
||||||
</SingleLine>
|
<Sub4Title>Name:</Sub4Title>
|
||||||
<SingleLine>
|
<Input onChange={e => setName(e.target.value)} />
|
||||||
<Sub4Title>BTCPay Connect Url:</Sub4Title>
|
</SingleLine>
|
||||||
<Input onChange={e => setJson(e.target.value)} />
|
<SingleLine>
|
||||||
</SingleLine>
|
<Sub4Title>BTCPay Connect Url:</Sub4Title>
|
||||||
{canConnect && (
|
<Input onChange={e => setJson(e.target.value)} />
|
||||||
<LoginButton
|
</SingleLine>
|
||||||
disabled={!canConnect}
|
{canConnect && (
|
||||||
enabled={canConnect}
|
<LoginButton
|
||||||
onClick={handleClick}
|
disabled={!canConnect}
|
||||||
color={'yellow'}
|
enabled={canConnect}
|
||||||
>
|
onClick={handleClick}
|
||||||
Connect
|
color={'yellow'}
|
||||||
</LoginButton>
|
>
|
||||||
)}
|
Connect
|
||||||
</>
|
</LoginButton>
|
||||||
);
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return hasInfo ? (
|
return hasInfo ? (
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
isPass={isPass}
|
isPass={isPass}
|
||||||
setPass={setPass}
|
setPass={setPass}
|
||||||
callback={handleConnect}
|
callback={handleConnect}
|
||||||
|
loading={loading}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
renderContent()
|
renderContent()
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Input, SingleLine, Sub4Title } from '../../components/generic/Styled';
|
import { Input, SingleLine, Sub4Title } from '../../components/generic/Styled';
|
||||||
import { useAccount } from '../../context/AccountContext';
|
import { useAccount } from '../../context/AccountContext';
|
||||||
import {
|
import {
|
||||||
getAuthLnd,
|
getAuthLnd,
|
||||||
getBase64CertfromDerFormat,
|
getBase64CertfromDerFormat,
|
||||||
saveUserAuth,
|
saveUserAuth,
|
||||||
|
getAuthString,
|
||||||
} from '../../utils/auth';
|
} from '../../utils/auth';
|
||||||
import { LoginButton, PasswordInput } from './Password';
|
import { LoginButton, PasswordInput } from './Password';
|
||||||
import CryptoJS from 'crypto-js';
|
import CryptoJS from 'crypto-js';
|
||||||
|
import { useLazyQuery } from '@apollo/react-hooks';
|
||||||
|
import { GET_CAN_CONNECT } from '../../graphql/query';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
import { getErrorContent } from '../../utils/error';
|
||||||
|
|
||||||
interface AuthProps {
|
interface AuthProps {
|
||||||
available?: number;
|
available: number;
|
||||||
callback?: () => void;
|
callback?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,71 +28,86 @@ export const ConnectLoginForm = ({ available, callback }: AuthProps) => {
|
||||||
const [hasInfo, setHasInfo] = useState(false);
|
const [hasInfo, setHasInfo] = useState(false);
|
||||||
const [isPass, setPass] = useState('');
|
const [isPass, setPass] = useState('');
|
||||||
|
|
||||||
if (!available) return null;
|
const [tryToConnect, { data, loading }] = useLazyQuery(GET_CAN_CONNECT, {
|
||||||
|
onError: error => toast.error(getErrorContent(error)),
|
||||||
|
});
|
||||||
|
|
||||||
const canConnect = isUrl !== '' && !!available;
|
useEffect(() => {
|
||||||
|
if (!loading && data && data.getNodeInfo && data.getNodeInfo.alias) {
|
||||||
|
const { cert, macaroon, socket } = getAuthLnd(isUrl);
|
||||||
|
|
||||||
|
const base64Cert = getBase64CertfromDerFormat(cert) || '';
|
||||||
|
|
||||||
|
const encryptedAdmin = CryptoJS.AES.encrypt(
|
||||||
|
macaroon,
|
||||||
|
isPass,
|
||||||
|
).toString();
|
||||||
|
|
||||||
|
saveUserAuth({
|
||||||
|
available,
|
||||||
|
name: isName,
|
||||||
|
host: socket,
|
||||||
|
admin: encryptedAdmin,
|
||||||
|
cert: base64Cert,
|
||||||
|
});
|
||||||
|
|
||||||
|
sessionStorage.setItem('session', macaroon);
|
||||||
|
|
||||||
|
setAccount({
|
||||||
|
loggedIn: true,
|
||||||
|
host: socket,
|
||||||
|
admin: encryptedAdmin,
|
||||||
|
read: macaroon,
|
||||||
|
cert: base64Cert,
|
||||||
|
});
|
||||||
|
|
||||||
|
toast.success('Connected!');
|
||||||
|
callback && callback();
|
||||||
|
}
|
||||||
|
}, [data, loading, available, callback, isName, isPass, isUrl, setAccount]);
|
||||||
|
|
||||||
const handleConnect = () => {
|
const handleConnect = () => {
|
||||||
const { cert, macaroon, socket } = getAuthLnd(isUrl);
|
const { cert, macaroon, socket } = getAuthLnd(isUrl);
|
||||||
|
|
||||||
const base64Cert = getBase64CertfromDerFormat(cert) || '';
|
const base64Cert = getBase64CertfromDerFormat(cert) || '';
|
||||||
|
|
||||||
const encryptedAdmin = CryptoJS.AES.encrypt(
|
tryToConnect({
|
||||||
macaroon,
|
variables: { auth: getAuthString(socket, macaroon, base64Cert) },
|
||||||
isPass,
|
|
||||||
).toString();
|
|
||||||
|
|
||||||
console.log(encryptedAdmin);
|
|
||||||
|
|
||||||
saveUserAuth({
|
|
||||||
available,
|
|
||||||
name: isName,
|
|
||||||
host: socket,
|
|
||||||
admin: encryptedAdmin,
|
|
||||||
cert: base64Cert,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
sessionStorage.setItem('session', macaroon);
|
|
||||||
|
|
||||||
setAccount({
|
|
||||||
loggedIn: true,
|
|
||||||
host: socket,
|
|
||||||
admin: encryptedAdmin,
|
|
||||||
read: macaroon,
|
|
||||||
cert: base64Cert,
|
|
||||||
});
|
|
||||||
|
|
||||||
callback && callback();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderContent = () => (
|
const renderContent = () => {
|
||||||
<>
|
const canConnect = isUrl !== '' && !!available;
|
||||||
<SingleLine>
|
return (
|
||||||
<Sub4Title>Name:</Sub4Title>
|
<>
|
||||||
<Input onChange={e => setName(e.target.value)} />
|
<SingleLine>
|
||||||
</SingleLine>
|
<Sub4Title>Name:</Sub4Title>
|
||||||
<SingleLine>
|
<Input onChange={e => setName(e.target.value)} />
|
||||||
<Sub4Title>LN Connect Url:</Sub4Title>
|
</SingleLine>
|
||||||
<Input onChange={e => setUrl(e.target.value)} />
|
<SingleLine>
|
||||||
</SingleLine>
|
<Sub4Title>LN Connect Url:</Sub4Title>
|
||||||
{canConnect && (
|
<Input onChange={e => setUrl(e.target.value)} />
|
||||||
<LoginButton
|
</SingleLine>
|
||||||
disabled={!canConnect}
|
{canConnect && (
|
||||||
enabled={canConnect}
|
<LoginButton
|
||||||
onClick={() => setHasInfo(true)}
|
disabled={!canConnect}
|
||||||
color={'yellow'}
|
enabled={canConnect}
|
||||||
>
|
onClick={() => setHasInfo(true)}
|
||||||
Connect
|
color={'yellow'}
|
||||||
</LoginButton>
|
>
|
||||||
)}
|
Connect
|
||||||
</>
|
</LoginButton>
|
||||||
);
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return hasInfo ? (
|
return hasInfo ? (
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
isPass={isPass}
|
isPass={isPass}
|
||||||
setPass={setPass}
|
setPass={setPass}
|
||||||
callback={handleConnect}
|
callback={handleConnect}
|
||||||
|
loading={loading}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
renderContent()
|
renderContent()
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Input, SingleLine, Sub4Title } from '../generic/Styled';
|
import { Input, SingleLine, Sub4Title } from '../generic/Styled';
|
||||||
import { useAccount } from '../../context/AccountContext';
|
import { useAccount } from '../../context/AccountContext';
|
||||||
import { saveUserAuth } from '../../utils/auth';
|
import { saveUserAuth, getAuthString } from '../../utils/auth';
|
||||||
import CryptoJS from 'crypto-js';
|
import CryptoJS from 'crypto-js';
|
||||||
import base64url from 'base64url';
|
import base64url from 'base64url';
|
||||||
import { PasswordInput, LoginButton } from './Password';
|
import { PasswordInput, LoginButton } from './Password';
|
||||||
|
import { useLazyQuery } from '@apollo/react-hooks';
|
||||||
|
import { GET_CAN_CONNECT } from '../../graphql/query';
|
||||||
|
import { getErrorContent } from '../../utils/error';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
interface AuthProps {
|
interface AuthProps {
|
||||||
available?: number;
|
available: number;
|
||||||
callback?: () => void;
|
callback?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,10 +27,9 @@ export const LoginForm = ({ available, callback }: AuthProps) => {
|
||||||
const [hasInfo, setHasInfo] = useState(false);
|
const [hasInfo, setHasInfo] = useState(false);
|
||||||
const [isPass, setPass] = useState('');
|
const [isPass, setPass] = useState('');
|
||||||
|
|
||||||
if (!available) return null;
|
const [tryToConnect, { data, loading }] = useLazyQuery(GET_CAN_CONNECT, {
|
||||||
|
onError: error => toast.error(getErrorContent(error)),
|
||||||
const canConnect =
|
});
|
||||||
isName !== '' && isHost !== '' && isRead !== '' && !!available;
|
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (isAdmin !== '') {
|
if (isAdmin !== '') {
|
||||||
|
@ -36,76 +39,110 @@ export const LoginForm = ({ available, callback }: AuthProps) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!loading && data && data.getNodeInfo && data.getNodeInfo.alias) {
|
||||||
|
const admin = base64url.fromBase64(isAdmin);
|
||||||
|
const read = base64url.fromBase64(isRead);
|
||||||
|
const cert = base64url.fromBase64(isCert);
|
||||||
|
|
||||||
|
const encryptedAdmin =
|
||||||
|
admin && isPass !== ''
|
||||||
|
? CryptoJS.AES.encrypt(admin, isPass).toString()
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
saveUserAuth({
|
||||||
|
available,
|
||||||
|
name: isName,
|
||||||
|
host: isHost,
|
||||||
|
admin: encryptedAdmin,
|
||||||
|
read,
|
||||||
|
cert,
|
||||||
|
});
|
||||||
|
|
||||||
|
setAccount({
|
||||||
|
loggedIn: true,
|
||||||
|
host: isHost,
|
||||||
|
admin: encryptedAdmin,
|
||||||
|
read,
|
||||||
|
cert,
|
||||||
|
});
|
||||||
|
|
||||||
|
toast.success('Connected!');
|
||||||
|
callback && callback();
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
data,
|
||||||
|
loading,
|
||||||
|
available,
|
||||||
|
callback,
|
||||||
|
isAdmin,
|
||||||
|
isCert,
|
||||||
|
isHost,
|
||||||
|
isName,
|
||||||
|
isPass,
|
||||||
|
isRead,
|
||||||
|
setAccount,
|
||||||
|
]);
|
||||||
|
|
||||||
const handleConnect = () => {
|
const handleConnect = () => {
|
||||||
const admin = base64url.fromBase64(isAdmin);
|
const admin = base64url.fromBase64(isAdmin);
|
||||||
const read = base64url.fromBase64(isRead);
|
const read = base64url.fromBase64(isRead);
|
||||||
const cert = base64url.fromBase64(isCert);
|
const cert = base64url.fromBase64(isCert);
|
||||||
|
|
||||||
const encryptedAdmin =
|
const correctMacaroon = read ? read : admin;
|
||||||
admin && isPass !== ''
|
|
||||||
? CryptoJS.AES.encrypt(admin, isPass).toString()
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
saveUserAuth({
|
tryToConnect({
|
||||||
available,
|
variables: {
|
||||||
name: isName,
|
auth: getAuthString(isHost, correctMacaroon, cert),
|
||||||
host: isHost,
|
},
|
||||||
admin: encryptedAdmin,
|
|
||||||
read,
|
|
||||||
cert,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
setAccount({
|
|
||||||
loggedIn: true,
|
|
||||||
host: isHost,
|
|
||||||
admin: encryptedAdmin,
|
|
||||||
read,
|
|
||||||
cert,
|
|
||||||
});
|
|
||||||
|
|
||||||
callback && callback();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderContent = () => (
|
const renderContent = () => {
|
||||||
<>
|
const canConnect =
|
||||||
<SingleLine>
|
isName !== '' && isHost !== '' && isRead !== '' && !!available;
|
||||||
<Sub4Title>Name:</Sub4Title>
|
return (
|
||||||
<Input onChange={e => setName(e.target.value)} />
|
<>
|
||||||
</SingleLine>
|
<SingleLine>
|
||||||
<SingleLine>
|
<Sub4Title>Name:</Sub4Title>
|
||||||
<Sub4Title>Host:</Sub4Title>
|
<Input onChange={e => setName(e.target.value)} />
|
||||||
<Input onChange={e => setHost(e.target.value)} />
|
</SingleLine>
|
||||||
</SingleLine>
|
<SingleLine>
|
||||||
<SingleLine>
|
<Sub4Title>Host:</Sub4Title>
|
||||||
<Sub4Title>Admin:</Sub4Title>
|
<Input onChange={e => setHost(e.target.value)} />
|
||||||
<Input onChange={e => setAdmin(e.target.value)} />
|
</SingleLine>
|
||||||
</SingleLine>
|
<SingleLine>
|
||||||
<SingleLine>
|
<Sub4Title>Admin:</Sub4Title>
|
||||||
<Sub4Title>Readonly:</Sub4Title>
|
<Input onChange={e => setAdmin(e.target.value)} />
|
||||||
<Input onChange={e => setRead(e.target.value)} />
|
</SingleLine>
|
||||||
</SingleLine>
|
<SingleLine>
|
||||||
<SingleLine>
|
<Sub4Title>Readonly:</Sub4Title>
|
||||||
<Sub4Title>Certificate:</Sub4Title>
|
<Input onChange={e => setRead(e.target.value)} />
|
||||||
<Input onChange={e => setCert(e.target.value)} />
|
</SingleLine>
|
||||||
</SingleLine>
|
<SingleLine>
|
||||||
{canConnect && (
|
<Sub4Title>Certificate:</Sub4Title>
|
||||||
<LoginButton
|
<Input onChange={e => setCert(e.target.value)} />
|
||||||
disabled={!canConnect}
|
</SingleLine>
|
||||||
enabled={canConnect}
|
{canConnect && (
|
||||||
onClick={handleClick}
|
<LoginButton
|
||||||
color={'yellow'}
|
disabled={!canConnect}
|
||||||
>
|
enabled={canConnect}
|
||||||
Connect
|
onClick={handleClick}
|
||||||
</LoginButton>
|
color={'yellow'}
|
||||||
)}
|
>
|
||||||
</>
|
Connect
|
||||||
);
|
</LoginButton>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return hasInfo ? (
|
return hasInfo ? (
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
isPass={isPass}
|
isPass={isPass}
|
||||||
setPass={setPass}
|
setPass={setPass}
|
||||||
callback={handleConnect}
|
callback={handleConnect}
|
||||||
|
loading={loading}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
renderContent()
|
renderContent()
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
import zxcvbn from 'zxcvbn';
|
import zxcvbn from 'zxcvbn';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { progressBackground, textColor } from '../../styles/Themes';
|
import { progressBackground, textColor } from '../../styles/Themes';
|
||||||
|
import { Loader } from '../generic/Icons';
|
||||||
|
|
||||||
const Progress = styled.div`
|
const Progress = styled.div`
|
||||||
width: 80%;
|
width: 80%;
|
||||||
|
@ -65,9 +66,15 @@ interface PasswordProps {
|
||||||
isPass: string;
|
isPass: string;
|
||||||
setPass: (pass: string) => void;
|
setPass: (pass: string) => void;
|
||||||
callback: () => void;
|
callback: () => void;
|
||||||
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PasswordInput = ({ isPass, setPass, callback }: PasswordProps) => {
|
export const PasswordInput = ({
|
||||||
|
isPass,
|
||||||
|
setPass,
|
||||||
|
callback,
|
||||||
|
loading = false,
|
||||||
|
}: PasswordProps) => {
|
||||||
const strength = (100 * Math.min(zxcvbn(isPass).guesses_log10, 40)) / 40;
|
const strength = (100 * Math.min(zxcvbn(isPass).guesses_log10, 40)) / 40;
|
||||||
const needed = 1;
|
const needed = 1;
|
||||||
return (
|
return (
|
||||||
|
@ -86,7 +93,7 @@ export const PasswordInput = ({ isPass, setPass, callback }: PasswordProps) => {
|
||||||
/>
|
/>
|
||||||
</Progress>
|
</Progress>
|
||||||
</SingleLine>
|
</SingleLine>
|
||||||
{strength >= needed && (
|
{strength >= needed && !loading && (
|
||||||
<LoginButton
|
<LoginButton
|
||||||
disabled={strength < needed}
|
disabled={strength < needed}
|
||||||
enabled={strength >= needed}
|
enabled={strength >= needed}
|
||||||
|
@ -96,6 +103,11 @@ export const PasswordInput = ({ isPass, setPass, callback }: PasswordProps) => {
|
||||||
Connect
|
Connect
|
||||||
</LoginButton>
|
</LoginButton>
|
||||||
)}
|
)}
|
||||||
|
{loading && (
|
||||||
|
<LoginButton disabled={true} color={'grey'}>
|
||||||
|
<Loader />
|
||||||
|
</LoginButton>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -99,7 +99,7 @@ export const ForwardChannelsReport = ({ isTime, isType, color }: Props) => {
|
||||||
|
|
||||||
const renderRoute = (parsed: {}[]) => {
|
const renderRoute = (parsed: {}[]) => {
|
||||||
const routes = parsed.map((channel: any, index: number) => (
|
const routes = parsed.map((channel: any, index: number) => (
|
||||||
<ChannelRow>
|
<ChannelRow key={index}>
|
||||||
<TableLine>{channel.aliasIn}</TableLine>
|
<TableLine>{channel.aliasIn}</TableLine>
|
||||||
<TableLine>{channel.aliasOut}</TableLine>
|
<TableLine>{channel.aliasOut}</TableLine>
|
||||||
<LastTableLine>
|
<LastTableLine>
|
||||||
|
|
|
@ -15,6 +15,14 @@ export const GET_NETWORK_INFO = gql`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const GET_CAN_CONNECT = gql`
|
||||||
|
query GetNodeInfo($auth: String!) {
|
||||||
|
getNodeInfo(auth: $auth) {
|
||||||
|
alias
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const GET_NODE_INFO = gql`
|
export const GET_NODE_INFO = gql`
|
||||||
query GetNodeInfo($auth: String!) {
|
query GetNodeInfo($auth: String!) {
|
||||||
getNodeInfo(auth: $auth) {
|
getNodeInfo(auth: $auth) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue