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:
Anthony Potdevin 2020-05-23 18:45:28 +02:00 committed by GitHub
parent 414c20f053
commit c2d2dc8e36
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 508 additions and 371 deletions

View file

@ -39,8 +39,10 @@ module.exports = {
],
rules: {
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'import/no-unresolved': 'off',
'import/order': 2,
'no-unused-vars': 2,
camelcase: 'off',
'@typescript-eslint/camelcase': 'off',
'react/prop-types': 'off',

View file

@ -1,6 +1,12 @@
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 { toWithError } from 'api/helpers/async';
import { logger } from '../../../helpers/logger';
import { requestLimiter } from '../../../helpers/rateLimiter';
import {
@ -11,36 +17,6 @@ import {
import { defaultParams } from '../../../helpers/defaultProps';
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 = {
type: new GraphQLList(ChannelType),
args: {
@ -53,37 +29,83 @@ export const getChannels = {
const auth = getCorrectAuth(params.auth, context);
const lnd = getAuthLnd(auth);
try {
const channelList: ChannelListProps = await getLnChannels({
const [walletInfo, walletError] = await toWithError(getWalletInfo({ lnd }));
const publicKey = walletInfo?.public_key;
walletError &&
logger.debug('Error getting wallet info in getChannels: %o', walletError);
const [channelList, channelListError] = await toWithError(
getLnChannels({
lnd,
is_active: params.active,
});
})
);
const getChannelList = () =>
Promise.all(
channelList.channels.map(async channel => {
const nodeInfo = await getNode({
if (channelListError) {
logger.error('Error getting channels: %o', channelListError);
throw new Error(getErrorMsg(channelListError));
}
const getChannelList = () =>
Promise.all(
channelList.channels.map(async channel => {
const [nodeInfo, nodeError] = await toWithError(
getNode({
lnd,
is_omitting_channels: true,
public_key: channel.partner_public_key,
});
})
);
return {
...channel,
time_offline: Math.round((channel.time_offline || 0) / 1000),
time_online: Math.round((channel.time_online || 0) / 1000),
partner_node_info: {
...nodeInfo,
},
};
})
);
const [channelInfo, channelError] = await toWithError(
getChannel({
lnd,
id: channel.id,
})
);
const channels = await getChannelList();
return channels;
} catch (error) {
logger.error('Error getting channels: %o', error);
throw new Error(getErrorMsg(error));
}
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 {
...channel,
time_offline: Math.round((channel.time_offline || 0) / 1000),
time_online: Math.round((channel.time_online || 0) / 1000),
partner_node_info,
};
})
);
const channels = await getChannelList();
return channels;
},
};

View file

@ -84,6 +84,9 @@ export const PartnerNodeType = new GraphQLObjectType({
channel_count: { type: GraphQLInt },
color: { type: GraphQLString },
updated_at: { type: GraphQLString },
base_fee: { type: GraphQLInt },
fee_rate: { type: GraphQLInt },
cltv_delta: { type: GraphQLInt },
};
},
});

View file

@ -12,7 +12,7 @@
"start:two": "cross-env NODE_OPTIONS='--insecure-http-parser' next start -p 3001",
"start:compatible": "next start",
"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}",
"release": "standard-version",
"release:push": "standard-version && git push --follow-tags origin master",

View file

@ -161,7 +161,7 @@ const BalanceView = () => {
<SingleLine>
<SubTitle>Channel Balancing</SubTitle>
</SingleLine>
<Card>
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
{renderOutgoing()}
{renderIncoming()}
<ResponsiveLine>

View file

@ -1,18 +1,31 @@
import React, { useState, useEffect } from 'react';
import { useAccountState } from 'src/context/AccountContext';
import { useGetChannelAmountInfoQuery } from 'src/graphql/queries/__generated__/getNodeInfo.generated';
import styled from 'styled-components';
import { Channels } from '../src/views/channels/channels/Channels';
import { PendingChannels } from '../src/views/channels/pendingChannels/PendingChannels';
import { ClosedChannels } from '../src/views/channels/closedChannels/ClosedChannels';
import {
CardWithTitle,
SubTitle,
CardTitle,
SingleLine,
ColorButton,
SmallButton,
} from '../src/components/generic/Styled';
import { useConfigState } from '../src/context/ConfigContext';
import { textColorMap } from '../src/styles/Themes';
import { mediaWidths } 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 [view, setView] = useState<number>(1);
@ -22,7 +35,6 @@ const ChannelView = () => {
closed: 0,
});
const { theme } = useConfigState();
const { auth } = useAccountState();
const { data } = useGetChannelAmountInfoQuery({
@ -31,7 +43,7 @@ const ChannelView = () => {
});
useEffect(() => {
if (data?.getNodeInfo) {
if (data && data.getNodeInfo) {
const {
active_channels_count,
closed_channels_count,
@ -70,20 +82,20 @@ const ChannelView = () => {
return (
<CardWithTitle>
<CardTitle>
<ChannelsCardTitle>
<SubTitle>{getTitle()}</SubTitle>
<SingleLine>
<ColorButton color={textColorMap[theme]} onClick={() => setView(1)}>
<ButtonRow>
<SmallButton onClick={() => setView(1)}>
{`Open (${amounts.active})`}
</ColorButton>
<ColorButton color={textColorMap[theme]} onClick={() => setView(2)}>
</SmallButton>
<SmallButton onClick={() => setView(2)}>
{`Pending (${amounts.pending})`}
</ColorButton>
<ColorButton color={textColorMap[theme]} onClick={() => setView(3)}>
</SmallButton>
<SmallButton onClick={() => setView(3)}>
{`Closed (${amounts.closed})`}
</ColorButton>
</SingleLine>
</CardTitle>
</SmallButton>
</ButtonRow>
</ChannelsCardTitle>
{getView()}
</CardWithTitle>
);

View file

@ -110,7 +110,7 @@ const FeesView = () => {
</AdminSwitch>
<CardWithTitle>
<SubTitle>Channel Fees</SubTitle>
<Card>
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
{data.getChannelFees.map((channel: any, index: number) => (
<FeeCard
channelInfo={channel}

View file

@ -7,14 +7,12 @@ import {
Card,
CardWithTitle,
CardTitle,
ColorButton,
SmallButton,
SingleLine,
} from '../src/components/generic/Styled';
import { getErrorContent } from '../src/utils/error';
import { LoadingCard } from '../src/components/loading/LoadingCard';
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';
const timeMap: { [key: string]: string } = {
@ -28,7 +26,6 @@ const ForwardsView = () => {
const [time, setTime] = useState('week');
const [indexOpen, setIndexOpen] = useState(0);
const { theme } = useConfigState();
const { auth } = useAccountState();
const { loading, data } = useGetForwardsQuery({
@ -42,17 +39,13 @@ const ForwardsView = () => {
}
const renderButton = (selectedTime: string, title: string) => (
<ColorButton
color={textColorMap[theme]}
onClick={() => setTime(selectedTime)}
selected={time === selectedTime}
>
{title}
</ColorButton>
<SmallButton onClick={() => setTime(selectedTime)}>{title}</SmallButton>
);
const renderNoForwards = () => (
<p>{`Your node has not forwarded any payments ${timeMap[time]}.`}</p>
<Card>
<p>{`Your node has not forwarded any payments ${timeMap[time]}.`}</p>
</Card>
);
return (
@ -68,8 +61,8 @@ const ForwardsView = () => {
{renderButton('threeMonths', '3M')}
</SingleLine>
</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) => (
<ForwardCard
forward={forward}

View file

@ -28,7 +28,7 @@ const PeersView = () => {
<AddPeer />
<CardWithTitle>
<SubTitle>Peers</SubTitle>
<Card>
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
{data.getPeers.map((peer: any, index: number) => (
<PeersCard
peer={peer}

View file

@ -1,8 +1,7 @@
import React from 'react';
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 { textColor } from '../src/styles/Themes';
import { AccountSettings } from '../src/views/settings/Account';
import { DangerView } from '../src/views/settings/Danger';
import { CurrentSettings } from '../src/views/settings/Current';
@ -19,14 +18,6 @@ export const SettingsLine = styled(SingleLine)`
margin: 8px 0;
`;
export const SettingsButton = styled(SimpleButton)`
padding: 8px;
&:hover {
border: 1px solid ${textColor};
}
`;
const SettingsView = () => {
return (
<>

View file

@ -99,7 +99,7 @@ const TradingView = () => {
<Card bottom={'16px'}>
<OfferFilters offerFilters={queryObject} />
</Card>
<Card bottom={'8px'}>
<Card bottom={'8px'} mobileCardPadding={'0'} mobileNoBackground={true}>
{amountOfOffers <= 0 && <DarkSubTitle>No Offers Found</DarkSubTitle>}
{data.getOffers.map((offer: any, index: number) => (
<OfferCard

View file

@ -47,7 +47,7 @@ const TransactionsView = () => {
<FlowBox />
<CardWithTitle>
<SubTitle>Transactions</SubTitle>
<Card bottom={'8px'}>
<Card bottom={'8px'} mobileCardPadding={'0'} mobileNoBackground={true}>
{resumeList.map((entry: any, index: number) => {
if (entry.type === 'invoice') {
return (

View file

@ -25,7 +25,7 @@ export const AuthSSOCheck = ({ cookieParam }: AuthCheckProps) => {
});
React.useEffect(() => {
if (cookieParam && !loading && data?.getAuthToken && !ssoSaved) {
if (cookieParam && !loading && data && data.getAuthToken && !ssoSaved) {
Cookies.set('SSOAuth', data.getAuthToken, {
sameSite: 'strict',
});

View file

@ -40,7 +40,7 @@ export const ServerAccounts = () => {
}, [dispatch]);
React.useEffect(() => {
if (!loading && data?.getServerAccounts) {
if (!loading && data && data.getServerAccounts) {
const accountsToAdd = data.getServerAccounts.map(a => {
const type = a?.id === SSO_ACCOUNT ? SSO_ACCOUNT : SERVER_ACCOUNT;
return {

View file

@ -42,7 +42,7 @@ export const ChatInit = () => {
}, [dispatch, getMessages, account]);
React.useEffect(() => {
if (!initLoading && !initError && initData?.getMessages) {
if (!initLoading && !initError && initData && initData.getMessages) {
const { messages } = initData.getMessages;
if (messages.length <= 0) {

View file

@ -1,11 +1,10 @@
import styled from 'styled-components';
import {
progressBackground,
progressFirst,
progressSecond,
mediaWidths,
cardColor,
cardBorderColor,
chartColors,
} from '../../styles/Themes';
export const Progress = styled.div`
@ -20,13 +19,18 @@ interface ProgressBar {
export const ProgressBar = styled.div<ProgressBar>`
height: 10px;
background-image: linear-gradient(
to bottom,
rgba(255, 255, 255, 0.3),
rgba(0, 0, 0, 0.05)
);
background-color: ${({ order }) =>
order === 2 ? progressFirst : progressSecond};
background-color: ${({ order }) => {
switch (order) {
case 1:
return chartColors.lightblue;
case 2:
return chartColors.green;
case 3:
return chartColors.orange;
default:
return chartColors.purple;
}
}};
width: ${({ percent }) => `${percent}%`};
`;
@ -47,8 +51,8 @@ export const NodeTitle = styled.div`
export const StatusLine = styled.div`
width: 100%;
position: relative;
right: -8px;
top: -8px;
right: -12px;
top: -12px;
display: flex;
justify-content: flex-end;
margin: 0 0 -8px 0;

View file

@ -7,11 +7,13 @@ import {
smallLinkColor,
unSelectedNavButton,
textColor,
buttonBorderColor,
chartLinkColor,
inverseTextColor,
separationColor,
mediaWidths,
colorButtonBackground,
colorButtonBorder,
hoverTextColor,
} from '../../styles/Themes';
export const CardWithTitle = styled.div`
@ -29,6 +31,7 @@ export interface CardProps {
bottom?: string;
cardPadding?: string;
mobileCardPadding?: string;
mobileNoBackground?: boolean;
}
export const Card = styled.div<CardProps>`
@ -41,6 +44,13 @@ export const Card = styled.div<CardProps>`
width: 100%;
@media (${mediaWidths.mobile}) {
${({ mobileNoBackground }) =>
mobileNoBackground &&
css`
background: unset;
border: none;
box-shadow: none;
`}
${({ cardPadding, mobileCardPadding }) =>
mobileCardPadding
? css`
@ -70,6 +80,7 @@ interface SubCardProps {
color?: string;
padding?: string;
withMargin?: string;
noCard?: boolean;
}
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 {
fontSize?: string;
withMargin?: string;
@ -178,17 +168,24 @@ export const DarkSubTitle = styled.div<DarkProps>`
margin: ${({ withMargin }) => (withMargin ? withMargin : '0')};
`;
interface ColorProps {
color: string;
selected?: boolean;
}
export const ColorButton = styled(SimpleButton)<ColorProps>`
color: ${({ selected }) => (selected ? textColor : chartLinkColor)};
border: ${({ selected, color }) => (selected ? `1px solid ${color}` : '')};
export const SmallButton = styled.button`
cursor: pointer;
outline: none;
padding: 5px;
margin: 5px;
text-decoration: none;
border: none;
display: flex;
align-items: center;
justify-content: center;
border-radius: 5px;
white-space: nowrap;
color: ${chartLinkColor};
background-color: ${colorButtonBackground};
&:hover {
border: 1px solid ${({ color }: ColorProps) => color};
color: ${textColor};
color: ${hoverTextColor};
background-color: ${colorButtonBorder};
}
`;

View file

@ -9,11 +9,19 @@ import { X } from 'react-feather';
import { SmallLink, DarkSubTitle, OverflowText, SingleLine } from './Styled';
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) => {
const link = `https://www.blockchain.com/btc/tx/${transaction}`;
return (
<SmallLink href={link} target="_blank">
{transaction}
{shorten(transaction)}
</SmallLink>
);
};
@ -22,7 +30,7 @@ export const getNodeLink = (publicKey: string) => {
const link = `https://1ml.com/node/${publicKey}`;
return (
<SmallLink href={link} target="_blank">
{publicKey}
{shorten(publicKey)}
</SmallLink>
);
};

View file

@ -27,7 +27,7 @@ export const RemovePeerModal = ({
peerAlias,
}: RemovePeerProps) => {
const [removePeer, { loading }] = useRemovePeerMutation({
onCompleted: data => {
onCompleted: () => {
toast.success('Peer Removed');
},
onError: error => {

View file

@ -3,7 +3,7 @@ import { useRouter } from 'next/router';
import { toast } from 'react-toastify';
import { useAccountState } from 'src/context/AccountContext';
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';
export const StatusCheck = () => {
@ -11,10 +11,8 @@ export const StatusCheck = () => {
const { push } = useRouter();
const { account, auth } = useAccountState();
const { connected } = useStatusState();
const { data, loading, error, stopPolling } = useGetNodeInfoQuery({
skip: !auth || !connected,
skip: !auth,
fetchPolicy: 'network-only',
variables: { auth },
pollInterval: 10000,

View file

@ -17,6 +17,7 @@ type State = {
hideNonVerified: boolean;
maxFee: number;
chatPollingSpeed: number;
channelBarType: 'normal' | 'partner';
};
type ConfigInitProps = {
@ -36,6 +37,7 @@ type ActionType = {
hideNonVerified?: boolean;
maxFee?: number;
chatPollingSpeed?: number;
channelBarType?: 'normal' | 'partner';
};
type Dispatch = (action: ActionType) => void;
@ -63,6 +65,7 @@ const initialState: State = {
hideNonVerified: false,
maxFee: 20,
chatPollingSpeed: 1000,
channelBarType: 'normal',
};
const stateReducer = (state: State, action: ActionType): State => {

View file

@ -40,7 +40,14 @@ export type GetChannelsQuery = { __typename?: 'Query' } & {
partner_node_info?: Types.Maybe<
{ __typename?: 'partnerNodeType' } & Pick<
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
color
updated_at
base_fee
fee_rate
cltv_delta
}
}
}

View file

@ -31,6 +31,9 @@ export const GET_CHANNELS = gql`
channel_count
color
updated_at
base_fee
fee_rate
cltv_delta
}
}
}

View file

@ -261,6 +261,9 @@ export type PartnerNodeType = {
channel_count?: Maybe<Scalars['Int']>;
color?: 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 = {

View file

@ -61,7 +61,7 @@ export const Header = () => {
<Link to={connected ? '/home' : '/'} underline={'transparent'}>
<HeaderTitle withPadding={!connected}>
<IconPadding>
<Cpu color={'white'} />
<Cpu color={'white'} size={18} />
</IconPadding>
ThunderHub
</HeaderTitle>

View file

@ -35,7 +35,9 @@ export const getValue = ({
if (currency === 'btc') {
if (!value) return '₿0.0';
const amountInBtc = value / 100000000;
return `${amountInBtc}`;
const rounded = Math.round(amountInBtc * 10000) / 10000;
return `${rounded}`;
}
if (currency === 'sat') {
const breakAmount = breakNumber
@ -107,9 +109,9 @@ export const formatSeconds = (seconds: number): string | null => {
const m = Math.floor((seconds % 3600) / 60);
const s = Math.floor(seconds % 60);
const dDisplay = d > 0 ? d + (d == 1 ? ' day, ' : ' days, ') : '';
const hDisplay = h > 0 ? h + (h == 1 ? ' hour, ' : ' hours, ') : '';
const mDisplay = m > 0 ? m + (m == 1 ? ' minute, ' : ' minutes, ') : '';
const sDisplay = s > 0 ? s + (s == 1 ? ' second' : ' seconds') : '';
const dDisplay = d > 0 ? `${d}d ` : '';
const hDisplay = h > 0 ? `${h}h ` : '';
const mDisplay = m > 0 ? `${m}m ` : '';
const sDisplay = s > 0 ? `${s}s` : '';
return dDisplay + hDisplay + mDisplay + sDisplay;
};

View file

@ -28,7 +28,7 @@ export const ChainTransactions = () => {
return (
<CardWithTitle>
<SubTitle>Chain Transactions</SubTitle>
<Card>
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
{data.getChainTransactions.map((transaction: any, index: number) => (
<TransactionsCard
transaction={transaction}

View file

@ -28,7 +28,7 @@ export const ChainUtxos = () => {
return (
<CardWithTitle>
<SubTitle>Unspent Utxos</SubTitle>
<Card>
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
{data.getUtxos.map((utxo: any, index: number) => (
<UtxoCard
utxo={utxo}

View file

@ -2,11 +2,11 @@ import React, { useState } from 'react';
import ReactTooltip from 'react-tooltip';
import styled from 'styled-components';
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 {
Progress,
ProgressBar,
NodeTitle,
StatusLine,
MainInfo,
} from '../../../components/generic/CardGeneric';
@ -16,10 +16,12 @@ import {
Sub4Title,
RightAlign,
ResponsiveLine,
ResponsiveSingle,
ResponsiveCol,
DarkSubTitle,
} from '../../../components/generic/Styled';
import { useConfigState } from '../../../context/ConfigContext';
import {
useConfigState,
useConfigDispatch,
} from '../../../context/ConfigContext';
import {
getStatusDot,
getTooltipType,
@ -37,23 +39,69 @@ import { getPrice } from '../../../components/price/Price';
import { usePriceState } from '../../../context/PriceContext';
const IconPadding = styled.div`
margin-left: 16px;
margin-right: 8px;
display: flex;
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) => {
return status ? <ArrowDown size={18} /> : <ArrowUp size={18} />;
return status ? <ArrowDown size={14} /> : <ArrowUp size={14} />;
};
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 {
channelInfo: any;
channelInfo: ChannelType;
index: number;
setIndexOpen: (index: number) => void;
indexOpen: number;
biggest: number;
biggestPartner: number;
mostChannels: number;
biggestBaseFee: number;
biggestRateFee: number;
}
export const ChannelCard = ({
@ -61,7 +109,14 @@ export const ChannelCard = ({
index,
setIndexOpen,
indexOpen,
biggest,
biggestPartner,
mostChannels,
biggestBaseFee,
biggestRateFee,
}: ChannelCardProps) => {
const { channelBarType } = useConfigState();
const dispatch = useConfigDispatch();
const [modalOpen, setModalOpen] = useState(false);
const { theme, currency, displayValues } = useConfigState();
@ -98,10 +153,12 @@ export const ChannelCard = ({
const {
alias,
capacity: partnerNodeCapacity,
capacity: partnerNodeCapacity = 0,
channel_count,
color: nodeColor,
updated_at,
base_fee,
fee_rate,
cltv_delta,
} = partner_node_info;
const formatBalance = format({ amount: capacity });
@ -123,10 +180,20 @@ export const ChannelCard = ({
}
};
const handleBarClick = () => {
dispatch({
type: 'change',
channelBarType: channelBarType === 'normal' ? 'partner' : 'normal',
});
};
const renderDetails = () => {
return (
<>
<Separation />
{renderLine('Status:', is_active ? 'Active' : 'Not Active')}
{renderLine('Is Opening:', is_opening ? 'True' : 'False')}
{renderLine('Is Closing:', is_closing ? 'True' : 'False')}
{renderLine(
'Balancedness:',
getPercent(local_balance, remote_balance) / 100
@ -154,6 +221,9 @@ export const ChannelCard = ({
'Last Update:',
`${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>
<Separation />
<RightAlign>
@ -170,37 +240,86 @@ export const ChannelCard = ({
);
};
const renderBars = () => {
switch (channelBarType) {
case 'partner':
return (
<>
<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 color={nodeColor} key={`${index}-${id}`}>
<MainInfo onClick={() => handleClick()}>
<StatusLine>
{getStatusDot(is_active, 'active')}
{getStatusDot(is_opening, 'opening')}
{getStatusDot(is_closing, 'closing')}
</StatusLine>
<ResponsiveLine>
<NodeTitle style={{ flexGrow: 2 }}>
<SubCard key={`${index}-${id}`} noCard={true}>
<StatusLine>
{getStatusDot(is_active, 'active')}
{getStatusDot(is_opening, 'opening')}
{getStatusDot(is_closing, 'closing')}
</StatusLine>
<ResponsiveLine>
<NodeTitle style={{ flexGrow: 2 }}>
<MainInfo onClick={() => handleClick()}>
{alias || partner_public_key?.substring(0, 6)}
</NodeTitle>
<ResponsiveSingle>
{formatBalance}
<IconPadding>
{getPrivate(is_private)}
{getSymbol(is_partner_initiated)}
</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>
</MainInfo>
<DarkSubTitle>{formatBalance}</DarkSubTitle>
</MainInfo>
</NodeTitle>
<BarSide>
<StatsColumn
data-tip
data-for={`node_balance_tip_${index}`}
onClick={handleBarClick}
>
{renderBars()}
</StatsColumn>
</BarSide>
<IconPadding>
{getPrivate(is_private)}
{getSymbol(is_partner_initiated)}
</IconPadding>
</ResponsiveLine>
{index === indexOpen && renderDetails()}
<ReactTooltip
id={`node_balance_tip_${index}`}
@ -208,17 +327,7 @@ export const ChannelCard = ({
place={'bottom'}
type={tooltipType}
>
<div>{`Local Balance: ${formatLocal}`}</div>
<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>
{renderBarsInfo()}
</ReactTooltip>
<Modal isOpen={modalOpen} closeCallback={() => setModalOpen(false)}>
<CloseChannel

View file

@ -23,15 +23,59 @@ export const Channels = () => {
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 (
<Card>
{data.getChannels.map((channel: any, index: number) => (
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
{data.getChannels.map((channel, index: number) => (
<ChannelCard
channelInfo={channel}
index={index + 1}
setIndexOpen={setIndexOpen}
indexOpen={indexOpen}
key={`${index}-${channel.id}`}
biggest={biggest}
biggestPartner={biggestPartner}
mostChannels={mostChannels}
biggestBaseFee={biggestBaseFee * 2}
biggestRateFee={biggestRateFee}
/>
))}
</Card>

View file

@ -1,5 +1,6 @@
import React from 'react';
import styled from 'styled-components';
import { ClosedChannelType } from 'src/graphql/types';
import { NodeTitle, MainInfo } from '../../../components/generic/CardGeneric';
import {
SubCard,
@ -20,7 +21,7 @@ const Padding = styled.div`
`;
interface PendingCardProps {
channelInfo: any;
channelInfo: ClosedChannelType;
index: number;
setIndexOpen: (index: number) => void;
indexOpen: number;

View file

@ -23,8 +23,8 @@ export const ClosedChannels = () => {
}
return (
<Card>
{data.getClosedChannels.map((channel: any, index: number) => (
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
{data.getClosedChannels.map((channel, index: number) => (
<ClosedCard
channelInfo={channel}
key={index}

View file

@ -1,5 +1,6 @@
import React from 'react';
import ReactTooltip from 'react-tooltip';
import { PendingChannelType } from 'src/graphql/types';
import { getPercent } from '../../../utils/helpers';
import {
Progress,
@ -29,32 +30,8 @@ import {
import { getPrice } from '../../../components/price/Price';
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 {
channelInfo: ChannelProps;
channelInfo: PendingChannelType;
index: number;
setIndexOpen: (index: number) => void;
indexOpen: number;
@ -93,7 +70,7 @@ export const PendingCard = ({
const {
alias,
capacity,
channelCount,
channel_count,
color: nodeColor,
updated_at,
} = partner_node_info;
@ -132,7 +109,7 @@ export const PendingCard = ({
{renderLine('Remote Reserve:', remote_reserve)}
<Sub4Title>Partner Node Info</Sub4Title>
{renderLine('Node Capacity:', capacity)}
{renderLine('Channels:', channelCount)}
{renderLine('Channels:', channel_count)}
{renderLine(
'Last Update:',
`${getDateDif(updated_at)} ago (${getFormatDate(updated_at)})`

View file

@ -23,8 +23,8 @@ export const PendingChannels = () => {
}
return (
<Card>
{data.getPendingChannels.map((channel: any, index: number) => (
<Card mobileCardPadding={'0'} mobileNoBackground={true}>
{data.getPendingChannels.map((channel, index: number) => (
<PendingCard
channelInfo={channel}
key={index}

View file

@ -39,7 +39,7 @@ const SendButton = ({ amount }: SendButtonProps) => {
});
React.useEffect(() => {
if (!loading && data?.sendMessage >= 0) {
if (!loading && data && data.sendMessage >= 0) {
dispatch({
type: 'newChat',
newChat: {

View file

@ -35,7 +35,7 @@ export const ChatInput = ({
);
React.useEffect(() => {
if (!loading && data?.sendMessage >= 0) {
if (!loading && data && data.sendMessage >= 0) {
setMessage('');
dispatch({
type: 'newChat',

View file

@ -52,7 +52,7 @@ export const ContactCard = ({
}, [contact, sender, alias, contactSender, getInfo, setUser, user]);
React.useEffect(() => {
if (!loading && data?.getNode) {
if (!loading && data && data.getNode) {
const { alias } = data.getNode;
const name =
alias && alias !== '' ? alias : contactSender.substring(0, 6);

View file

@ -1,13 +1,13 @@
import React, { useState } from 'react';
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 {
Card,
CardWithTitle,
SubTitle,
Separation,
DarkSubTitle,
ColorButton,
ResponsiveLine,
} from '../../../components/generic/Styled';
import { LoadingCard } from '../../../components/loading/LoadingCard';
@ -35,8 +35,14 @@ const Tile = styled.div`
}
`;
const ButtonRow = styled.div`
const AccountButtonWrapper = styled.div`
display: flex;
flex-direction: column;
@media (${mediaWidths.mobile}) {
flex-direction: row;
width: 100%;
}
`;
const sectionColor = '#FFD300';
@ -118,14 +124,24 @@ export const AccountInfo = () => {
);
const renderButtons = (send: string, receive: string) => (
<>
<ColorButton color={sectionColor} onClick={() => setState(send)}>
<ArrowUp size={18} />
<AccountButtonWrapper>
<ColorButton
fullWidth={true}
withMargin={'0 0 2px'}
mobileMargin={'8px 4px 0 0'}
onClick={() => setState(send)}
>
Send
</ColorButton>
<ColorButton color={sectionColor} onClick={() => setState(receive)}>
<ArrowDown size={18} />
<ColorButton
fullWidth={true}
withMargin={'2px 0 0'}
mobileMargin={'8px 0 0 4px'}
onClick={() => setState(receive)}
>
Receive
</ColorButton>
</>
</AccountButtonWrapper>
);
const renderLnAccount = () => (
@ -137,14 +153,10 @@ export const AccountInfo = () => {
</Tile>
{renderBalances(formatCCB, formatPCB)}
<AdminSwitch>
<ButtonRow>
{showLn && showChain && renderButtons('send_ln', 'receive_ln')}
{showLn && !showChain && (
<ColorButton color={sectionColor} onClick={() => setState('none')}>
<X size={18} />
</ColorButton>
)}
</ButtonRow>
{showLn && showChain && renderButtons('send_ln', 'receive_ln')}
{showLn && !showChain && (
<ColorButton onClick={() => setState('none')}>Cancel</ColorButton>
)}
</AdminSwitch>
</ResponsiveLine>
);
@ -158,14 +170,10 @@ export const AccountInfo = () => {
</Tile>
{renderBalances(formatCB, formatPB)}
<AdminSwitch>
<ButtonRow>
{showLn && showChain && renderButtons('send_chain', 'receive_chain')}
{!showLn && showChain && (
<ColorButton color={sectionColor} onClick={() => setState('none')}>
<X size={18} />
</ColorButton>
)}
</ButtonRow>
{showLn && showChain && renderButtons('send_chain', 'receive_chain')}
{!showLn && showChain && (
<ColorButton onClick={() => setState('none')}>Cancel</ColorButton>
)}
</AdminSwitch>
</ResponsiveLine>
);

View file

@ -5,6 +5,7 @@ import styled from 'styled-components';
import CopyToClipboard from 'react-copy-to-clipboard';
import { useAccountState } from 'src/context/AccountContext';
import { useGetCanConnectInfoQuery } from 'src/graphql/queries/__generated__/getNodeInfo.generated';
import { ColorButton } from 'src/components/buttons/colorButton/ColorButton';
import { getErrorContent } from '../../../utils/error';
import { LoadingCard } from '../../../components/loading/LoadingCard';
import {
@ -14,7 +15,6 @@ import {
Card,
SingleLine,
DarkSubTitle,
ColorButton,
} from '../../../components/generic/Styled';
import { mediaWidths } from '../../../styles/Themes';
@ -52,6 +52,14 @@ const TextPadding = styled.span`
margin-left: 5px;
`;
const ButtonRow = styled.div`
display: flex;
@media (${mediaWidths.mobile}) {
width: 100%;
}
`;
const sectionColor = '#fa541c';
export const ConnectCard = () => {
@ -84,13 +92,13 @@ export const ConnectCard = () => {
<DarkSubTitle>Public Key</DarkSubTitle>
<Key>{public_key}</Key>
</Tile>
<SingleLine>
<ButtonRow>
{onionAddress ? (
<CopyToClipboard
text={onionAddress}
onCopy={() => toast.success('Onion Address Copied')}
>
<ColorButton color={sectionColor}>
<ColorButton fullWidth={true} withMargin={'0 4px 0 0'}>
<Copy size={18} />
<TextPadding>Onion</TextPadding>
</ColorButton>
@ -101,12 +109,12 @@ export const ConnectCard = () => {
text={normalAddress}
onCopy={() => toast.success('Public Address Copied')}
>
<ColorButton color={sectionColor}>
<ColorButton fullWidth={true} withMargin={'0 0 0 4px'}>
<Copy size={18} />
</ColorButton>
</CopyToClipboard>
) : null}
</SingleLine>
</ButtonRow>
</Responsive>
</Card>
</CardWithTitle>

View file

@ -6,7 +6,7 @@ import {
SubTitle,
Card,
CardTitle,
ColorButton,
SmallButton,
} from '../../../components/generic/Styled';
import { unSelectedNavButton } from '../../../styles/Themes';
import { AdminSwitch } from '../../../components/adminSwitch/AdminSwitch';
@ -87,9 +87,9 @@ export const QuickActions = () => {
<CardTitle>
<SubTitle>{getTitle()}</SubTitle>
{openCard !== 'none' && (
<ColorButton onClick={() => setOpenCard('none')} color={sectionColor}>
<SmallButton onClick={() => setOpenCard('none')}>
<X size={18} />
</ColorButton>
</SmallButton>
)}
</CardTitle>
{renderContent()}

View file

@ -1,46 +1,28 @@
import React from 'react';
import numeral from 'numeral';
import {
VictoryBar,
VictoryChart,
VictoryAxis,
VictoryVoronoiContainer,
VictoryGroup,
} from 'victory';
import { VictoryBar, VictoryChart, VictoryAxis, VictoryGroup } from 'victory';
import { useConfigState } from '../../../../context/ConfigContext';
import {
chartAxisColor,
chartGridColor,
// chartColors,
flowBarColor,
flowBarColor2,
} from '../../../../styles/Themes';
import { getPrice } from '../../../../components/price/Price';
import { usePriceState } from '../../../../context/PriceContext';
// import { WaterfallProps } from '.';
// const beforeMap = {
// amount: 'amountBefore',
// tokens: 'tokensBefore',
// };
interface Props {
isTime: string;
isType: string;
// isGraph: string;
parsedData: {}[];
parsedData2: {}[];
// waterfall: WaterfallProps[];
}
export const FlowReport = ({
isTime,
isType,
// isGraph,
parsedData,
parsedData2,
}: // waterfall,
Props) => {
}: Props) => {
const { theme, currency, displayValues } = useConfigState();
const priceContext = usePriceState();
const format = getPrice(currency, displayValues, priceContext);
@ -55,13 +37,6 @@ Props) => {
barWidth = 3;
}
const getLabelString = (value: number) => {
if (isType === 'amount') {
return numeral(value).format('0,0');
}
return format({ amount: value });
};
return (
<VictoryChart
height={100}
@ -72,12 +47,6 @@ Props) => {
right: 50,
bottom: 10,
}}
containerComponent={
<VictoryVoronoiContainer
voronoiDimension="x"
labels={({ datum }) => `${getLabelString(datum[isType])}`}
/>
}
>
<VictoryAxis
domain={[0, domain]}
@ -96,7 +65,9 @@ Props) => {
grid: { stroke: chartGridColor[theme] },
axis: { stroke: 'transparent' },
}}
tickFormat={a => (isType === 'tokens' ? format({ amount: a }) : a)}
tickFormat={a =>
isType === 'tokens' ? format({ amount: a, breakNumber: true }) : a
}
/>
<VictoryGroup offset={barWidth}>
<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>
</VictoryChart>
);

View file

@ -1,5 +1,5 @@
import React from 'react';
import { CardTitle, ColorButton } from '../../../../components/generic/Styled';
import { CardTitle, SmallButton } from '../../../../components/generic/Styled';
interface ButtonProps {
isTime: string;
@ -44,12 +44,12 @@ ButtonProps) => {
index: number
) => {
return (
<ColorButton
<SmallButton
color={buttonBorder}
onClick={() => setFn(toggleButtons(array, index))}
>
{mapped[index]}
</ColorButton>
</SmallButton>
);
};

View file

@ -1,13 +1,13 @@
import React, { useState } from 'react';
import { toast } from 'react-toastify';
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 { useGetForwardChannelsReportQuery } from 'src/graphql/queries/__generated__/getForwardChannelsReport.generated';
import { getErrorContent } from '../../../../utils/error';
import {
DarkSubTitle,
ColorButton,
SmallButton,
SingleLine,
} from '../../../../components/generic/Styled';
import { LoadingCard } from '../../../../components/loading/LoadingCard';
@ -28,9 +28,19 @@ const ButtonRow = styled.div`
margin-bottom: 5px;
`;
const TriButton = styled(ColorButton)`
type TriButtonProps = {
selected: boolean;
};
const TriButton = styled(SmallButton)<TriButtonProps>`
margin: 0;
border-radius: 0;
${({ selected }) =>
selected &&
css`
color: white;
`}
`;
const LeftButton = styled(TriButton)`

View file

@ -91,7 +91,7 @@ export const LiquidReport = () => {
grid: { stroke: chartGridColor[theme] },
axis: { stroke: 'transparent' },
}}
tickFormat={a => `${format({ amount: a })}`}
tickFormat={a => `${format({ amount: a, breakNumber: true })}`}
/>
<VictoryBar
horizontal

View file

@ -46,7 +46,7 @@ export const Accounts = () => {
});
React.useEffect(() => {
if (!loading && data?.getNodeInfo && newAccount) {
if (!loading && data && data.getNodeInfo && newAccount) {
dispatch({ type: 'changeAccount', changeId: newAccount });
dispatchStatus({ type: 'connected' });
push(appendBasePath('/home'));

View file

@ -12,10 +12,9 @@ import {
CardWithTitle,
SubTitle,
SingleLine,
SimpleButton,
Sub4Title,
} from '../../components/generic/Styled';
import { textColor, fontColors } from '../../styles/Themes';
import { fontColors } from '../../styles/Themes';
import { ColorButton } from '../../components/buttons/colorButton/ColorButton';
import {
MultiButton,
@ -40,14 +39,6 @@ export const SettingsLine = styled(SingleLine)`
margin: 10px 0;
`;
export const SettingsButton = styled(SimpleButton)`
padding: 10px;
&:hover {
border: 1px solid ${textColor};
}
`;
export const CheckboxText = styled.div`
font-size: 13px;
color: ${fontColors.grey7};

View file

@ -1,7 +1,6 @@
import React from 'react';
import styled from 'styled-components';
import { SingleLine, SimpleButton } from '../../components/generic/Styled';
import { textColor } from '../../styles/Themes';
import { SingleLine } from '../../components/generic/Styled';
import { InterfaceSettings } from './Interface';
import { AccountSettings } from './Account';
import { DangerView } from './Danger';
@ -17,14 +16,6 @@ export const SettingsLine = styled(SingleLine)`
margin: 8px 0;
`;
export const SettingsButton = styled(SimpleButton)`
padding: 8px;
&:hover {
border: 1px solid ${textColor};
}
`;
const SettingsView = () => {
return (
<>