mirror of
https://github.com/apotdevin/thunderhub.git
synced 2025-02-22 14:22:33 +01:00
feat: ✨ style changes (#48)
* feat: ✨ style changes * chore: 🔧 number format * fix: 🐛 partner capacity * fix: 🐛 small change * chore: 🔧 add channel status * refactor: ♻️ bar width
This commit is contained in:
parent
414c20f053
commit
c2d2dc8e36
47 changed files with 508 additions and 371 deletions
|
@ -39,8 +39,10 @@ module.exports = {
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
'import/no-unresolved': 'off',
|
'import/no-unresolved': 'off',
|
||||||
'import/order': 2,
|
'import/order': 2,
|
||||||
|
'no-unused-vars': 2,
|
||||||
camelcase: 'off',
|
camelcase: 'off',
|
||||||
'@typescript-eslint/camelcase': 'off',
|
'@typescript-eslint/camelcase': 'off',
|
||||||
'react/prop-types': 'off',
|
'react/prop-types': 'off',
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
import { GraphQLList, GraphQLBoolean } from 'graphql';
|
import { GraphQLList, GraphQLBoolean } from 'graphql';
|
||||||
import { getChannels as getLnChannels, getNode } from 'ln-service';
|
import {
|
||||||
|
getChannels as getLnChannels,
|
||||||
|
getNode,
|
||||||
|
getChannel,
|
||||||
|
getWalletInfo,
|
||||||
|
} from 'ln-service';
|
||||||
import { ContextType } from 'api/types/apiTypes';
|
import { ContextType } from 'api/types/apiTypes';
|
||||||
|
import { toWithError } from 'api/helpers/async';
|
||||||
import { logger } from '../../../helpers/logger';
|
import { logger } from '../../../helpers/logger';
|
||||||
import { requestLimiter } from '../../../helpers/rateLimiter';
|
import { requestLimiter } from '../../../helpers/rateLimiter';
|
||||||
import {
|
import {
|
||||||
|
@ -11,36 +17,6 @@ import {
|
||||||
import { defaultParams } from '../../../helpers/defaultProps';
|
import { defaultParams } from '../../../helpers/defaultProps';
|
||||||
import { ChannelType } from '../../types/QueryType';
|
import { ChannelType } from '../../types/QueryType';
|
||||||
|
|
||||||
interface ChannelListProps {
|
|
||||||
channels: ChannelProps[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ChannelProps {
|
|
||||||
capacity: number;
|
|
||||||
commit_transaction_fee: number;
|
|
||||||
commit_transaction_weight: number;
|
|
||||||
id: string;
|
|
||||||
is_active: boolean;
|
|
||||||
is_closing: boolean;
|
|
||||||
is_opening: boolean;
|
|
||||||
is_partner_initiated: boolean;
|
|
||||||
is_private: boolean;
|
|
||||||
is_static_remote_key: boolean;
|
|
||||||
local_balance: number;
|
|
||||||
local_reserve: number;
|
|
||||||
partner_public_key: string;
|
|
||||||
pending_payments: [];
|
|
||||||
received: number;
|
|
||||||
remote_balance: number;
|
|
||||||
remote_reserve: number;
|
|
||||||
sent: number;
|
|
||||||
time_offline: number;
|
|
||||||
time_online: number;
|
|
||||||
transaction_id: string;
|
|
||||||
transaction_vout: number;
|
|
||||||
unsettled_balance: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getChannels = {
|
export const getChannels = {
|
||||||
type: new GraphQLList(ChannelType),
|
type: new GraphQLList(ChannelType),
|
||||||
args: {
|
args: {
|
||||||
|
@ -53,37 +29,83 @@ export const getChannels = {
|
||||||
const auth = getCorrectAuth(params.auth, context);
|
const auth = getCorrectAuth(params.auth, context);
|
||||||
const lnd = getAuthLnd(auth);
|
const lnd = getAuthLnd(auth);
|
||||||
|
|
||||||
try {
|
const [walletInfo, walletError] = await toWithError(getWalletInfo({ lnd }));
|
||||||
const channelList: ChannelListProps = await getLnChannels({
|
const publicKey = walletInfo?.public_key;
|
||||||
|
|
||||||
|
walletError &&
|
||||||
|
logger.debug('Error getting wallet info in getChannels: %o', walletError);
|
||||||
|
|
||||||
|
const [channelList, channelListError] = await toWithError(
|
||||||
|
getLnChannels({
|
||||||
lnd,
|
lnd,
|
||||||
is_active: params.active,
|
is_active: params.active,
|
||||||
});
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (channelListError) {
|
||||||
|
logger.error('Error getting channels: %o', channelListError);
|
||||||
|
throw new Error(getErrorMsg(channelListError));
|
||||||
|
}
|
||||||
|
|
||||||
const getChannelList = () =>
|
const getChannelList = () =>
|
||||||
Promise.all(
|
Promise.all(
|
||||||
channelList.channels.map(async channel => {
|
channelList.channels.map(async channel => {
|
||||||
const nodeInfo = await getNode({
|
const [nodeInfo, nodeError] = await toWithError(
|
||||||
|
getNode({
|
||||||
lnd,
|
lnd,
|
||||||
is_omitting_channels: true,
|
is_omitting_channels: true,
|
||||||
public_key: channel.partner_public_key,
|
public_key: channel.partner_public_key,
|
||||||
});
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const [channelInfo, channelError] = await toWithError(
|
||||||
|
getChannel({
|
||||||
|
lnd,
|
||||||
|
id: channel.id,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
nodeError &&
|
||||||
|
logger.debug(
|
||||||
|
`Error getting node with public key ${channel.partner_public_key}: %o`,
|
||||||
|
nodeError
|
||||||
|
);
|
||||||
|
|
||||||
|
channelError &&
|
||||||
|
logger.debug(
|
||||||
|
`Error getting channel with id ${channel.id}: %o`,
|
||||||
|
channelError
|
||||||
|
);
|
||||||
|
|
||||||
|
let partnerFees = {};
|
||||||
|
if (!channelError && publicKey) {
|
||||||
|
const partnerPolicy = channelInfo.policies.filter(
|
||||||
|
policy => policy.public_key !== publicKey
|
||||||
|
);
|
||||||
|
if (partnerPolicy && partnerPolicy.length >= 1) {
|
||||||
|
partnerFees = {
|
||||||
|
base_fee: partnerPolicy[0].base_fee_mtokens || 0,
|
||||||
|
fee_rate: partnerPolicy[0].fee_rate || 0,
|
||||||
|
cltv_delta: partnerPolicy[0].cltv_delta || 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const partner_node_info = {
|
||||||
|
...(!nodeError && nodeInfo),
|
||||||
|
...partnerFees,
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...channel,
|
...channel,
|
||||||
time_offline: Math.round((channel.time_offline || 0) / 1000),
|
time_offline: Math.round((channel.time_offline || 0) / 1000),
|
||||||
time_online: Math.round((channel.time_online || 0) / 1000),
|
time_online: Math.round((channel.time_online || 0) / 1000),
|
||||||
partner_node_info: {
|
partner_node_info,
|
||||||
...nodeInfo,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const channels = await getChannelList();
|
const channels = await getChannelList();
|
||||||
return channels;
|
return channels;
|
||||||
} catch (error) {
|
|
||||||
logger.error('Error getting channels: %o', error);
|
|
||||||
throw new Error(getErrorMsg(error));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -84,6 +84,9 @@ export const PartnerNodeType = new GraphQLObjectType({
|
||||||
channel_count: { type: GraphQLInt },
|
channel_count: { type: GraphQLInt },
|
||||||
color: { type: GraphQLString },
|
color: { type: GraphQLString },
|
||||||
updated_at: { type: GraphQLString },
|
updated_at: { type: GraphQLString },
|
||||||
|
base_fee: { type: GraphQLInt },
|
||||||
|
fee_rate: { type: GraphQLInt },
|
||||||
|
cltv_delta: { type: GraphQLInt },
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
"start:two": "cross-env NODE_OPTIONS='--insecure-http-parser' next start -p 3001",
|
"start:two": "cross-env NODE_OPTIONS='--insecure-http-parser' next start -p 3001",
|
||||||
"start:compatible": "next start",
|
"start:compatible": "next start",
|
||||||
"start:compatible:two": "next start -p 3001",
|
"start:compatible:two": "next start -p 3001",
|
||||||
"lint": "eslint */**/*.{js,ts,tsx} --quiet --fix",
|
"lint": "eslint */**/*.{js,ts,tsx} --fix",
|
||||||
"prettier": "prettier --write **/*.{ts,tsx,js,css,html}",
|
"prettier": "prettier --write **/*.{ts,tsx,js,css,html}",
|
||||||
"release": "standard-version",
|
"release": "standard-version",
|
||||||
"release:push": "standard-version && git push --follow-tags origin master",
|
"release:push": "standard-version && git push --follow-tags origin master",
|
||||||
|
|
|
@ -161,7 +161,7 @@ const BalanceView = () => {
|
||||||
<SingleLine>
|
<SingleLine>
|
||||||
<SubTitle>Channel Balancing</SubTitle>
|
<SubTitle>Channel Balancing</SubTitle>
|
||||||
</SingleLine>
|
</SingleLine>
|
||||||
<Card>
|
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
|
||||||
{renderOutgoing()}
|
{renderOutgoing()}
|
||||||
{renderIncoming()}
|
{renderIncoming()}
|
||||||
<ResponsiveLine>
|
<ResponsiveLine>
|
||||||
|
|
|
@ -1,18 +1,31 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useAccountState } from 'src/context/AccountContext';
|
import { useAccountState } from 'src/context/AccountContext';
|
||||||
import { useGetChannelAmountInfoQuery } from 'src/graphql/queries/__generated__/getNodeInfo.generated';
|
import { useGetChannelAmountInfoQuery } from 'src/graphql/queries/__generated__/getNodeInfo.generated';
|
||||||
|
import styled from 'styled-components';
|
||||||
import { Channels } from '../src/views/channels/channels/Channels';
|
import { Channels } from '../src/views/channels/channels/Channels';
|
||||||
import { PendingChannels } from '../src/views/channels/pendingChannels/PendingChannels';
|
import { PendingChannels } from '../src/views/channels/pendingChannels/PendingChannels';
|
||||||
import { ClosedChannels } from '../src/views/channels/closedChannels/ClosedChannels';
|
import { ClosedChannels } from '../src/views/channels/closedChannels/ClosedChannels';
|
||||||
import {
|
import {
|
||||||
CardWithTitle,
|
CardWithTitle,
|
||||||
SubTitle,
|
SubTitle,
|
||||||
CardTitle,
|
SmallButton,
|
||||||
SingleLine,
|
|
||||||
ColorButton,
|
|
||||||
} from '../src/components/generic/Styled';
|
} from '../src/components/generic/Styled';
|
||||||
import { useConfigState } from '../src/context/ConfigContext';
|
import { mediaWidths } from '../src/styles/Themes';
|
||||||
import { textColorMap } from '../src/styles/Themes';
|
|
||||||
|
const ChannelsCardTitle = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
@media (${mediaWidths.mobile}) {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ButtonRow = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
`;
|
||||||
|
|
||||||
const ChannelView = () => {
|
const ChannelView = () => {
|
||||||
const [view, setView] = useState<number>(1);
|
const [view, setView] = useState<number>(1);
|
||||||
|
@ -22,7 +35,6 @@ const ChannelView = () => {
|
||||||
closed: 0,
|
closed: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { theme } = useConfigState();
|
|
||||||
const { auth } = useAccountState();
|
const { auth } = useAccountState();
|
||||||
|
|
||||||
const { data } = useGetChannelAmountInfoQuery({
|
const { data } = useGetChannelAmountInfoQuery({
|
||||||
|
@ -31,7 +43,7 @@ const ChannelView = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data?.getNodeInfo) {
|
if (data && data.getNodeInfo) {
|
||||||
const {
|
const {
|
||||||
active_channels_count,
|
active_channels_count,
|
||||||
closed_channels_count,
|
closed_channels_count,
|
||||||
|
@ -70,20 +82,20 @@ const ChannelView = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CardWithTitle>
|
<CardWithTitle>
|
||||||
<CardTitle>
|
<ChannelsCardTitle>
|
||||||
<SubTitle>{getTitle()}</SubTitle>
|
<SubTitle>{getTitle()}</SubTitle>
|
||||||
<SingleLine>
|
<ButtonRow>
|
||||||
<ColorButton color={textColorMap[theme]} onClick={() => setView(1)}>
|
<SmallButton onClick={() => setView(1)}>
|
||||||
{`Open (${amounts.active})`}
|
{`Open (${amounts.active})`}
|
||||||
</ColorButton>
|
</SmallButton>
|
||||||
<ColorButton color={textColorMap[theme]} onClick={() => setView(2)}>
|
<SmallButton onClick={() => setView(2)}>
|
||||||
{`Pending (${amounts.pending})`}
|
{`Pending (${amounts.pending})`}
|
||||||
</ColorButton>
|
</SmallButton>
|
||||||
<ColorButton color={textColorMap[theme]} onClick={() => setView(3)}>
|
<SmallButton onClick={() => setView(3)}>
|
||||||
{`Closed (${amounts.closed})`}
|
{`Closed (${amounts.closed})`}
|
||||||
</ColorButton>
|
</SmallButton>
|
||||||
</SingleLine>
|
</ButtonRow>
|
||||||
</CardTitle>
|
</ChannelsCardTitle>
|
||||||
{getView()}
|
{getView()}
|
||||||
</CardWithTitle>
|
</CardWithTitle>
|
||||||
);
|
);
|
||||||
|
|
|
@ -110,7 +110,7 @@ const FeesView = () => {
|
||||||
</AdminSwitch>
|
</AdminSwitch>
|
||||||
<CardWithTitle>
|
<CardWithTitle>
|
||||||
<SubTitle>Channel Fees</SubTitle>
|
<SubTitle>Channel Fees</SubTitle>
|
||||||
<Card>
|
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
|
||||||
{data.getChannelFees.map((channel: any, index: number) => (
|
{data.getChannelFees.map((channel: any, index: number) => (
|
||||||
<FeeCard
|
<FeeCard
|
||||||
channelInfo={channel}
|
channelInfo={channel}
|
||||||
|
|
|
@ -7,14 +7,12 @@ import {
|
||||||
Card,
|
Card,
|
||||||
CardWithTitle,
|
CardWithTitle,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
ColorButton,
|
SmallButton,
|
||||||
SingleLine,
|
SingleLine,
|
||||||
} from '../src/components/generic/Styled';
|
} from '../src/components/generic/Styled';
|
||||||
import { getErrorContent } from '../src/utils/error';
|
import { getErrorContent } from '../src/utils/error';
|
||||||
import { LoadingCard } from '../src/components/loading/LoadingCard';
|
import { LoadingCard } from '../src/components/loading/LoadingCard';
|
||||||
import { ForwardCard } from '../src/views/forwards/ForwardsCard';
|
import { ForwardCard } from '../src/views/forwards/ForwardsCard';
|
||||||
import { textColorMap } from '../src/styles/Themes';
|
|
||||||
import { useConfigState } from '../src/context/ConfigContext';
|
|
||||||
import { ForwardBox } from '../src/views/home/reports/forwardReport';
|
import { ForwardBox } from '../src/views/home/reports/forwardReport';
|
||||||
|
|
||||||
const timeMap: { [key: string]: string } = {
|
const timeMap: { [key: string]: string } = {
|
||||||
|
@ -28,7 +26,6 @@ const ForwardsView = () => {
|
||||||
const [time, setTime] = useState('week');
|
const [time, setTime] = useState('week');
|
||||||
const [indexOpen, setIndexOpen] = useState(0);
|
const [indexOpen, setIndexOpen] = useState(0);
|
||||||
|
|
||||||
const { theme } = useConfigState();
|
|
||||||
const { auth } = useAccountState();
|
const { auth } = useAccountState();
|
||||||
|
|
||||||
const { loading, data } = useGetForwardsQuery({
|
const { loading, data } = useGetForwardsQuery({
|
||||||
|
@ -42,17 +39,13 @@ const ForwardsView = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderButton = (selectedTime: string, title: string) => (
|
const renderButton = (selectedTime: string, title: string) => (
|
||||||
<ColorButton
|
<SmallButton onClick={() => setTime(selectedTime)}>{title}</SmallButton>
|
||||||
color={textColorMap[theme]}
|
|
||||||
onClick={() => setTime(selectedTime)}
|
|
||||||
selected={time === selectedTime}
|
|
||||||
>
|
|
||||||
{title}
|
|
||||||
</ColorButton>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderNoForwards = () => (
|
const renderNoForwards = () => (
|
||||||
|
<Card>
|
||||||
<p>{`Your node has not forwarded any payments ${timeMap[time]}.`}</p>
|
<p>{`Your node has not forwarded any payments ${timeMap[time]}.`}</p>
|
||||||
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -68,8 +61,8 @@ const ForwardsView = () => {
|
||||||
{renderButton('threeMonths', '3M')}
|
{renderButton('threeMonths', '3M')}
|
||||||
</SingleLine>
|
</SingleLine>
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<Card>
|
|
||||||
{data.getForwards.forwards.length <= 0 && renderNoForwards()}
|
{data.getForwards.forwards.length <= 0 && renderNoForwards()}
|
||||||
|
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
|
||||||
{data.getForwards.forwards.map((forward: any, index: number) => (
|
{data.getForwards.forwards.map((forward: any, index: number) => (
|
||||||
<ForwardCard
|
<ForwardCard
|
||||||
forward={forward}
|
forward={forward}
|
||||||
|
|
|
@ -28,7 +28,7 @@ const PeersView = () => {
|
||||||
<AddPeer />
|
<AddPeer />
|
||||||
<CardWithTitle>
|
<CardWithTitle>
|
||||||
<SubTitle>Peers</SubTitle>
|
<SubTitle>Peers</SubTitle>
|
||||||
<Card>
|
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
|
||||||
{data.getPeers.map((peer: any, index: number) => (
|
{data.getPeers.map((peer: any, index: number) => (
|
||||||
<PeersCard
|
<PeersCard
|
||||||
peer={peer}
|
peer={peer}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { SingleLine, SimpleButton } from '../src/components/generic/Styled';
|
import { SingleLine } from '../src/components/generic/Styled';
|
||||||
import { InterfaceSettings } from '../src/views/settings/Interface';
|
import { InterfaceSettings } from '../src/views/settings/Interface';
|
||||||
import { textColor } from '../src/styles/Themes';
|
|
||||||
import { AccountSettings } from '../src/views/settings/Account';
|
import { AccountSettings } from '../src/views/settings/Account';
|
||||||
import { DangerView } from '../src/views/settings/Danger';
|
import { DangerView } from '../src/views/settings/Danger';
|
||||||
import { CurrentSettings } from '../src/views/settings/Current';
|
import { CurrentSettings } from '../src/views/settings/Current';
|
||||||
|
@ -19,14 +18,6 @@ export const SettingsLine = styled(SingleLine)`
|
||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const SettingsButton = styled(SimpleButton)`
|
|
||||||
padding: 8px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border: 1px solid ${textColor};
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SettingsView = () => {
|
const SettingsView = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -99,7 +99,7 @@ const TradingView = () => {
|
||||||
<Card bottom={'16px'}>
|
<Card bottom={'16px'}>
|
||||||
<OfferFilters offerFilters={queryObject} />
|
<OfferFilters offerFilters={queryObject} />
|
||||||
</Card>
|
</Card>
|
||||||
<Card bottom={'8px'}>
|
<Card bottom={'8px'} mobileCardPadding={'0'} mobileNoBackground={true}>
|
||||||
{amountOfOffers <= 0 && <DarkSubTitle>No Offers Found</DarkSubTitle>}
|
{amountOfOffers <= 0 && <DarkSubTitle>No Offers Found</DarkSubTitle>}
|
||||||
{data.getOffers.map((offer: any, index: number) => (
|
{data.getOffers.map((offer: any, index: number) => (
|
||||||
<OfferCard
|
<OfferCard
|
||||||
|
|
|
@ -47,7 +47,7 @@ const TransactionsView = () => {
|
||||||
<FlowBox />
|
<FlowBox />
|
||||||
<CardWithTitle>
|
<CardWithTitle>
|
||||||
<SubTitle>Transactions</SubTitle>
|
<SubTitle>Transactions</SubTitle>
|
||||||
<Card bottom={'8px'}>
|
<Card bottom={'8px'} mobileCardPadding={'0'} mobileNoBackground={true}>
|
||||||
{resumeList.map((entry: any, index: number) => {
|
{resumeList.map((entry: any, index: number) => {
|
||||||
if (entry.type === 'invoice') {
|
if (entry.type === 'invoice') {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -25,7 +25,7 @@ export const AuthSSOCheck = ({ cookieParam }: AuthCheckProps) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (cookieParam && !loading && data?.getAuthToken && !ssoSaved) {
|
if (cookieParam && !loading && data && data.getAuthToken && !ssoSaved) {
|
||||||
Cookies.set('SSOAuth', data.getAuthToken, {
|
Cookies.set('SSOAuth', data.getAuthToken, {
|
||||||
sameSite: 'strict',
|
sameSite: 'strict',
|
||||||
});
|
});
|
||||||
|
|
|
@ -40,7 +40,7 @@ export const ServerAccounts = () => {
|
||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!loading && data?.getServerAccounts) {
|
if (!loading && data && data.getServerAccounts) {
|
||||||
const accountsToAdd = data.getServerAccounts.map(a => {
|
const accountsToAdd = data.getServerAccounts.map(a => {
|
||||||
const type = a?.id === SSO_ACCOUNT ? SSO_ACCOUNT : SERVER_ACCOUNT;
|
const type = a?.id === SSO_ACCOUNT ? SSO_ACCOUNT : SERVER_ACCOUNT;
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -42,7 +42,7 @@ export const ChatInit = () => {
|
||||||
}, [dispatch, getMessages, account]);
|
}, [dispatch, getMessages, account]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!initLoading && !initError && initData?.getMessages) {
|
if (!initLoading && !initError && initData && initData.getMessages) {
|
||||||
const { messages } = initData.getMessages;
|
const { messages } = initData.getMessages;
|
||||||
|
|
||||||
if (messages.length <= 0) {
|
if (messages.length <= 0) {
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import {
|
import {
|
||||||
progressBackground,
|
progressBackground,
|
||||||
progressFirst,
|
|
||||||
progressSecond,
|
|
||||||
mediaWidths,
|
mediaWidths,
|
||||||
cardColor,
|
cardColor,
|
||||||
cardBorderColor,
|
cardBorderColor,
|
||||||
|
chartColors,
|
||||||
} from '../../styles/Themes';
|
} from '../../styles/Themes';
|
||||||
|
|
||||||
export const Progress = styled.div`
|
export const Progress = styled.div`
|
||||||
|
@ -20,13 +19,18 @@ interface ProgressBar {
|
||||||
|
|
||||||
export const ProgressBar = styled.div<ProgressBar>`
|
export const ProgressBar = styled.div<ProgressBar>`
|
||||||
height: 10px;
|
height: 10px;
|
||||||
background-image: linear-gradient(
|
background-color: ${({ order }) => {
|
||||||
to bottom,
|
switch (order) {
|
||||||
rgba(255, 255, 255, 0.3),
|
case 1:
|
||||||
rgba(0, 0, 0, 0.05)
|
return chartColors.lightblue;
|
||||||
);
|
case 2:
|
||||||
background-color: ${({ order }) =>
|
return chartColors.green;
|
||||||
order === 2 ? progressFirst : progressSecond};
|
case 3:
|
||||||
|
return chartColors.orange;
|
||||||
|
default:
|
||||||
|
return chartColors.purple;
|
||||||
|
}
|
||||||
|
}};
|
||||||
width: ${({ percent }) => `${percent}%`};
|
width: ${({ percent }) => `${percent}%`};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -47,8 +51,8 @@ export const NodeTitle = styled.div`
|
||||||
export const StatusLine = styled.div`
|
export const StatusLine = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
right: -8px;
|
right: -12px;
|
||||||
top: -8px;
|
top: -12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
margin: 0 0 -8px 0;
|
margin: 0 0 -8px 0;
|
||||||
|
|
|
@ -7,11 +7,13 @@ import {
|
||||||
smallLinkColor,
|
smallLinkColor,
|
||||||
unSelectedNavButton,
|
unSelectedNavButton,
|
||||||
textColor,
|
textColor,
|
||||||
buttonBorderColor,
|
|
||||||
chartLinkColor,
|
chartLinkColor,
|
||||||
inverseTextColor,
|
inverseTextColor,
|
||||||
separationColor,
|
separationColor,
|
||||||
mediaWidths,
|
mediaWidths,
|
||||||
|
colorButtonBackground,
|
||||||
|
colorButtonBorder,
|
||||||
|
hoverTextColor,
|
||||||
} from '../../styles/Themes';
|
} from '../../styles/Themes';
|
||||||
|
|
||||||
export const CardWithTitle = styled.div`
|
export const CardWithTitle = styled.div`
|
||||||
|
@ -29,6 +31,7 @@ export interface CardProps {
|
||||||
bottom?: string;
|
bottom?: string;
|
||||||
cardPadding?: string;
|
cardPadding?: string;
|
||||||
mobileCardPadding?: string;
|
mobileCardPadding?: string;
|
||||||
|
mobileNoBackground?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Card = styled.div<CardProps>`
|
export const Card = styled.div<CardProps>`
|
||||||
|
@ -41,6 +44,13 @@ export const Card = styled.div<CardProps>`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
@media (${mediaWidths.mobile}) {
|
@media (${mediaWidths.mobile}) {
|
||||||
|
${({ mobileNoBackground }) =>
|
||||||
|
mobileNoBackground &&
|
||||||
|
css`
|
||||||
|
background: unset;
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
`}
|
||||||
${({ cardPadding, mobileCardPadding }) =>
|
${({ cardPadding, mobileCardPadding }) =>
|
||||||
mobileCardPadding
|
mobileCardPadding
|
||||||
? css`
|
? css`
|
||||||
|
@ -70,6 +80,7 @@ interface SubCardProps {
|
||||||
color?: string;
|
color?: string;
|
||||||
padding?: string;
|
padding?: string;
|
||||||
withMargin?: string;
|
withMargin?: string;
|
||||||
|
noCard?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SubCard = styled.div<SubCardProps>`
|
export const SubCard = styled.div<SubCardProps>`
|
||||||
|
@ -146,27 +157,6 @@ export const ColumnLine = styled.div`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const SimpleButton = styled.button<{ enabled?: boolean }>`
|
|
||||||
cursor: pointer;
|
|
||||||
outline: none;
|
|
||||||
padding: 5px;
|
|
||||||
margin: 5px;
|
|
||||||
text-decoration: none;
|
|
||||||
background-color: transparent;
|
|
||||||
color: ${({ enabled = true }) => (enabled ? textColor : unSelectedNavButton)};
|
|
||||||
border: 1px solid ${buttonBorderColor};
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
border-radius: 5px;
|
|
||||||
white-space: nowrap;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const SimpleInverseButton = styled(SimpleButton)`
|
|
||||||
color: ${({ enabled = true }: { enabled?: boolean }) =>
|
|
||||||
enabled ? inverseTextColor : unSelectedNavButton};
|
|
||||||
`;
|
|
||||||
|
|
||||||
interface DarkProps {
|
interface DarkProps {
|
||||||
fontSize?: string;
|
fontSize?: string;
|
||||||
withMargin?: string;
|
withMargin?: string;
|
||||||
|
@ -178,17 +168,24 @@ export const DarkSubTitle = styled.div<DarkProps>`
|
||||||
margin: ${({ withMargin }) => (withMargin ? withMargin : '0')};
|
margin: ${({ withMargin }) => (withMargin ? withMargin : '0')};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
interface ColorProps {
|
export const SmallButton = styled.button`
|
||||||
color: string;
|
cursor: pointer;
|
||||||
selected?: boolean;
|
outline: none;
|
||||||
}
|
padding: 5px;
|
||||||
export const ColorButton = styled(SimpleButton)<ColorProps>`
|
margin: 5px;
|
||||||
color: ${({ selected }) => (selected ? textColor : chartLinkColor)};
|
text-decoration: none;
|
||||||
border: ${({ selected, color }) => (selected ? `1px solid ${color}` : '')};
|
border: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 5px;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: ${chartLinkColor};
|
||||||
|
background-color: ${colorButtonBackground};
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border: 1px solid ${({ color }: ColorProps) => color};
|
color: ${hoverTextColor};
|
||||||
color: ${textColor};
|
background-color: ${colorButtonBorder};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,19 @@ import { X } from 'react-feather';
|
||||||
import { SmallLink, DarkSubTitle, OverflowText, SingleLine } from './Styled';
|
import { SmallLink, DarkSubTitle, OverflowText, SingleLine } from './Styled';
|
||||||
import { StatusDot, DetailLine } from './CardGeneric';
|
import { StatusDot, DetailLine } from './CardGeneric';
|
||||||
|
|
||||||
|
const shorten = (text: string): string => {
|
||||||
|
const amount = 6;
|
||||||
|
const beginning = text.slice(0, amount);
|
||||||
|
const end = text.slice(text.length - amount);
|
||||||
|
|
||||||
|
return `${beginning}...${end}`;
|
||||||
|
};
|
||||||
|
|
||||||
export const getTransactionLink = (transaction: string) => {
|
export const getTransactionLink = (transaction: string) => {
|
||||||
const link = `https://www.blockchain.com/btc/tx/${transaction}`;
|
const link = `https://www.blockchain.com/btc/tx/${transaction}`;
|
||||||
return (
|
return (
|
||||||
<SmallLink href={link} target="_blank">
|
<SmallLink href={link} target="_blank">
|
||||||
{transaction}
|
{shorten(transaction)}
|
||||||
</SmallLink>
|
</SmallLink>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -22,7 +30,7 @@ export const getNodeLink = (publicKey: string) => {
|
||||||
const link = `https://1ml.com/node/${publicKey}`;
|
const link = `https://1ml.com/node/${publicKey}`;
|
||||||
return (
|
return (
|
||||||
<SmallLink href={link} target="_blank">
|
<SmallLink href={link} target="_blank">
|
||||||
{publicKey}
|
{shorten(publicKey)}
|
||||||
</SmallLink>
|
</SmallLink>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,7 +27,7 @@ export const RemovePeerModal = ({
|
||||||
peerAlias,
|
peerAlias,
|
||||||
}: RemovePeerProps) => {
|
}: RemovePeerProps) => {
|
||||||
const [removePeer, { loading }] = useRemovePeerMutation({
|
const [removePeer, { loading }] = useRemovePeerMutation({
|
||||||
onCompleted: data => {
|
onCompleted: () => {
|
||||||
toast.success('Peer Removed');
|
toast.success('Peer Removed');
|
||||||
},
|
},
|
||||||
onError: error => {
|
onError: error => {
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { useRouter } from 'next/router';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { useAccountState } from 'src/context/AccountContext';
|
import { useAccountState } from 'src/context/AccountContext';
|
||||||
import { useGetNodeInfoQuery } from 'src/graphql/queries/__generated__/getNodeInfo.generated';
|
import { useGetNodeInfoQuery } from 'src/graphql/queries/__generated__/getNodeInfo.generated';
|
||||||
import { useStatusDispatch, useStatusState } from '../../context/StatusContext';
|
import { useStatusDispatch } from '../../context/StatusContext';
|
||||||
import { appendBasePath } from '../../utils/basePath';
|
import { appendBasePath } from '../../utils/basePath';
|
||||||
|
|
||||||
export const StatusCheck = () => {
|
export const StatusCheck = () => {
|
||||||
|
@ -11,10 +11,8 @@ export const StatusCheck = () => {
|
||||||
const { push } = useRouter();
|
const { push } = useRouter();
|
||||||
|
|
||||||
const { account, auth } = useAccountState();
|
const { account, auth } = useAccountState();
|
||||||
const { connected } = useStatusState();
|
|
||||||
|
|
||||||
const { data, loading, error, stopPolling } = useGetNodeInfoQuery({
|
const { data, loading, error, stopPolling } = useGetNodeInfoQuery({
|
||||||
skip: !auth || !connected,
|
skip: !auth,
|
||||||
fetchPolicy: 'network-only',
|
fetchPolicy: 'network-only',
|
||||||
variables: { auth },
|
variables: { auth },
|
||||||
pollInterval: 10000,
|
pollInterval: 10000,
|
||||||
|
|
|
@ -17,6 +17,7 @@ type State = {
|
||||||
hideNonVerified: boolean;
|
hideNonVerified: boolean;
|
||||||
maxFee: number;
|
maxFee: number;
|
||||||
chatPollingSpeed: number;
|
chatPollingSpeed: number;
|
||||||
|
channelBarType: 'normal' | 'partner';
|
||||||
};
|
};
|
||||||
|
|
||||||
type ConfigInitProps = {
|
type ConfigInitProps = {
|
||||||
|
@ -36,6 +37,7 @@ type ActionType = {
|
||||||
hideNonVerified?: boolean;
|
hideNonVerified?: boolean;
|
||||||
maxFee?: number;
|
maxFee?: number;
|
||||||
chatPollingSpeed?: number;
|
chatPollingSpeed?: number;
|
||||||
|
channelBarType?: 'normal' | 'partner';
|
||||||
};
|
};
|
||||||
|
|
||||||
type Dispatch = (action: ActionType) => void;
|
type Dispatch = (action: ActionType) => void;
|
||||||
|
@ -63,6 +65,7 @@ const initialState: State = {
|
||||||
hideNonVerified: false,
|
hideNonVerified: false,
|
||||||
maxFee: 20,
|
maxFee: 20,
|
||||||
chatPollingSpeed: 1000,
|
chatPollingSpeed: 1000,
|
||||||
|
channelBarType: 'normal',
|
||||||
};
|
};
|
||||||
|
|
||||||
const stateReducer = (state: State, action: ActionType): State => {
|
const stateReducer = (state: State, action: ActionType): State => {
|
||||||
|
|
|
@ -40,7 +40,14 @@ export type GetChannelsQuery = { __typename?: 'Query' } & {
|
||||||
partner_node_info?: Types.Maybe<
|
partner_node_info?: Types.Maybe<
|
||||||
{ __typename?: 'partnerNodeType' } & Pick<
|
{ __typename?: 'partnerNodeType' } & Pick<
|
||||||
Types.PartnerNodeType,
|
Types.PartnerNodeType,
|
||||||
'alias' | 'capacity' | 'channel_count' | 'color' | 'updated_at'
|
| 'alias'
|
||||||
|
| 'capacity'
|
||||||
|
| 'channel_count'
|
||||||
|
| 'color'
|
||||||
|
| 'updated_at'
|
||||||
|
| 'base_fee'
|
||||||
|
| 'fee_rate'
|
||||||
|
| 'cltv_delta'
|
||||||
>
|
>
|
||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
|
@ -80,6 +87,9 @@ export const GetChannelsDocument = gql`
|
||||||
channel_count
|
channel_count
|
||||||
color
|
color
|
||||||
updated_at
|
updated_at
|
||||||
|
base_fee
|
||||||
|
fee_rate
|
||||||
|
cltv_delta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,9 @@ export const GET_CHANNELS = gql`
|
||||||
channel_count
|
channel_count
|
||||||
color
|
color
|
||||||
updated_at
|
updated_at
|
||||||
|
base_fee
|
||||||
|
fee_rate
|
||||||
|
cltv_delta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -261,6 +261,9 @@ export type PartnerNodeType = {
|
||||||
channel_count?: Maybe<Scalars['Int']>;
|
channel_count?: Maybe<Scalars['Int']>;
|
||||||
color?: Maybe<Scalars['String']>;
|
color?: Maybe<Scalars['String']>;
|
||||||
updated_at?: Maybe<Scalars['String']>;
|
updated_at?: Maybe<Scalars['String']>;
|
||||||
|
base_fee?: Maybe<Scalars['Int']>;
|
||||||
|
fee_rate?: Maybe<Scalars['Int']>;
|
||||||
|
cltv_delta?: Maybe<Scalars['Int']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ClosedChannelType = {
|
export type ClosedChannelType = {
|
||||||
|
|
|
@ -61,7 +61,7 @@ export const Header = () => {
|
||||||
<Link to={connected ? '/home' : '/'} underline={'transparent'}>
|
<Link to={connected ? '/home' : '/'} underline={'transparent'}>
|
||||||
<HeaderTitle withPadding={!connected}>
|
<HeaderTitle withPadding={!connected}>
|
||||||
<IconPadding>
|
<IconPadding>
|
||||||
<Cpu color={'white'} />
|
<Cpu color={'white'} size={18} />
|
||||||
</IconPadding>
|
</IconPadding>
|
||||||
ThunderHub
|
ThunderHub
|
||||||
</HeaderTitle>
|
</HeaderTitle>
|
||||||
|
|
|
@ -35,7 +35,9 @@ export const getValue = ({
|
||||||
if (currency === 'btc') {
|
if (currency === 'btc') {
|
||||||
if (!value) return '₿0.0';
|
if (!value) return '₿0.0';
|
||||||
const amountInBtc = value / 100000000;
|
const amountInBtc = value / 100000000;
|
||||||
return `₿${amountInBtc}`;
|
const rounded = Math.round(amountInBtc * 10000) / 10000;
|
||||||
|
|
||||||
|
return `₿${rounded}`;
|
||||||
}
|
}
|
||||||
if (currency === 'sat') {
|
if (currency === 'sat') {
|
||||||
const breakAmount = breakNumber
|
const breakAmount = breakNumber
|
||||||
|
@ -107,9 +109,9 @@ export const formatSeconds = (seconds: number): string | null => {
|
||||||
const m = Math.floor((seconds % 3600) / 60);
|
const m = Math.floor((seconds % 3600) / 60);
|
||||||
const s = Math.floor(seconds % 60);
|
const s = Math.floor(seconds % 60);
|
||||||
|
|
||||||
const dDisplay = d > 0 ? d + (d == 1 ? ' day, ' : ' days, ') : '';
|
const dDisplay = d > 0 ? `${d}d ` : '';
|
||||||
const hDisplay = h > 0 ? h + (h == 1 ? ' hour, ' : ' hours, ') : '';
|
const hDisplay = h > 0 ? `${h}h ` : '';
|
||||||
const mDisplay = m > 0 ? m + (m == 1 ? ' minute, ' : ' minutes, ') : '';
|
const mDisplay = m > 0 ? `${m}m ` : '';
|
||||||
const sDisplay = s > 0 ? s + (s == 1 ? ' second' : ' seconds') : '';
|
const sDisplay = s > 0 ? `${s}s` : '';
|
||||||
return dDisplay + hDisplay + mDisplay + sDisplay;
|
return dDisplay + hDisplay + mDisplay + sDisplay;
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,7 +28,7 @@ export const ChainTransactions = () => {
|
||||||
return (
|
return (
|
||||||
<CardWithTitle>
|
<CardWithTitle>
|
||||||
<SubTitle>Chain Transactions</SubTitle>
|
<SubTitle>Chain Transactions</SubTitle>
|
||||||
<Card>
|
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
|
||||||
{data.getChainTransactions.map((transaction: any, index: number) => (
|
{data.getChainTransactions.map((transaction: any, index: number) => (
|
||||||
<TransactionsCard
|
<TransactionsCard
|
||||||
transaction={transaction}
|
transaction={transaction}
|
||||||
|
|
|
@ -28,7 +28,7 @@ export const ChainUtxos = () => {
|
||||||
return (
|
return (
|
||||||
<CardWithTitle>
|
<CardWithTitle>
|
||||||
<SubTitle>Unspent Utxos</SubTitle>
|
<SubTitle>Unspent Utxos</SubTitle>
|
||||||
<Card>
|
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
|
||||||
{data.getUtxos.map((utxo: any, index: number) => (
|
{data.getUtxos.map((utxo: any, index: number) => (
|
||||||
<UtxoCard
|
<UtxoCard
|
||||||
utxo={utxo}
|
utxo={utxo}
|
||||||
|
|
|
@ -2,11 +2,11 @@ import React, { useState } from 'react';
|
||||||
import ReactTooltip from 'react-tooltip';
|
import ReactTooltip from 'react-tooltip';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { ArrowDown, ArrowUp, EyeOff } from 'react-feather';
|
import { ArrowDown, ArrowUp, EyeOff } from 'react-feather';
|
||||||
|
import { mediaWidths } from 'src/styles/Themes';
|
||||||
|
import { ChannelType } from 'src/graphql/types';
|
||||||
import { getPercent, formatSeconds } from '../../../utils/helpers';
|
import { getPercent, formatSeconds } from '../../../utils/helpers';
|
||||||
import {
|
import {
|
||||||
Progress,
|
|
||||||
ProgressBar,
|
ProgressBar,
|
||||||
NodeTitle,
|
|
||||||
StatusLine,
|
StatusLine,
|
||||||
MainInfo,
|
MainInfo,
|
||||||
} from '../../../components/generic/CardGeneric';
|
} from '../../../components/generic/CardGeneric';
|
||||||
|
@ -16,10 +16,12 @@ import {
|
||||||
Sub4Title,
|
Sub4Title,
|
||||||
RightAlign,
|
RightAlign,
|
||||||
ResponsiveLine,
|
ResponsiveLine,
|
||||||
ResponsiveSingle,
|
DarkSubTitle,
|
||||||
ResponsiveCol,
|
|
||||||
} from '../../../components/generic/Styled';
|
} from '../../../components/generic/Styled';
|
||||||
import { useConfigState } from '../../../context/ConfigContext';
|
import {
|
||||||
|
useConfigState,
|
||||||
|
useConfigDispatch,
|
||||||
|
} from '../../../context/ConfigContext';
|
||||||
import {
|
import {
|
||||||
getStatusDot,
|
getStatusDot,
|
||||||
getTooltipType,
|
getTooltipType,
|
||||||
|
@ -37,23 +39,69 @@ import { getPrice } from '../../../components/price/Price';
|
||||||
import { usePriceState } from '../../../context/PriceContext';
|
import { usePriceState } from '../../../context/PriceContext';
|
||||||
|
|
||||||
const IconPadding = styled.div`
|
const IconPadding = styled.div`
|
||||||
margin-left: 16px;
|
display: flex;
|
||||||
margin-right: 8px;
|
flex-direction: column;
|
||||||
|
margin-left: 8px;
|
||||||
|
|
||||||
|
@media (${mediaWidths.mobile}) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StatsColumn = styled.div`
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const BarSide = styled.div`
|
||||||
|
width: 50%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
@media (${mediaWidths.mobile}) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const NodeTitle = styled.div`
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
|
@media (${mediaWidths.mobile}) {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const getSymbol = (status: boolean) => {
|
const getSymbol = (status: boolean) => {
|
||||||
return status ? <ArrowDown size={18} /> : <ArrowUp size={18} />;
|
return status ? <ArrowDown size={14} /> : <ArrowUp size={14} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPrivate = (status: boolean) => {
|
const getPrivate = (status: boolean) => {
|
||||||
return status && <EyeOff />;
|
return status && <EyeOff size={14} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getBar = (top: number, bottom: number) => {
|
||||||
|
const percent = (top / bottom) * 100;
|
||||||
|
return Math.min(percent, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ChannelCardProps {
|
interface ChannelCardProps {
|
||||||
channelInfo: any;
|
channelInfo: ChannelType;
|
||||||
index: number;
|
index: number;
|
||||||
setIndexOpen: (index: number) => void;
|
setIndexOpen: (index: number) => void;
|
||||||
indexOpen: number;
|
indexOpen: number;
|
||||||
|
biggest: number;
|
||||||
|
biggestPartner: number;
|
||||||
|
mostChannels: number;
|
||||||
|
biggestBaseFee: number;
|
||||||
|
biggestRateFee: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ChannelCard = ({
|
export const ChannelCard = ({
|
||||||
|
@ -61,7 +109,14 @@ export const ChannelCard = ({
|
||||||
index,
|
index,
|
||||||
setIndexOpen,
|
setIndexOpen,
|
||||||
indexOpen,
|
indexOpen,
|
||||||
|
biggest,
|
||||||
|
biggestPartner,
|
||||||
|
mostChannels,
|
||||||
|
biggestBaseFee,
|
||||||
|
biggestRateFee,
|
||||||
}: ChannelCardProps) => {
|
}: ChannelCardProps) => {
|
||||||
|
const { channelBarType } = useConfigState();
|
||||||
|
const dispatch = useConfigDispatch();
|
||||||
const [modalOpen, setModalOpen] = useState(false);
|
const [modalOpen, setModalOpen] = useState(false);
|
||||||
|
|
||||||
const { theme, currency, displayValues } = useConfigState();
|
const { theme, currency, displayValues } = useConfigState();
|
||||||
|
@ -98,10 +153,12 @@ export const ChannelCard = ({
|
||||||
|
|
||||||
const {
|
const {
|
||||||
alias,
|
alias,
|
||||||
capacity: partnerNodeCapacity,
|
capacity: partnerNodeCapacity = 0,
|
||||||
channel_count,
|
channel_count,
|
||||||
color: nodeColor,
|
|
||||||
updated_at,
|
updated_at,
|
||||||
|
base_fee,
|
||||||
|
fee_rate,
|
||||||
|
cltv_delta,
|
||||||
} = partner_node_info;
|
} = partner_node_info;
|
||||||
|
|
||||||
const formatBalance = format({ amount: capacity });
|
const formatBalance = format({ amount: capacity });
|
||||||
|
@ -123,10 +180,20 @@ export const ChannelCard = ({
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleBarClick = () => {
|
||||||
|
dispatch({
|
||||||
|
type: 'change',
|
||||||
|
channelBarType: channelBarType === 'normal' ? 'partner' : 'normal',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const renderDetails = () => {
|
const renderDetails = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Separation />
|
<Separation />
|
||||||
|
{renderLine('Status:', is_active ? 'Active' : 'Not Active')}
|
||||||
|
{renderLine('Is Opening:', is_opening ? 'True' : 'False')}
|
||||||
|
{renderLine('Is Closing:', is_closing ? 'True' : 'False')}
|
||||||
{renderLine(
|
{renderLine(
|
||||||
'Balancedness:',
|
'Balancedness:',
|
||||||
getPercent(local_balance, remote_balance) / 100
|
getPercent(local_balance, remote_balance) / 100
|
||||||
|
@ -154,6 +221,9 @@ export const ChannelCard = ({
|
||||||
'Last Update:',
|
'Last Update:',
|
||||||
`${getDateDif(updated_at)} ago (${getFormatDate(updated_at)})`
|
`${getDateDif(updated_at)} ago (${getFormatDate(updated_at)})`
|
||||||
)}
|
)}
|
||||||
|
{renderLine('Base Fee:', `${base_fee} mSats`)}
|
||||||
|
{renderLine('Fee Rate:', `${fee_rate} sats/MSats`)}
|
||||||
|
{renderLine('CTLV Delta:', cltv_delta)}
|
||||||
<AdminSwitch>
|
<AdminSwitch>
|
||||||
<Separation />
|
<Separation />
|
||||||
<RightAlign>
|
<RightAlign>
|
||||||
|
@ -170,9 +240,60 @@ export const ChannelCard = ({
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const renderBars = () => {
|
||||||
|
switch (channelBarType) {
|
||||||
|
case 'partner':
|
||||||
return (
|
return (
|
||||||
<SubCard color={nodeColor} key={`${index}-${id}`}>
|
<>
|
||||||
<MainInfo onClick={() => handleClick()}>
|
<ProgressBar
|
||||||
|
order={0}
|
||||||
|
percent={getBar(Number(partnerNodeCapacity), biggestPartner)}
|
||||||
|
/>
|
||||||
|
<ProgressBar
|
||||||
|
order={3}
|
||||||
|
percent={getBar(channel_count, mostChannels)}
|
||||||
|
/>
|
||||||
|
<ProgressBar order={1} percent={getBar(base_fee, biggestBaseFee)} />
|
||||||
|
<ProgressBar order={2} percent={getBar(fee_rate, biggestRateFee)} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ProgressBar order={0} percent={getBar(local_balance, biggest)} />
|
||||||
|
<ProgressBar order={1} percent={getBar(remote_balance, biggest)} />
|
||||||
|
<ProgressBar order={2} percent={getBar(received, biggest)} />
|
||||||
|
<ProgressBar order={3} percent={getBar(sent, biggest)} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderBarsInfo = () => {
|
||||||
|
switch (channelBarType) {
|
||||||
|
case 'partner':
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div>{`Partner Capacity: ${nodeCapacity}`}</div>
|
||||||
|
<div>{`Partner Channels: ${channel_count}`}</div>
|
||||||
|
<div>{`Partner Base Fee: ${base_fee} mSats`}</div>
|
||||||
|
<div>{`Partner Fee Rate: ${fee_rate} sats/MSats`}</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div>{`Local Balance: ${formatLocal}`}</div>
|
||||||
|
<div>{`Remote Balance: ${formatRemote}`}</div>
|
||||||
|
<div>{`Received: ${formatReceived}`}</div>
|
||||||
|
<div>{`Sent: ${formatSent}`}</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SubCard key={`${index}-${id}`} noCard={true}>
|
||||||
<StatusLine>
|
<StatusLine>
|
||||||
{getStatusDot(is_active, 'active')}
|
{getStatusDot(is_active, 'active')}
|
||||||
{getStatusDot(is_opening, 'opening')}
|
{getStatusDot(is_opening, 'opening')}
|
||||||
|
@ -180,27 +301,25 @@ export const ChannelCard = ({
|
||||||
</StatusLine>
|
</StatusLine>
|
||||||
<ResponsiveLine>
|
<ResponsiveLine>
|
||||||
<NodeTitle style={{ flexGrow: 2 }}>
|
<NodeTitle style={{ flexGrow: 2 }}>
|
||||||
|
<MainInfo onClick={() => handleClick()}>
|
||||||
{alias || partner_public_key?.substring(0, 6)}
|
{alias || partner_public_key?.substring(0, 6)}
|
||||||
|
<DarkSubTitle>{formatBalance}</DarkSubTitle>
|
||||||
|
</MainInfo>
|
||||||
</NodeTitle>
|
</NodeTitle>
|
||||||
<ResponsiveSingle>
|
<BarSide>
|
||||||
{formatBalance}
|
<StatsColumn
|
||||||
|
data-tip
|
||||||
|
data-for={`node_balance_tip_${index}`}
|
||||||
|
onClick={handleBarClick}
|
||||||
|
>
|
||||||
|
{renderBars()}
|
||||||
|
</StatsColumn>
|
||||||
|
</BarSide>
|
||||||
<IconPadding>
|
<IconPadding>
|
||||||
{getPrivate(is_private)}
|
{getPrivate(is_private)}
|
||||||
{getSymbol(is_partner_initiated)}
|
{getSymbol(is_partner_initiated)}
|
||||||
</IconPadding>
|
</IconPadding>
|
||||||
<ResponsiveCol>
|
|
||||||
<Progress data-tip data-for={`node_balance_tip_${index}`}>
|
|
||||||
<ProgressBar
|
|
||||||
percent={getPercent(local_balance, remote_balance)}
|
|
||||||
/>
|
|
||||||
</Progress>
|
|
||||||
<Progress data-tip data-for={`node_activity_tip_${index}`}>
|
|
||||||
<ProgressBar order={2} percent={getPercent(received, sent)} />
|
|
||||||
</Progress>
|
|
||||||
</ResponsiveCol>
|
|
||||||
</ResponsiveSingle>
|
|
||||||
</ResponsiveLine>
|
</ResponsiveLine>
|
||||||
</MainInfo>
|
|
||||||
{index === indexOpen && renderDetails()}
|
{index === indexOpen && renderDetails()}
|
||||||
<ReactTooltip
|
<ReactTooltip
|
||||||
id={`node_balance_tip_${index}`}
|
id={`node_balance_tip_${index}`}
|
||||||
|
@ -208,17 +327,7 @@ export const ChannelCard = ({
|
||||||
place={'bottom'}
|
place={'bottom'}
|
||||||
type={tooltipType}
|
type={tooltipType}
|
||||||
>
|
>
|
||||||
<div>{`Local Balance: ${formatLocal}`}</div>
|
{renderBarsInfo()}
|
||||||
<div>{`Remote Balance: ${formatRemote}`}</div>
|
|
||||||
</ReactTooltip>
|
|
||||||
<ReactTooltip
|
|
||||||
id={`node_activity_tip_${index}`}
|
|
||||||
effect={'solid'}
|
|
||||||
place={'bottom'}
|
|
||||||
type={tooltipType}
|
|
||||||
>
|
|
||||||
<div>{`Received: ${formatReceived}`}</div>
|
|
||||||
<div>{`Sent: ${formatSent}`}</div>
|
|
||||||
</ReactTooltip>
|
</ReactTooltip>
|
||||||
<Modal isOpen={modalOpen} closeCallback={() => setModalOpen(false)}>
|
<Modal isOpen={modalOpen} closeCallback={() => setModalOpen(false)}>
|
||||||
<CloseChannel
|
<CloseChannel
|
||||||
|
|
|
@ -23,15 +23,59 @@ export const Channels = () => {
|
||||||
return <LoadingCard noTitle={true} />;
|
return <LoadingCard noTitle={true} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let biggest = 0;
|
||||||
|
let biggestPartner = 0;
|
||||||
|
let mostChannels = 0;
|
||||||
|
let biggestBaseFee = 0;
|
||||||
|
let biggestRateFee = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < data.getChannels.length; i++) {
|
||||||
|
const channel = data.getChannels[i];
|
||||||
|
const {
|
||||||
|
local_balance,
|
||||||
|
remote_balance,
|
||||||
|
sent,
|
||||||
|
received,
|
||||||
|
partner_node_info = {},
|
||||||
|
} = channel;
|
||||||
|
|
||||||
|
const { capacity, channel_count, base_fee, fee_rate } = partner_node_info;
|
||||||
|
const partner = Number(capacity) || 0;
|
||||||
|
const channels = Number(channel_count) || 0;
|
||||||
|
|
||||||
|
const max = Math.max(local_balance, remote_balance, sent, received);
|
||||||
|
|
||||||
|
if (max > biggest) {
|
||||||
|
biggest = max;
|
||||||
|
}
|
||||||
|
if (partner > biggestPartner) {
|
||||||
|
biggestPartner = partner;
|
||||||
|
}
|
||||||
|
if (channels > mostChannels) {
|
||||||
|
mostChannels = channels;
|
||||||
|
}
|
||||||
|
if (base_fee > biggestBaseFee) {
|
||||||
|
biggestBaseFee = base_fee;
|
||||||
|
}
|
||||||
|
if (fee_rate > biggestRateFee) {
|
||||||
|
biggestRateFee = fee_rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
|
||||||
{data.getChannels.map((channel: any, index: number) => (
|
{data.getChannels.map((channel, index: number) => (
|
||||||
<ChannelCard
|
<ChannelCard
|
||||||
channelInfo={channel}
|
channelInfo={channel}
|
||||||
index={index + 1}
|
index={index + 1}
|
||||||
setIndexOpen={setIndexOpen}
|
setIndexOpen={setIndexOpen}
|
||||||
indexOpen={indexOpen}
|
indexOpen={indexOpen}
|
||||||
key={`${index}-${channel.id}`}
|
key={`${index}-${channel.id}`}
|
||||||
|
biggest={biggest}
|
||||||
|
biggestPartner={biggestPartner}
|
||||||
|
mostChannels={mostChannels}
|
||||||
|
biggestBaseFee={biggestBaseFee * 2}
|
||||||
|
biggestRateFee={biggestRateFee}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import { ClosedChannelType } from 'src/graphql/types';
|
||||||
import { NodeTitle, MainInfo } from '../../../components/generic/CardGeneric';
|
import { NodeTitle, MainInfo } from '../../../components/generic/CardGeneric';
|
||||||
import {
|
import {
|
||||||
SubCard,
|
SubCard,
|
||||||
|
@ -20,7 +21,7 @@ const Padding = styled.div`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
interface PendingCardProps {
|
interface PendingCardProps {
|
||||||
channelInfo: any;
|
channelInfo: ClosedChannelType;
|
||||||
index: number;
|
index: number;
|
||||||
setIndexOpen: (index: number) => void;
|
setIndexOpen: (index: number) => void;
|
||||||
indexOpen: number;
|
indexOpen: number;
|
||||||
|
|
|
@ -23,8 +23,8 @@ export const ClosedChannels = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
|
||||||
{data.getClosedChannels.map((channel: any, index: number) => (
|
{data.getClosedChannels.map((channel, index: number) => (
|
||||||
<ClosedCard
|
<ClosedCard
|
||||||
channelInfo={channel}
|
channelInfo={channel}
|
||||||
key={index}
|
key={index}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTooltip from 'react-tooltip';
|
import ReactTooltip from 'react-tooltip';
|
||||||
|
import { PendingChannelType } from 'src/graphql/types';
|
||||||
import { getPercent } from '../../../utils/helpers';
|
import { getPercent } from '../../../utils/helpers';
|
||||||
import {
|
import {
|
||||||
Progress,
|
Progress,
|
||||||
|
@ -29,32 +30,8 @@ import {
|
||||||
import { getPrice } from '../../../components/price/Price';
|
import { getPrice } from '../../../components/price/Price';
|
||||||
import { usePriceState } from '../../../context/PriceContext';
|
import { usePriceState } from '../../../context/PriceContext';
|
||||||
|
|
||||||
interface ChannelProps {
|
|
||||||
close_transaction_id: string;
|
|
||||||
is_active: boolean;
|
|
||||||
is_closing: boolean;
|
|
||||||
is_opening: boolean;
|
|
||||||
local_balance: number;
|
|
||||||
local_reserve: number;
|
|
||||||
partner_public_key: string;
|
|
||||||
received: number;
|
|
||||||
remote_balance: number;
|
|
||||||
remote_reserve: number;
|
|
||||||
sent: number;
|
|
||||||
transaction_fee: number;
|
|
||||||
transaction_id: string;
|
|
||||||
transaction_vout: number;
|
|
||||||
partner_node_info: {
|
|
||||||
alias: string;
|
|
||||||
capacity: string;
|
|
||||||
channelCount: string;
|
|
||||||
color: string;
|
|
||||||
updated_at: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PendingCardProps {
|
interface PendingCardProps {
|
||||||
channelInfo: ChannelProps;
|
channelInfo: PendingChannelType;
|
||||||
index: number;
|
index: number;
|
||||||
setIndexOpen: (index: number) => void;
|
setIndexOpen: (index: number) => void;
|
||||||
indexOpen: number;
|
indexOpen: number;
|
||||||
|
@ -93,7 +70,7 @@ export const PendingCard = ({
|
||||||
const {
|
const {
|
||||||
alias,
|
alias,
|
||||||
capacity,
|
capacity,
|
||||||
channelCount,
|
channel_count,
|
||||||
color: nodeColor,
|
color: nodeColor,
|
||||||
updated_at,
|
updated_at,
|
||||||
} = partner_node_info;
|
} = partner_node_info;
|
||||||
|
@ -132,7 +109,7 @@ export const PendingCard = ({
|
||||||
{renderLine('Remote Reserve:', remote_reserve)}
|
{renderLine('Remote Reserve:', remote_reserve)}
|
||||||
<Sub4Title>Partner Node Info</Sub4Title>
|
<Sub4Title>Partner Node Info</Sub4Title>
|
||||||
{renderLine('Node Capacity:', capacity)}
|
{renderLine('Node Capacity:', capacity)}
|
||||||
{renderLine('Channels:', channelCount)}
|
{renderLine('Channels:', channel_count)}
|
||||||
{renderLine(
|
{renderLine(
|
||||||
'Last Update:',
|
'Last Update:',
|
||||||
`${getDateDif(updated_at)} ago (${getFormatDate(updated_at)})`
|
`${getDateDif(updated_at)} ago (${getFormatDate(updated_at)})`
|
||||||
|
|
|
@ -23,8 +23,8 @@ export const PendingChannels = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
|
||||||
{data.getPendingChannels.map((channel: any, index: number) => (
|
{data.getPendingChannels.map((channel, index: number) => (
|
||||||
<PendingCard
|
<PendingCard
|
||||||
channelInfo={channel}
|
channelInfo={channel}
|
||||||
key={index}
|
key={index}
|
||||||
|
|
|
@ -39,7 +39,7 @@ const SendButton = ({ amount }: SendButtonProps) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!loading && data?.sendMessage >= 0) {
|
if (!loading && data && data.sendMessage >= 0) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'newChat',
|
type: 'newChat',
|
||||||
newChat: {
|
newChat: {
|
||||||
|
|
|
@ -35,7 +35,7 @@ export const ChatInput = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!loading && data?.sendMessage >= 0) {
|
if (!loading && data && data.sendMessage >= 0) {
|
||||||
setMessage('');
|
setMessage('');
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'newChat',
|
type: 'newChat',
|
||||||
|
|
|
@ -52,7 +52,7 @@ export const ContactCard = ({
|
||||||
}, [contact, sender, alias, contactSender, getInfo, setUser, user]);
|
}, [contact, sender, alias, contactSender, getInfo, setUser, user]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!loading && data?.getNode) {
|
if (!loading && data && data.getNode) {
|
||||||
const { alias } = data.getNode;
|
const { alias } = data.getNode;
|
||||||
const name =
|
const name =
|
||||||
alias && alias !== '' ? alias : contactSender.substring(0, 6);
|
alias && alias !== '' ? alias : contactSender.substring(0, 6);
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { ArrowUp, Zap, Anchor, Pocket, ArrowDown, X } from 'react-feather';
|
import { Zap, Anchor, Pocket } from 'react-feather';
|
||||||
|
import { ColorButton } from 'src/components/buttons/colorButton/ColorButton';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardWithTitle,
|
CardWithTitle,
|
||||||
SubTitle,
|
SubTitle,
|
||||||
Separation,
|
Separation,
|
||||||
DarkSubTitle,
|
DarkSubTitle,
|
||||||
ColorButton,
|
|
||||||
ResponsiveLine,
|
ResponsiveLine,
|
||||||
} from '../../../components/generic/Styled';
|
} from '../../../components/generic/Styled';
|
||||||
import { LoadingCard } from '../../../components/loading/LoadingCard';
|
import { LoadingCard } from '../../../components/loading/LoadingCard';
|
||||||
|
@ -35,8 +35,14 @@ const Tile = styled.div`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ButtonRow = styled.div`
|
const AccountButtonWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
@media (${mediaWidths.mobile}) {
|
||||||
|
flex-direction: row;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const sectionColor = '#FFD300';
|
const sectionColor = '#FFD300';
|
||||||
|
@ -118,14 +124,24 @@ export const AccountInfo = () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderButtons = (send: string, receive: string) => (
|
const renderButtons = (send: string, receive: string) => (
|
||||||
<>
|
<AccountButtonWrapper>
|
||||||
<ColorButton color={sectionColor} onClick={() => setState(send)}>
|
<ColorButton
|
||||||
<ArrowUp size={18} />
|
fullWidth={true}
|
||||||
|
withMargin={'0 0 2px'}
|
||||||
|
mobileMargin={'8px 4px 0 0'}
|
||||||
|
onClick={() => setState(send)}
|
||||||
|
>
|
||||||
|
Send
|
||||||
</ColorButton>
|
</ColorButton>
|
||||||
<ColorButton color={sectionColor} onClick={() => setState(receive)}>
|
<ColorButton
|
||||||
<ArrowDown size={18} />
|
fullWidth={true}
|
||||||
|
withMargin={'2px 0 0'}
|
||||||
|
mobileMargin={'8px 0 0 4px'}
|
||||||
|
onClick={() => setState(receive)}
|
||||||
|
>
|
||||||
|
Receive
|
||||||
</ColorButton>
|
</ColorButton>
|
||||||
</>
|
</AccountButtonWrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderLnAccount = () => (
|
const renderLnAccount = () => (
|
||||||
|
@ -137,14 +153,10 @@ export const AccountInfo = () => {
|
||||||
</Tile>
|
</Tile>
|
||||||
{renderBalances(formatCCB, formatPCB)}
|
{renderBalances(formatCCB, formatPCB)}
|
||||||
<AdminSwitch>
|
<AdminSwitch>
|
||||||
<ButtonRow>
|
|
||||||
{showLn && showChain && renderButtons('send_ln', 'receive_ln')}
|
{showLn && showChain && renderButtons('send_ln', 'receive_ln')}
|
||||||
{showLn && !showChain && (
|
{showLn && !showChain && (
|
||||||
<ColorButton color={sectionColor} onClick={() => setState('none')}>
|
<ColorButton onClick={() => setState('none')}>Cancel</ColorButton>
|
||||||
<X size={18} />
|
|
||||||
</ColorButton>
|
|
||||||
)}
|
)}
|
||||||
</ButtonRow>
|
|
||||||
</AdminSwitch>
|
</AdminSwitch>
|
||||||
</ResponsiveLine>
|
</ResponsiveLine>
|
||||||
);
|
);
|
||||||
|
@ -158,14 +170,10 @@ export const AccountInfo = () => {
|
||||||
</Tile>
|
</Tile>
|
||||||
{renderBalances(formatCB, formatPB)}
|
{renderBalances(formatCB, formatPB)}
|
||||||
<AdminSwitch>
|
<AdminSwitch>
|
||||||
<ButtonRow>
|
|
||||||
{showLn && showChain && renderButtons('send_chain', 'receive_chain')}
|
{showLn && showChain && renderButtons('send_chain', 'receive_chain')}
|
||||||
{!showLn && showChain && (
|
{!showLn && showChain && (
|
||||||
<ColorButton color={sectionColor} onClick={() => setState('none')}>
|
<ColorButton onClick={() => setState('none')}>Cancel</ColorButton>
|
||||||
<X size={18} />
|
|
||||||
</ColorButton>
|
|
||||||
)}
|
)}
|
||||||
</ButtonRow>
|
|
||||||
</AdminSwitch>
|
</AdminSwitch>
|
||||||
</ResponsiveLine>
|
</ResponsiveLine>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,6 +5,7 @@ import styled from 'styled-components';
|
||||||
import CopyToClipboard from 'react-copy-to-clipboard';
|
import CopyToClipboard from 'react-copy-to-clipboard';
|
||||||
import { useAccountState } from 'src/context/AccountContext';
|
import { useAccountState } from 'src/context/AccountContext';
|
||||||
import { useGetCanConnectInfoQuery } from 'src/graphql/queries/__generated__/getNodeInfo.generated';
|
import { useGetCanConnectInfoQuery } from 'src/graphql/queries/__generated__/getNodeInfo.generated';
|
||||||
|
import { ColorButton } from 'src/components/buttons/colorButton/ColorButton';
|
||||||
import { getErrorContent } from '../../../utils/error';
|
import { getErrorContent } from '../../../utils/error';
|
||||||
import { LoadingCard } from '../../../components/loading/LoadingCard';
|
import { LoadingCard } from '../../../components/loading/LoadingCard';
|
||||||
import {
|
import {
|
||||||
|
@ -14,7 +15,6 @@ import {
|
||||||
Card,
|
Card,
|
||||||
SingleLine,
|
SingleLine,
|
||||||
DarkSubTitle,
|
DarkSubTitle,
|
||||||
ColorButton,
|
|
||||||
} from '../../../components/generic/Styled';
|
} from '../../../components/generic/Styled';
|
||||||
import { mediaWidths } from '../../../styles/Themes';
|
import { mediaWidths } from '../../../styles/Themes';
|
||||||
|
|
||||||
|
@ -52,6 +52,14 @@ const TextPadding = styled.span`
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const ButtonRow = styled.div`
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
@media (${mediaWidths.mobile}) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const sectionColor = '#fa541c';
|
const sectionColor = '#fa541c';
|
||||||
|
|
||||||
export const ConnectCard = () => {
|
export const ConnectCard = () => {
|
||||||
|
@ -84,13 +92,13 @@ export const ConnectCard = () => {
|
||||||
<DarkSubTitle>Public Key</DarkSubTitle>
|
<DarkSubTitle>Public Key</DarkSubTitle>
|
||||||
<Key>{public_key}</Key>
|
<Key>{public_key}</Key>
|
||||||
</Tile>
|
</Tile>
|
||||||
<SingleLine>
|
<ButtonRow>
|
||||||
{onionAddress ? (
|
{onionAddress ? (
|
||||||
<CopyToClipboard
|
<CopyToClipboard
|
||||||
text={onionAddress}
|
text={onionAddress}
|
||||||
onCopy={() => toast.success('Onion Address Copied')}
|
onCopy={() => toast.success('Onion Address Copied')}
|
||||||
>
|
>
|
||||||
<ColorButton color={sectionColor}>
|
<ColorButton fullWidth={true} withMargin={'0 4px 0 0'}>
|
||||||
<Copy size={18} />
|
<Copy size={18} />
|
||||||
<TextPadding>Onion</TextPadding>
|
<TextPadding>Onion</TextPadding>
|
||||||
</ColorButton>
|
</ColorButton>
|
||||||
|
@ -101,12 +109,12 @@ export const ConnectCard = () => {
|
||||||
text={normalAddress}
|
text={normalAddress}
|
||||||
onCopy={() => toast.success('Public Address Copied')}
|
onCopy={() => toast.success('Public Address Copied')}
|
||||||
>
|
>
|
||||||
<ColorButton color={sectionColor}>
|
<ColorButton fullWidth={true} withMargin={'0 0 0 4px'}>
|
||||||
<Copy size={18} />
|
<Copy size={18} />
|
||||||
</ColorButton>
|
</ColorButton>
|
||||||
</CopyToClipboard>
|
</CopyToClipboard>
|
||||||
) : null}
|
) : null}
|
||||||
</SingleLine>
|
</ButtonRow>
|
||||||
</Responsive>
|
</Responsive>
|
||||||
</Card>
|
</Card>
|
||||||
</CardWithTitle>
|
</CardWithTitle>
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
SubTitle,
|
SubTitle,
|
||||||
Card,
|
Card,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
ColorButton,
|
SmallButton,
|
||||||
} from '../../../components/generic/Styled';
|
} from '../../../components/generic/Styled';
|
||||||
import { unSelectedNavButton } from '../../../styles/Themes';
|
import { unSelectedNavButton } from '../../../styles/Themes';
|
||||||
import { AdminSwitch } from '../../../components/adminSwitch/AdminSwitch';
|
import { AdminSwitch } from '../../../components/adminSwitch/AdminSwitch';
|
||||||
|
@ -87,9 +87,9 @@ export const QuickActions = () => {
|
||||||
<CardTitle>
|
<CardTitle>
|
||||||
<SubTitle>{getTitle()}</SubTitle>
|
<SubTitle>{getTitle()}</SubTitle>
|
||||||
{openCard !== 'none' && (
|
{openCard !== 'none' && (
|
||||||
<ColorButton onClick={() => setOpenCard('none')} color={sectionColor}>
|
<SmallButton onClick={() => setOpenCard('none')}>
|
||||||
<X size={18} />
|
<X size={18} />
|
||||||
</ColorButton>
|
</SmallButton>
|
||||||
)}
|
)}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
{renderContent()}
|
{renderContent()}
|
||||||
|
|
|
@ -1,46 +1,28 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import numeral from 'numeral';
|
import { VictoryBar, VictoryChart, VictoryAxis, VictoryGroup } from 'victory';
|
||||||
import {
|
|
||||||
VictoryBar,
|
|
||||||
VictoryChart,
|
|
||||||
VictoryAxis,
|
|
||||||
VictoryVoronoiContainer,
|
|
||||||
VictoryGroup,
|
|
||||||
} from 'victory';
|
|
||||||
import { useConfigState } from '../../../../context/ConfigContext';
|
import { useConfigState } from '../../../../context/ConfigContext';
|
||||||
import {
|
import {
|
||||||
chartAxisColor,
|
chartAxisColor,
|
||||||
chartGridColor,
|
chartGridColor,
|
||||||
// chartColors,
|
|
||||||
flowBarColor,
|
flowBarColor,
|
||||||
flowBarColor2,
|
flowBarColor2,
|
||||||
} from '../../../../styles/Themes';
|
} from '../../../../styles/Themes';
|
||||||
import { getPrice } from '../../../../components/price/Price';
|
import { getPrice } from '../../../../components/price/Price';
|
||||||
import { usePriceState } from '../../../../context/PriceContext';
|
import { usePriceState } from '../../../../context/PriceContext';
|
||||||
// import { WaterfallProps } from '.';
|
|
||||||
|
|
||||||
// const beforeMap = {
|
|
||||||
// amount: 'amountBefore',
|
|
||||||
// tokens: 'tokensBefore',
|
|
||||||
// };
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isTime: string;
|
isTime: string;
|
||||||
isType: string;
|
isType: string;
|
||||||
// isGraph: string;
|
|
||||||
parsedData: {}[];
|
parsedData: {}[];
|
||||||
parsedData2: {}[];
|
parsedData2: {}[];
|
||||||
// waterfall: WaterfallProps[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FlowReport = ({
|
export const FlowReport = ({
|
||||||
isTime,
|
isTime,
|
||||||
isType,
|
isType,
|
||||||
// isGraph,
|
|
||||||
parsedData,
|
parsedData,
|
||||||
parsedData2,
|
parsedData2,
|
||||||
}: // waterfall,
|
}: Props) => {
|
||||||
Props) => {
|
|
||||||
const { theme, currency, displayValues } = useConfigState();
|
const { theme, currency, displayValues } = useConfigState();
|
||||||
const priceContext = usePriceState();
|
const priceContext = usePriceState();
|
||||||
const format = getPrice(currency, displayValues, priceContext);
|
const format = getPrice(currency, displayValues, priceContext);
|
||||||
|
@ -55,13 +37,6 @@ Props) => {
|
||||||
barWidth = 3;
|
barWidth = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getLabelString = (value: number) => {
|
|
||||||
if (isType === 'amount') {
|
|
||||||
return numeral(value).format('0,0');
|
|
||||||
}
|
|
||||||
return format({ amount: value });
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VictoryChart
|
<VictoryChart
|
||||||
height={100}
|
height={100}
|
||||||
|
@ -72,12 +47,6 @@ Props) => {
|
||||||
right: 50,
|
right: 50,
|
||||||
bottom: 10,
|
bottom: 10,
|
||||||
}}
|
}}
|
||||||
containerComponent={
|
|
||||||
<VictoryVoronoiContainer
|
|
||||||
voronoiDimension="x"
|
|
||||||
labels={({ datum }) => `${getLabelString(datum[isType])}`}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<VictoryAxis
|
<VictoryAxis
|
||||||
domain={[0, domain]}
|
domain={[0, domain]}
|
||||||
|
@ -96,7 +65,9 @@ Props) => {
|
||||||
grid: { stroke: chartGridColor[theme] },
|
grid: { stroke: chartGridColor[theme] },
|
||||||
axis: { stroke: 'transparent' },
|
axis: { stroke: 'transparent' },
|
||||||
}}
|
}}
|
||||||
tickFormat={a => (isType === 'tokens' ? format({ amount: a }) : a)}
|
tickFormat={a =>
|
||||||
|
isType === 'tokens' ? format({ amount: a, breakNumber: true }) : a
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<VictoryGroup offset={barWidth}>
|
<VictoryGroup offset={barWidth}>
|
||||||
<VictoryBar
|
<VictoryBar
|
||||||
|
@ -127,30 +98,6 @@ Props) => {
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/* {isGraph === 'graph' && (
|
|
||||||
<VictoryBar
|
|
||||||
data={waterfall}
|
|
||||||
x="period"
|
|
||||||
y={isType}
|
|
||||||
y0={beforeMap[isType]}
|
|
||||||
style={{
|
|
||||||
data: {
|
|
||||||
fill: ({ data, index }: any) => {
|
|
||||||
console.log(data, index);
|
|
||||||
return data[index][isType] -
|
|
||||||
data[index][beforeMap[isType]] >
|
|
||||||
0
|
|
||||||
? chartColors.green
|
|
||||||
: 'red';
|
|
||||||
},
|
|
||||||
width: barWidth,
|
|
||||||
},
|
|
||||||
labels: {
|
|
||||||
fontSize: '12px',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)} */}
|
|
||||||
</VictoryGroup>
|
</VictoryGroup>
|
||||||
</VictoryChart>
|
</VictoryChart>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { CardTitle, ColorButton } from '../../../../components/generic/Styled';
|
import { CardTitle, SmallButton } from '../../../../components/generic/Styled';
|
||||||
|
|
||||||
interface ButtonProps {
|
interface ButtonProps {
|
||||||
isTime: string;
|
isTime: string;
|
||||||
|
@ -44,12 +44,12 @@ ButtonProps) => {
|
||||||
index: number
|
index: number
|
||||||
) => {
|
) => {
|
||||||
return (
|
return (
|
||||||
<ColorButton
|
<SmallButton
|
||||||
color={buttonBorder}
|
color={buttonBorder}
|
||||||
onClick={() => setFn(toggleButtons(array, index))}
|
onClick={() => setFn(toggleButtons(array, index))}
|
||||||
>
|
>
|
||||||
{mapped[index]}
|
{mapped[index]}
|
||||||
</ColorButton>
|
</SmallButton>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import { GitCommit, ArrowDown, ArrowUp } from 'react-feather';
|
import { GitCommit, ArrowDown, ArrowUp } from 'react-feather';
|
||||||
import styled from 'styled-components';
|
import styled, { css } from 'styled-components';
|
||||||
import { useAccountState } from 'src/context/AccountContext';
|
import { useAccountState } from 'src/context/AccountContext';
|
||||||
import { useGetForwardChannelsReportQuery } from 'src/graphql/queries/__generated__/getForwardChannelsReport.generated';
|
import { useGetForwardChannelsReportQuery } from 'src/graphql/queries/__generated__/getForwardChannelsReport.generated';
|
||||||
import { getErrorContent } from '../../../../utils/error';
|
import { getErrorContent } from '../../../../utils/error';
|
||||||
import {
|
import {
|
||||||
DarkSubTitle,
|
DarkSubTitle,
|
||||||
ColorButton,
|
SmallButton,
|
||||||
SingleLine,
|
SingleLine,
|
||||||
} from '../../../../components/generic/Styled';
|
} from '../../../../components/generic/Styled';
|
||||||
import { LoadingCard } from '../../../../components/loading/LoadingCard';
|
import { LoadingCard } from '../../../../components/loading/LoadingCard';
|
||||||
|
@ -28,9 +28,19 @@ const ButtonRow = styled.div`
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const TriButton = styled(ColorButton)`
|
type TriButtonProps = {
|
||||||
|
selected: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const TriButton = styled(SmallButton)<TriButtonProps>`
|
||||||
margin: 0;
|
margin: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
|
|
||||||
|
${({ selected }) =>
|
||||||
|
selected &&
|
||||||
|
css`
|
||||||
|
color: white;
|
||||||
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const LeftButton = styled(TriButton)`
|
const LeftButton = styled(TriButton)`
|
||||||
|
|
|
@ -91,7 +91,7 @@ export const LiquidReport = () => {
|
||||||
grid: { stroke: chartGridColor[theme] },
|
grid: { stroke: chartGridColor[theme] },
|
||||||
axis: { stroke: 'transparent' },
|
axis: { stroke: 'transparent' },
|
||||||
}}
|
}}
|
||||||
tickFormat={a => `${format({ amount: a })}`}
|
tickFormat={a => `${format({ amount: a, breakNumber: true })}`}
|
||||||
/>
|
/>
|
||||||
<VictoryBar
|
<VictoryBar
|
||||||
horizontal
|
horizontal
|
||||||
|
|
|
@ -46,7 +46,7 @@ export const Accounts = () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!loading && data?.getNodeInfo && newAccount) {
|
if (!loading && data && data.getNodeInfo && newAccount) {
|
||||||
dispatch({ type: 'changeAccount', changeId: newAccount });
|
dispatch({ type: 'changeAccount', changeId: newAccount });
|
||||||
dispatchStatus({ type: 'connected' });
|
dispatchStatus({ type: 'connected' });
|
||||||
push(appendBasePath('/home'));
|
push(appendBasePath('/home'));
|
||||||
|
|
|
@ -12,10 +12,9 @@ import {
|
||||||
CardWithTitle,
|
CardWithTitle,
|
||||||
SubTitle,
|
SubTitle,
|
||||||
SingleLine,
|
SingleLine,
|
||||||
SimpleButton,
|
|
||||||
Sub4Title,
|
Sub4Title,
|
||||||
} from '../../components/generic/Styled';
|
} from '../../components/generic/Styled';
|
||||||
import { textColor, fontColors } from '../../styles/Themes';
|
import { fontColors } from '../../styles/Themes';
|
||||||
import { ColorButton } from '../../components/buttons/colorButton/ColorButton';
|
import { ColorButton } from '../../components/buttons/colorButton/ColorButton';
|
||||||
import {
|
import {
|
||||||
MultiButton,
|
MultiButton,
|
||||||
|
@ -40,14 +39,6 @@ export const SettingsLine = styled(SingleLine)`
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const SettingsButton = styled(SimpleButton)`
|
|
||||||
padding: 10px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border: 1px solid ${textColor};
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const CheckboxText = styled.div`
|
export const CheckboxText = styled.div`
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: ${fontColors.grey7};
|
color: ${fontColors.grey7};
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { SingleLine, SimpleButton } from '../../components/generic/Styled';
|
import { SingleLine } from '../../components/generic/Styled';
|
||||||
import { textColor } from '../../styles/Themes';
|
|
||||||
import { InterfaceSettings } from './Interface';
|
import { InterfaceSettings } from './Interface';
|
||||||
import { AccountSettings } from './Account';
|
import { AccountSettings } from './Account';
|
||||||
import { DangerView } from './Danger';
|
import { DangerView } from './Danger';
|
||||||
|
@ -17,14 +16,6 @@ export const SettingsLine = styled(SingleLine)`
|
||||||
margin: 8px 0;
|
margin: 8px 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const SettingsButton = styled(SimpleButton)`
|
|
||||||
padding: 8px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border: 1px solid ${textColor};
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SettingsView = () => {
|
const SettingsView = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
Loading…
Add table
Reference in a new issue