feat: more views

This commit is contained in:
AP 2019-11-22 08:35:01 +01:00
parent 237b9bba24
commit e89f5bf2b1
18 changed files with 418 additions and 85 deletions

View file

@ -15,6 +15,7 @@
"@types/styled-components": "^4.4.0",
"@types/styled-theming": "^2.2.2",
"apollo-boost": "^0.4.4",
"date-fns": "^2.8.0",
"graphql": "^14.5.8",
"lodash.merge": "^4.6.2",
"node-sass": "^4.13.0",

View file

@ -81,6 +81,8 @@ export const StatusDot = styled.div`
export const DetailLine = styled.div`
font-size: 14px;
word-wrap: break-word;
display: flex;
justify-content: space-between;
`;
export const MainInfo = styled.div`

View file

@ -13,7 +13,12 @@ import {
import ReactTooltip from "react-tooltip";
import { SubCard, Separation } from "../../generic/Styled";
import { SettingsContext } from "../../../context/SettingsContext";
import { getStatusDot, getPrivate, getSymbol } from "../helpers";
import {
getStatusDot,
getPrivate,
getSymbol,
getTooltipType
} from "../../generic/Helpers";
import { getTransactionLink, getNodeLink } from "../../generic/Helpers";
import Modal from "../../modal/ReactModal";
import { CloseChannel } from "../../closeChannel/CloseChannel";
@ -22,9 +27,11 @@ export const ChannelCard = ({ channelInfo, index }: any) => {
const [isOpen, setIsOpen] = useState(false);
const [modalOpen, setModalOpen] = useState(false);
const { price, symbol, currency } = useContext(SettingsContext);
const { price, symbol, currency, theme } = useContext(SettingsContext);
const priceProps = { price, symbol, currency };
const tooltipType = getTooltipType(theme);
const getFormat = (amount: string) =>
getValue({
amount,
@ -76,13 +83,21 @@ export const ChannelCard = ({ channelInfo, index }: any) => {
<>
<Separation />
<DetailLine>
Partner Public Key: {getNodeLink(partnerPublicKey)}
<div>Node Public Key:</div>
{getNodeLink(partnerPublicKey)}
</DetailLine>
<DetailLine>
Transaction Id: {getTransactionLink(transactionId)}
<div>Transaction Id:</div>
{getTransactionLink(transactionId)}
</DetailLine>
<DetailLine>
<div>Channel Id:</div>
{id}
</DetailLine>
<DetailLine>
<div>Commit Fee:</div>
{getFormat(commitTransactionFee)}
</DetailLine>
<DetailLine>Channel Id: {id}</DetailLine>
<DetailLine>Commit Fee: {getFormat(commitTransactionFee)}</DetailLine>
{/* <div>{commitTransactionWeight}</div> */}
{/* <div>{isStaticRemoteKey}</div> */}
{/* <div>{localReserve}</div> */}
@ -132,6 +147,7 @@ export const ChannelCard = ({ channelInfo, index }: any) => {
id={`node_balance_tip_${index}`}
effect={"solid"}
place={"bottom"}
type={tooltipType}
>
<div>{`Local Balance: ${formatLocal}`}</div>
<div>{`Remote Balance: ${formatRemote}`}</div>
@ -140,6 +156,7 @@ export const ChannelCard = ({ channelInfo, index }: any) => {
id={`node_activity_tip_${index}`}
effect={"solid"}
place={"bottom"}
type={tooltipType}
>
<div>{`received: ${formatreceived}`}</div>
<div>{`Sent: ${formatSent}`}</div>

View file

@ -15,7 +15,7 @@ export const Channels = () => {
return (
<Card>
<h1 style={{ margin: "0" }}>Channels</h1>
<h1 style={{ margin: "0", marginBottom: "10px" }}>Channels</h1>
{data.getChannels.map((channel: any, index: number) => (
<>
<ChannelCard channelInfo={channel} index={index} />

View file

@ -1,25 +0,0 @@
import React from "react";
import { StatusDot } from "./Channels.style";
import { DownArrow, UpArrow, EyeOff } from "../generic/Icons";
export const getStatusDot = (status: boolean, type: string) => {
if (type === "active") {
return status ? (
<StatusDot color="#95de64" />
) : (
<StatusDot color="#ff4d4f" />
);
} else if (type === "opening") {
return status ? <StatusDot color="#13c2c2" /> : null;
} else {
return status ? <StatusDot color="#ff4d4f" /> : null;
}
};
export const getSymbol = (status: boolean) => {
return status ? <DownArrow /> : <UpArrow />;
};
export const getPrivate = (status: boolean) => {
return status && <EyeOff />;
};

View file

@ -12,15 +12,17 @@ import {
import ReactTooltip from "react-tooltip";
import { SubCard, Separation } from "../../generic/Styled";
import { SettingsContext } from "../../../context/SettingsContext";
import { getStatusDot } from "../helpers";
import { getStatusDot, getTooltipType } from "../../generic/Helpers";
import { getNodeLink } from "../../generic/Helpers";
export const PendingCard = ({ channelInfo, index }: any) => {
const [isOpen, setIsOpen] = useState(false);
const { price, symbol, currency } = useContext(SettingsContext);
const { price, symbol, currency, theme } = useContext(SettingsContext);
const priceProps = { price, symbol, currency };
const tooltipType = getTooltipType(theme);
const getFormat = (amount: string) =>
getValue({
amount,
@ -60,7 +62,8 @@ export const PendingCard = ({ channelInfo, index }: any) => {
<>
<Separation />
<DetailLine>
Partner Public Key: {getNodeLink(partnerPublicKey)}
<div>Node Public Key:</div>
{getNodeLink(partnerPublicKey)}
</DetailLine>
{/* <DetailLine>{localReserve}</DetailLine> */}
{/* <DetailLine>{remoteReserve}</DetailLine> */}
@ -101,6 +104,7 @@ export const PendingCard = ({ channelInfo, index }: any) => {
id={`node_balance_tip_${index}`}
effect={"solid"}
place={"bottom"}
type={tooltipType}
>
<div>{`Local Balance: ${formatLocal}`}</div>
<div>{`Remote Balance: ${formatRemote}`}</div>
@ -109,6 +113,7 @@ export const PendingCard = ({ channelInfo, index }: any) => {
id={`node_activity_tip_${index}`}
effect={"solid"}
place={"bottom"}
type={tooltipType}
>
<div>{`received: ${formatreceived}`}</div>
<div>{`Sent: ${formatSent}`}</div>

View file

@ -15,7 +15,7 @@ export const PendingChannels = () => {
return (
<Card>
<h1 style={{ margin: "0" }}>Pending Channels</h1>
<h1 style={{ margin: "0", marginBottom: "10px" }}>Pending Channels</h1>
{data.getPendingChannels.map((channel: any, index: number) => (
<>
<PendingCard channelInfo={channel} index={index} />

View file

@ -1,5 +1,8 @@
import React from "react";
import { SmallLink } from "./Styled";
import { StatusDot } from "../channels/Channels.style";
import { DownArrow, UpArrow, EyeOff } from "./Icons";
import { formatDistanceStrict, format } from "date-fns";
export const getTransactionLink = (transaction: string) => {
const link = `https://www.blockchain.com/btc/tx/${transaction}`;
@ -18,3 +21,37 @@ export const getNodeLink = (publicKey: string) => {
</SmallLink>
);
};
export const getDateDif = (date: string) => {
return formatDistanceStrict(new Date(date), new Date());
};
export const getFormatDate = (date: string) => {
return format(new Date(date), "dd-MM-yyyy - HH:mm:ss");
};
export const getTooltipType = (theme: string) => {
return theme === "dark" ? "light" : undefined;
};
export const getStatusDot = (status: boolean, type: string) => {
if (type === "active") {
return status ? (
<StatusDot color="#95de64" />
) : (
<StatusDot color="#ff4d4f" />
);
} else if (type === "opening") {
return status ? <StatusDot color="#13c2c2" /> : null;
} else {
return status ? <StatusDot color="#ff4d4f" /> : null;
}
};
export const getSymbol = (status: boolean) => {
return status ? <DownArrow /> : <UpArrow />;
};
export const getPrivate = (status: boolean) => {
return status && <EyeOff />;
};

View file

@ -0,0 +1,116 @@
import React, { useContext, useState } from "react";
import { getValue } from "../../helpers/Helpers";
import { SettingsContext } from "../../context/SettingsContext";
import { Separation, SubCard } from "../generic/Styled";
import {
DetailLine,
StatusLine,
NodeBar,
NodeTitle,
NodeDetails
} from "../channels/Channels.style";
import { getStatusDot, getDateDif, getFormatDate } from "../generic/Helpers";
import styled from "styled-components";
const DifLine = styled.div`
font-size: 12px;
color: #bfbfbf;
`;
const formatDifference = (
difference: string,
numDif: number,
status: boolean
) => {
if (numDif > 0) {
return `+ ${difference}`;
} else if (numDif < 0 && status) {
return `- ${difference}`;
} else {
return null;
}
};
export const InvoiceCard = ({ invoice, index }: any) => {
const [isOpen, setIsOpen] = useState(false);
const { price, symbol, currency } = useContext(SettingsContext);
const priceProps = { price, symbol, currency };
const getFormat = (amount: string) =>
getValue({
amount,
...priceProps
});
const {
confirmedAt,
createdAt,
description,
expiresAt,
isConfirmed,
received,
tokens
// chainAddress,
// descriptionHash,
// id,
// isCanceled,
// isHeld,
// isOutgoing,
// isPrivate,
// payments,
// receivedMtokens,
// request,
// secret,
} = invoice;
const formatAmount = getFormat(tokens);
const dif = received - tokens;
const formatDif = getFormat(`${dif}`);
const renderDetails = () => {
return (
<>
<Separation />
{isConfirmed && (
<DetailLine>
<div>Confirmed</div>
{`${getDateDif(confirmedAt)} ago (${getFormatDate(confirmedAt)})`}
</DetailLine>
)}
<DetailLine>
<div>Created:</div>
{`${getDateDif(createdAt)} ago (${getFormatDate(createdAt)})`}
</DetailLine>
<DetailLine>
<div>Expires:</div>
{`${getDateDif(expiresAt)} ago (${getFormatDate(expiresAt)})`}
</DetailLine>
{/* <DetailLine>{chainAddress}</DetailLine> */}
{/* <DetailLine>{descriptionHash}</DetailLine> */}
{/* <DetailLine>{isCanceled}</DetailLine> */}
{/* <DetailLine>{isHeld}</DetailLine> */}
{/* <DetailLine>{isOutgoing}</DetailLine> */}
{/* <DetailLine>{isPrivate}</DetailLine> */}
{/* <DetailLine>{payments}</DetailLine> */}
{/* <DetailLine>{receivedMtokens}</DetailLine> */}
{/* <DetailLine>{request}</DetailLine> */}
{/* <DetailLine>{secret}</DetailLine> */}
</>
);
};
return (
<SubCard key={index} onClick={() => setIsOpen(prev => !prev)}>
<StatusLine>{getStatusDot(isConfirmed, "active")}</StatusLine>
<NodeBar>
<NodeTitle>
{formatAmount}
<DifLine>{formatDifference(formatDif, dif, isConfirmed)}</DifLine>
</NodeTitle>
<NodeDetails>{description}</NodeDetails>
</NodeBar>
{isOpen && renderDetails()}
</SubCard>
);
};

View file

@ -2,6 +2,7 @@ import React from "react";
import { useQuery } from "@apollo/react-hooks";
import { GET_INVOICES } from "../../graphql/query";
import { Card } from "../generic/Styled";
import { InvoiceCard } from "./InvoiceCard";
export const Invoices = () => {
const { loading, error, data } = useQuery(GET_INVOICES);
@ -13,50 +14,14 @@ export const Invoices = () => {
}
const renderInvoices = () => {
return data.getInvoices.map((invoice: any, index: number) => {
const {
chainAddress,
confirmedAt,
createdAt,
description,
descriptionHash,
expiresAt,
id,
isCanceled,
isConfirmed,
isHeld,
isOutgoing,
isPrivate,
payments,
received,
receivedMtokens,
request,
secret,
tokens
} = invoice;
return (
<Card bottom="10px" key={index}>
<p>{`Amount: ${tokens}`}</p>
<p>{`Confirmed: ${isConfirmed}`}</p>
<p>{`Received: ${received}`}</p>
<p>{chainAddress}</p>
<p>{confirmedAt}</p>
<p>{createdAt}</p>
<p>{description}</p>
<p>{descriptionHash}</p>
<p>{expiresAt}</p>
<p>{id}</p>
<p>{isCanceled}</p>
<p>{isHeld}</p>
<p>{isOutgoing}</p>
<p>{isPrivate}</p>
<p>{payments}</p>
<p>{receivedMtokens}</p>
<p>{request}</p>
<p>{secret}</p>
</Card>
);
});
return (
<Card>
<h1 style={{ margin: "0", marginBottom: "10px" }}>Invoices</h1>
{data.getInvoices.map((invoice: any, index: number) => {
return <InvoiceCard key={index} invoice={invoice} />;
})}
</Card>
);
};
return renderInvoices();

View file

@ -7,6 +7,7 @@ import { SettingsContext } from "../../context/SettingsContext";
import { getValue } from "../../helpers/Helpers";
import { Separation } from "../generic/Styled";
import { QuestionIcon, Zap, ZapOff } from "../generic/Icons";
import { getTooltipType } from "../generic/Helpers";
const Title = styled.div`
font-size: 18px;
@ -40,9 +41,10 @@ const Alias = styled.div`
export const NodeInfo = () => {
const { loading, error, data } = useQuery(GET_NODE_INFO);
const { price, symbol, currency } = useContext(SettingsContext);
const { price, symbol, currency, theme } = useContext(SettingsContext);
const priceProps = { price, symbol, currency };
const tooltipType = getTooltipType(theme);
// console.log(loading, error, data);
if (loading || !data || !data.getNodeInfo) {
@ -93,16 +95,31 @@ export const NodeInfo = () => {
</Info>
</Balance>
<Separation />
<ReactTooltip effect={"solid"} place={"right"} />
<ReactTooltip id={"balance_tip"} effect={"solid"} place={"right"}>
<ReactTooltip effect={"solid"} place={"right"} type={tooltipType} />
<ReactTooltip
id={"balance_tip"}
effect={"solid"}
place={"right"}
type={tooltipType}
>
<div>{`Channel Balance: ${formatCCB}`}</div>
<div>{`Pending Channel Balance: ${formatPCB}`}</div>
</ReactTooltip>
<ReactTooltip id={"chain_balance_tip"} effect={"solid"} place={"right"}>
<ReactTooltip
id={"chain_balance_tip"}
effect={"solid"}
place={"right"}
type={tooltipType}
>
<div>{`Chain Balance: ${formatCB}`}</div>
<div>{`Pending Chain Balance: ${formatPB}`}</div>
</ReactTooltip>
<ReactTooltip id={"node_tip"} effect={"solid"} place={"right"}>
<ReactTooltip
id={"node_tip"}
effect={"solid"}
place={"right"}
type={tooltipType}
>
<div>{`Active Channels: ${activeChannelsCount}`}</div>
<div>{`Pending Channels: ${pendingChannelsCount}`}</div>
<div>{`Peers: ${peersCount}`}</div>

View file

@ -0,0 +1,28 @@
import React from "react";
import { useQuery } from "@apollo/react-hooks";
import { GET_PAYMENTS } from "../../graphql/query";
import { Card } from "../generic/Styled";
import { PaymentsCard } from "./PaymentsCards";
export const Payments = () => {
const { loading, error, data } = useQuery(GET_PAYMENTS);
console.log(loading, error, data);
if (loading || !data || !data.getPayments) {
return <Card bottom="10px">Loading....</Card>;
}
const renderInvoices = () => {
return (
<Card>
<h1 style={{ margin: "0", marginBottom: "10px" }}>Payments</h1>
{data.getPayments.map((payment: any, index: number) => {
return <PaymentsCard key={index} payment={payment} />;
})}
</Card>
);
};
return renderInvoices();
};

View file

@ -0,0 +1,131 @@
import React, { useContext, useState } from "react";
import { getValue } from "../../helpers/Helpers";
import { SettingsContext } from "../../context/SettingsContext";
import { Separation, SubCard } from "../generic/Styled";
import {
DetailLine,
StatusLine,
NodeBar,
NodeTitle,
NodeDetails,
MainInfo
} from "../channels/Channels.style";
import {
getStatusDot,
getDateDif,
getFormatDate,
getNodeLink
} from "../generic/Helpers";
export const PaymentsCard = ({ payment, index }: any) => {
const [isOpen, setIsOpen] = useState(false);
const { price, symbol, currency } = useContext(SettingsContext);
const priceProps = { price, symbol, currency };
const getFormat = (amount: string) =>
getValue({
amount,
...priceProps
});
const {
createdAt,
destination,
fee,
feeMtokens,
hops,
isConfirmed,
tokens
// id,
// isOutgoing,
// mtokens,
// request,
// secret,
} = payment;
const formatAmount = getFormat(tokens);
const renderDetails = () => {
return (
<>
<Separation />
<DetailLine>
<div>Created:</div>
{`${getDateDif(createdAt)} ago (${getFormatDate(createdAt)})`}
</DetailLine>
<DetailLine>
<div>Destination Node:</div>
{getNodeLink(destination)}
</DetailLine>
<DetailLine>
<div>Fee:</div>
{getFormat(fee)}
</DetailLine>
<DetailLine>
<div>Fee msats:</div>
{`${feeMtokens} sats`}
</DetailLine>
<DetailLine data-tip data-for={`payment_hops_${index}`}>
<div>Hops:</div>
{hops.length}
</DetailLine>
{hops.map((hop: any, index: number) => (
<DetailLine>
<div>{`Hop ${index + 1}:`}</div>
<div style={{ textAlign: "right" }} key={index}>
{hop}
</div>
</DetailLine>
))}
{/* <DetailLine>{id}</DetailLine> */}
{/* <DetailLine>{isOutgoing ? 'true': 'false'}</DetailLine> */}
{/* <DetailLine>{secret}</DetailLine> */}
{/* <DetailLine>{request}</DetailLine> */}
</>
);
};
return (
<SubCard key={index}>
<MainInfo onClick={() => setIsOpen(prev => !prev)}>
<StatusLine>{getStatusDot(isConfirmed, "active")}</StatusLine>
<NodeBar>
<NodeTitle>
{formatAmount}
{/* <DifLine>
{formatDifference(formatDif, dif, isConfirmed)}
</DifLine> */}
</NodeTitle>
<NodeDetails>
{/* {description} */}
{/* {formatBalance} */}
{/* <div>
<Progress
data-tip
data-for={`node_balance_tip_${index}`}
>
<ProgressBar
percent={getPercent(
localBalance,
remoteBalance
)}
/>
</Progress>
<Progress
data-tip
data-for={`node_activity_tip_${index}`}
>
<ProgressBar
order={2}
percent={getPercent(received, sent)}
/>
</Progress>
</div> */}
</NodeDetails>
</NodeBar>
</MainInfo>
{isOpen && renderDetails()}
</SubCard>
);
};

View file

@ -138,6 +138,25 @@ export const GET_INVOICES = gql`
}
`;
export const GET_PAYMENTS = gql`
query GetPayments {
getPayments {
createdAt
destination
fee
feeMtokens
hops
id
isConfirmed
isOutgoing
mtokens
request
secret
tokens
}
}
`;
export const GET_BITCOIN_PRICE = gql`
query GetBitcoinPrice($currency: String) {
getBitcoinPrice(currency: $currency) {

View file

@ -7,6 +7,7 @@ import { ChannelView } from "../../views/channels/ChannelView";
import { InvoiceView } from "../../views/invoices/InvoiceView";
import { SettingsView } from "../../views/settings/Settings";
import { PendingChannelView } from "../../views/channels/PendingChannels";
import { PaymentsView } from "../../views/paymentsView/PaymentsView";
const ContentStyle = styled.div`
/* display: flex;
@ -26,6 +27,7 @@ export const Content = () => {
<Route path="/channels" render={() => <ChannelView />} />
<Route path="/pendingChannels" render={() => <PendingChannelView />} />
<Route path="/invoices" render={() => <InvoiceView />} />
<Route path="/payments" render={() => <PaymentsView />} />
<Route path="/settings" render={() => <SettingsView />} />
<Route path="*" render={() => <NotFound />} />
</Switch>

View file

@ -45,6 +45,9 @@ export const Navigation = () => {
<p>
<Link to="/invoices">Invoices</Link>
</p>
<p>
<Link to="/payments">Payments</Link>
</p>
<p>
<Link to="/settings">Settings</Link>
</p>

View file

@ -0,0 +1,10 @@
import React from "react";
import { Payments } from "../../components/payments/Payments";
export const PaymentsView = () => {
return (
<>
<Payments />
</>
);
};

View file

@ -3999,6 +3999,11 @@ data-urls@^1.0.0, data-urls@^1.1.0:
whatwg-mimetype "^2.2.0"
whatwg-url "^7.0.0"
date-fns@^2.8.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.8.0.tgz#628d865367e30e45747ed1e8b0c1572090b04f55"
integrity sha512-nbZMIMsoD7QiIKipZ5+XRTCtHZad1ch8OEkLaJxjGL6ThAK2IWAdjmAUAS7Fdz5fCaVWtqc+c8pAsN/MX8eaew==
date-now@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"