mirror of
https://github.com/apotdevin/thunderhub.git
synced 2025-02-22 22:25:21 +01:00
feat: channel view changes and more
This commit is contained in:
parent
9e84835561
commit
a75359f045
25 changed files with 554 additions and 145 deletions
|
@ -15,6 +15,11 @@ const client = new ApolloClient({
|
||||||
uri: "http://localhost:3001"
|
uri: "http://localhost:3001"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto 0 auto;
|
||||||
|
`;
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
|
@ -34,12 +39,14 @@ const ContextApp: React.FC = () => {
|
||||||
<ThemeProvider theme={{ mode: theme }}>
|
<ThemeProvider theme={{ mode: theme }}>
|
||||||
<BitcoinPrice />
|
<BitcoinPrice />
|
||||||
<GlobalStyles />
|
<GlobalStyles />
|
||||||
|
<Wrapper>
|
||||||
<Container>
|
<Container>
|
||||||
<Header />
|
<Header />
|
||||||
<Navigation />
|
<Navigation />
|
||||||
<Content />
|
<Content />
|
||||||
<Footer />
|
<Footer />
|
||||||
</Container>
|
</Container>
|
||||||
|
</Wrapper>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import {
|
import {
|
||||||
progressBackground,
|
progressBackground,
|
||||||
progressLeft,
|
progressFirst,
|
||||||
progressRight
|
progressSecond
|
||||||
} from "../../styles/Themes";
|
} from "../../styles/Themes";
|
||||||
|
|
||||||
export const Progress = styled.div`
|
export const Progress = styled.div`
|
||||||
|
@ -15,17 +15,22 @@ export const Progress = styled.div`
|
||||||
0 1px rgba(255, 255, 255, 0.08);
|
0 1px rgba(255, 255, 255, 0.08);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
interface ProgressBar {
|
||||||
|
percent: number;
|
||||||
|
order?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export const ProgressBar = styled.div`
|
export const ProgressBar = styled.div`
|
||||||
height: 10px;
|
height: 10px;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
background-image: linear-gradient(
|
background-image: linear-gradient(
|
||||||
to right,
|
to bottom,
|
||||||
${progressLeft} 0%,
|
rgba(255, 255, 255, 0.3),
|
||||||
${progressLeft} ${({ percent }: { percent: number }) => `${percent}%`},
|
rgba(0, 0, 0, 0.05)
|
||||||
${progressRight} ${({ percent }: { percent: number }) => `${percent}%`},
|
|
||||||
${progressRight} 100%
|
|
||||||
);
|
);
|
||||||
width: 100%;
|
background-color: ${({ order }: ProgressBar) =>
|
||||||
|
order === 2 ? progressFirst : progressSecond};
|
||||||
|
width: ${({ percent }: ProgressBar) => `${percent}%`};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const NodeBar = styled.div`
|
export const NodeBar = styled.div`
|
||||||
|
@ -48,3 +53,36 @@ export const NodeTitle = styled.div`
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const StatusLine = styled.div`
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
right: -8px;
|
||||||
|
top: -8px;
|
||||||
|
display: flex;
|
||||||
|
/* flex-direction: column; */
|
||||||
|
justify-content: flex-end;
|
||||||
|
/* align-items: flex-start; */
|
||||||
|
/* z-index: 2; */
|
||||||
|
margin: 0 0 -8px 0;
|
||||||
|
/* height: 36px; */
|
||||||
|
/* margin-left: 5px; */
|
||||||
|
/* margin: -8px -7px 0 0; */
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const StatusDot = styled.div`
|
||||||
|
margin: 0 2px;
|
||||||
|
height: 8px;
|
||||||
|
width: 8px;
|
||||||
|
border-radius: 100%;
|
||||||
|
background-color: ${({ color }: { color: string }) => color};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DetailLine = styled.div`
|
||||||
|
font-size: 14px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const MainInfo = styled.div`
|
||||||
|
cursor: pointer;
|
||||||
|
`;
|
||||||
|
|
|
@ -1,105 +0,0 @@
|
||||||
import React, { useContext } from "react";
|
|
||||||
import { useQuery } from "@apollo/react-hooks";
|
|
||||||
import { GET_CHANNELS } from "../../graphql/query";
|
|
||||||
import { Card } from "../generic/Styled";
|
|
||||||
import { getPercent, getValue } from "../../helpers/Helpers";
|
|
||||||
import {
|
|
||||||
Progress,
|
|
||||||
ProgressBar,
|
|
||||||
NodeTitle,
|
|
||||||
NodeBar,
|
|
||||||
NodeDetails
|
|
||||||
} from "./Channels.style";
|
|
||||||
import { SettingsContext } from "../../context/SettingsContext";
|
|
||||||
import { DownArrow, UpArrow } from "../generic/Icons";
|
|
||||||
|
|
||||||
const getSymbol = (status: boolean) => {
|
|
||||||
return status ? <DownArrow /> : <UpArrow />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Channels = () => {
|
|
||||||
const { loading, error, data } = useQuery(GET_CHANNELS);
|
|
||||||
const { price, symbol, currency } = useContext(SettingsContext);
|
|
||||||
const priceProps = { price, symbol, currency };
|
|
||||||
|
|
||||||
console.log(loading, error, data);
|
|
||||||
|
|
||||||
if (loading || !data || !data.getChannels) {
|
|
||||||
return <Card bottom="10px">Loading....</Card>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderChannels = () => {
|
|
||||||
return data.getChannels.map((channel: any, index: number) => {
|
|
||||||
const {
|
|
||||||
capacity,
|
|
||||||
// commitTransactionFee,
|
|
||||||
// commitTransactionWeight,
|
|
||||||
// id,
|
|
||||||
isActive,
|
|
||||||
isClosing,
|
|
||||||
isOpening,
|
|
||||||
isPartnerInitiated,
|
|
||||||
// isPrivate,
|
|
||||||
// isStaticRemoteKey,
|
|
||||||
localBalance,
|
|
||||||
// localReserve,
|
|
||||||
// partnerPublicKey,
|
|
||||||
recieved,
|
|
||||||
remoteBalance,
|
|
||||||
// remoteReserve,
|
|
||||||
sent,
|
|
||||||
// timeOffline,
|
|
||||||
// timeOnline,
|
|
||||||
// transactionId,
|
|
||||||
// transactionVout,
|
|
||||||
// unsettledBalance,
|
|
||||||
partnerNodeInfo
|
|
||||||
} = channel;
|
|
||||||
|
|
||||||
const {
|
|
||||||
alias,
|
|
||||||
capacity: nodeCapacity,
|
|
||||||
// channelCount,
|
|
||||||
color: nodeColor
|
|
||||||
// lastUpdate
|
|
||||||
} = partnerNodeInfo;
|
|
||||||
return (
|
|
||||||
<Card bottom="10px" color={nodeColor} key={index}>
|
|
||||||
<NodeBar>
|
|
||||||
<NodeTitle>{alias ? alias : "Unknown"}</NodeTitle>
|
|
||||||
<NodeDetails>
|
|
||||||
{`Capacity: ${getValue({
|
|
||||||
amount: capacity,
|
|
||||||
...priceProps
|
|
||||||
})}`}
|
|
||||||
{getSymbol(isPartnerInitiated)}
|
|
||||||
<div>
|
|
||||||
<Progress>
|
|
||||||
<ProgressBar
|
|
||||||
percent={getPercent(localBalance, remoteBalance)}
|
|
||||||
/>
|
|
||||||
</Progress>
|
|
||||||
<Progress>
|
|
||||||
<ProgressBar percent={getPercent(recieved, sent)} />
|
|
||||||
</Progress>
|
|
||||||
</div>
|
|
||||||
</NodeDetails>
|
|
||||||
</NodeBar>
|
|
||||||
|
|
||||||
{/* <p>{`${isActive}`}</p> */}
|
|
||||||
{/* <p>{`${isClosing}`}</p> */}
|
|
||||||
{/* <p>{`${isOpening}`}</p> */}
|
|
||||||
|
|
||||||
{/* <p>{`Node Capacity: ${nodeCapacity}`}</p> */}
|
|
||||||
{/* <p>{`Local: ${localBalance}`}</p> */}
|
|
||||||
{/* <p>{`Remote: ${remoteBalance}`}</p> */}
|
|
||||||
{/* <p>{`${recieved}`}</p> */}
|
|
||||||
{/* <p>{`${sent}`}</p> */}
|
|
||||||
{/* <p>{`${isPartnerInitiated}`}</p> */}
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return renderChannels();
|
|
||||||
};
|
|
144
src/components/channels/channels/ChannelCard.tsx
Normal file
144
src/components/channels/channels/ChannelCard.tsx
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
import React, { useContext, useState } from "react";
|
||||||
|
import { getPercent, getValue } from "../../../helpers/Helpers";
|
||||||
|
import {
|
||||||
|
Progress,
|
||||||
|
ProgressBar,
|
||||||
|
NodeTitle,
|
||||||
|
NodeBar,
|
||||||
|
NodeDetails,
|
||||||
|
StatusLine,
|
||||||
|
DetailLine,
|
||||||
|
MainInfo
|
||||||
|
} from "../Channels.style";
|
||||||
|
import ReactTooltip from "react-tooltip";
|
||||||
|
import { SubCard, Separation } from "../../generic/Styled";
|
||||||
|
import { SettingsContext } from "../../../context/SettingsContext";
|
||||||
|
import { getStatusDot, getPrivate, getSymbol } from "../helpers";
|
||||||
|
import { getTransactionLink, getNodeLink } from "../../generic/Helpers";
|
||||||
|
|
||||||
|
export const ChannelCard = ({ channelInfo, 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 {
|
||||||
|
capacity,
|
||||||
|
commitTransactionFee,
|
||||||
|
// commitTransactionWeight,
|
||||||
|
id,
|
||||||
|
isActive,
|
||||||
|
isClosing,
|
||||||
|
isOpening,
|
||||||
|
isPartnerInitiated,
|
||||||
|
isPrivate,
|
||||||
|
// isStaticRemoteKey,
|
||||||
|
localBalance,
|
||||||
|
// localReserve,
|
||||||
|
partnerPublicKey,
|
||||||
|
received,
|
||||||
|
remoteBalance,
|
||||||
|
// remoteReserve,
|
||||||
|
sent,
|
||||||
|
// timeOffline,
|
||||||
|
// timeOnline,
|
||||||
|
transactionId,
|
||||||
|
// transactionVout,
|
||||||
|
// unsettledBalance,
|
||||||
|
partnerNodeInfo
|
||||||
|
} = channelInfo;
|
||||||
|
|
||||||
|
const {
|
||||||
|
alias,
|
||||||
|
// capacity: nodeCapacity,
|
||||||
|
// channelCount,
|
||||||
|
color: nodeColor
|
||||||
|
// lastUpdate
|
||||||
|
} = partnerNodeInfo;
|
||||||
|
|
||||||
|
const formatBalance = getFormat(capacity);
|
||||||
|
const formatLocal = getFormat(localBalance);
|
||||||
|
const formatRemote = getFormat(remoteBalance);
|
||||||
|
const formatreceived = getFormat(received);
|
||||||
|
const formatSent = getFormat(sent);
|
||||||
|
|
||||||
|
const renderDetails = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Separation />
|
||||||
|
<DetailLine>
|
||||||
|
Partner Public Key: {getNodeLink(partnerPublicKey)}
|
||||||
|
</DetailLine>
|
||||||
|
<DetailLine>
|
||||||
|
Transaction Id: {getTransactionLink(transactionId)}
|
||||||
|
</DetailLine>
|
||||||
|
<DetailLine>Channel Id: {id}</DetailLine>
|
||||||
|
<DetailLine>Commit Fee: {getFormat(commitTransactionFee)}</DetailLine>
|
||||||
|
{/* <div>{commitTransactionWeight}</div> */}
|
||||||
|
{/* <div>{isStaticRemoteKey}</div> */}
|
||||||
|
{/* <div>{localReserve}</div> */}
|
||||||
|
{/* <div>{remoteReserve}</div> */}
|
||||||
|
{/* <div>{timeOffline}</div> */}
|
||||||
|
{/* <div>{timeOnline}</div> */}
|
||||||
|
{/* <div>{transactionVout}</div> */}
|
||||||
|
{/* <div>{unsettledBalance}</div> */}
|
||||||
|
{/* <div>{nodeCapacity}</div> */}
|
||||||
|
{/* <div>{channelCount}</div> */}
|
||||||
|
{/* <div>{lastUpdate}</div> */}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SubCard color={nodeColor} key={index}>
|
||||||
|
<MainInfo onClick={() => setIsOpen(prev => !prev)}>
|
||||||
|
<StatusLine>
|
||||||
|
{getStatusDot(isActive, "active")}
|
||||||
|
{getStatusDot(isOpening, "opening")}
|
||||||
|
{getStatusDot(isClosing, "closing")}
|
||||||
|
</StatusLine>
|
||||||
|
<NodeBar>
|
||||||
|
<NodeTitle>{alias ? alias : "Unknown"}</NodeTitle>
|
||||||
|
<NodeDetails>
|
||||||
|
{formatBalance}
|
||||||
|
{getPrivate(isPrivate)}
|
||||||
|
{getSymbol(isPartnerInitiated)}
|
||||||
|
<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()}
|
||||||
|
<ReactTooltip
|
||||||
|
id={`node_balance_tip_${index}`}
|
||||||
|
effect={"solid"}
|
||||||
|
place={"bottom"}
|
||||||
|
>
|
||||||
|
<div>{`Local Balance: ${formatLocal}`}</div>
|
||||||
|
<div>{`Remote Balance: ${formatRemote}`}</div>
|
||||||
|
</ReactTooltip>
|
||||||
|
<ReactTooltip
|
||||||
|
id={`node_activity_tip_${index}`}
|
||||||
|
effect={"solid"}
|
||||||
|
place={"bottom"}
|
||||||
|
>
|
||||||
|
<div>{`received: ${formatreceived}`}</div>
|
||||||
|
<div>{`Sent: ${formatSent}`}</div>
|
||||||
|
</ReactTooltip>
|
||||||
|
</SubCard>
|
||||||
|
);
|
||||||
|
};
|
26
src/components/channels/channels/Channels.tsx
Normal file
26
src/components/channels/channels/Channels.tsx
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import React from "react";
|
||||||
|
import { useQuery } from "@apollo/react-hooks";
|
||||||
|
import { GET_CHANNELS } from "../../../graphql/query";
|
||||||
|
import { Card } from "../../generic/Styled";
|
||||||
|
import { ChannelCard } from "./ChannelCard";
|
||||||
|
|
||||||
|
export const Channels = () => {
|
||||||
|
const { loading, error, data } = useQuery(GET_CHANNELS);
|
||||||
|
|
||||||
|
console.log(loading, error, data);
|
||||||
|
|
||||||
|
if (loading || !data || !data.getChannels) {
|
||||||
|
return <Card bottom="10px">Loading....</Card>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<h1 style={{ margin: "0" }}>Channels</h1>
|
||||||
|
{data.getChannels.map((channel: any, index: number) => (
|
||||||
|
<>
|
||||||
|
<ChannelCard channelInfo={channel} index={index} />
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
25
src/components/channels/helpers.tsx
Normal file
25
src/components/channels/helpers.tsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
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 />;
|
||||||
|
};
|
118
src/components/channels/pendingChannels/PendingCard.tsx
Normal file
118
src/components/channels/pendingChannels/PendingCard.tsx
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
import React, { useContext, useState } from "react";
|
||||||
|
import { getPercent, getValue } from "../../../helpers/Helpers";
|
||||||
|
import {
|
||||||
|
Progress,
|
||||||
|
ProgressBar,
|
||||||
|
NodeTitle,
|
||||||
|
NodeBar,
|
||||||
|
NodeDetails,
|
||||||
|
StatusLine,
|
||||||
|
DetailLine
|
||||||
|
} from "../Channels.style";
|
||||||
|
import ReactTooltip from "react-tooltip";
|
||||||
|
import { SubCard, Separation } from "../../generic/Styled";
|
||||||
|
import { SettingsContext } from "../../../context/SettingsContext";
|
||||||
|
import { getStatusDot } from "../helpers";
|
||||||
|
import { getNodeLink } from "../../generic/Helpers";
|
||||||
|
|
||||||
|
export const PendingCard = ({ channelInfo, 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 {
|
||||||
|
isActive,
|
||||||
|
isClosing,
|
||||||
|
isOpening,
|
||||||
|
localBalance,
|
||||||
|
// localReserve,
|
||||||
|
partnerPublicKey,
|
||||||
|
received,
|
||||||
|
remoteBalance,
|
||||||
|
// remoteReserve,
|
||||||
|
sent,
|
||||||
|
partnerNodeInfo
|
||||||
|
} = channelInfo;
|
||||||
|
|
||||||
|
const {
|
||||||
|
alias,
|
||||||
|
// capacity: nodeCapacity,
|
||||||
|
// channelCount,
|
||||||
|
color: nodeColor
|
||||||
|
// lastUpdate
|
||||||
|
} = partnerNodeInfo;
|
||||||
|
|
||||||
|
const formatBalance = getFormat(localBalance + remoteBalance);
|
||||||
|
const formatLocal = getFormat(localBalance);
|
||||||
|
const formatRemote = getFormat(remoteBalance);
|
||||||
|
const formatreceived = getFormat(received);
|
||||||
|
const formatSent = getFormat(sent);
|
||||||
|
|
||||||
|
const renderDetails = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Separation />
|
||||||
|
<DetailLine>
|
||||||
|
Partner Public Key: {getNodeLink(partnerPublicKey)}
|
||||||
|
</DetailLine>
|
||||||
|
{/* <DetailLine>{localReserve}</DetailLine> */}
|
||||||
|
{/* <DetailLine>{remoteReserve}</DetailLine> */}
|
||||||
|
{/* <DetailLine>{nodeCapacity}</DetailLine> */}
|
||||||
|
{/* <DetailLine>{channelCount}</DetailLine> */}
|
||||||
|
{/* <DetailLine>{lastUpdate}</DetailLine> */}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SubCard
|
||||||
|
color={nodeColor}
|
||||||
|
key={index}
|
||||||
|
onClick={() => setIsOpen(prev => !prev)}
|
||||||
|
>
|
||||||
|
<StatusLine>
|
||||||
|
{getStatusDot(isActive, "active")}
|
||||||
|
{getStatusDot(isOpening, "opening")}
|
||||||
|
{getStatusDot(isClosing, "closing")}
|
||||||
|
</StatusLine>
|
||||||
|
<NodeBar>
|
||||||
|
<NodeTitle>{alias ? alias : "Unknown"}</NodeTitle>
|
||||||
|
<NodeDetails>
|
||||||
|
{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>
|
||||||
|
{isOpen && renderDetails()}
|
||||||
|
<ReactTooltip
|
||||||
|
id={`node_balance_tip_${index}`}
|
||||||
|
effect={"solid"}
|
||||||
|
place={"bottom"}
|
||||||
|
>
|
||||||
|
<div>{`Local Balance: ${formatLocal}`}</div>
|
||||||
|
<div>{`Remote Balance: ${formatRemote}`}</div>
|
||||||
|
</ReactTooltip>
|
||||||
|
<ReactTooltip
|
||||||
|
id={`node_activity_tip_${index}`}
|
||||||
|
effect={"solid"}
|
||||||
|
place={"bottom"}
|
||||||
|
>
|
||||||
|
<div>{`received: ${formatreceived}`}</div>
|
||||||
|
<div>{`Sent: ${formatSent}`}</div>
|
||||||
|
</ReactTooltip>
|
||||||
|
</SubCard>
|
||||||
|
);
|
||||||
|
};
|
26
src/components/channels/pendingChannels/PendingChannels.tsx
Normal file
26
src/components/channels/pendingChannels/PendingChannels.tsx
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import React from "react";
|
||||||
|
import { useQuery } from "@apollo/react-hooks";
|
||||||
|
import { GET_PENDING_CHANNELS } from "../../../graphql/query";
|
||||||
|
import { Card } from "../../generic/Styled";
|
||||||
|
import { PendingCard } from "./PendingCard";
|
||||||
|
|
||||||
|
export const PendingChannels = () => {
|
||||||
|
const { loading, error, data } = useQuery(GET_PENDING_CHANNELS);
|
||||||
|
|
||||||
|
console.log(loading, error, data);
|
||||||
|
|
||||||
|
if (loading || !data || !data.getPendingChannels) {
|
||||||
|
return <Card bottom="10px">Loading....</Card>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<h1 style={{ margin: "0" }}>Pending Channels</h1>
|
||||||
|
{data.getPendingChannels.map((channel: any, index: number) => (
|
||||||
|
<>
|
||||||
|
<PendingCard channelInfo={channel} index={index} />
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
20
src/components/generic/Helpers.tsx
Normal file
20
src/components/generic/Helpers.tsx
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import React from "react";
|
||||||
|
import { SmallLink } from "./Styled";
|
||||||
|
|
||||||
|
export const getTransactionLink = (transaction: string) => {
|
||||||
|
const link = `https://www.blockchain.com/btc/tx/${transaction}`;
|
||||||
|
return (
|
||||||
|
<SmallLink href={link} target="_blank">
|
||||||
|
{transaction}
|
||||||
|
</SmallLink>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getNodeLink = (publicKey: string) => {
|
||||||
|
const link = `https://1ml.com/node/${publicKey}`;
|
||||||
|
return (
|
||||||
|
<SmallLink href={link} target="_blank">
|
||||||
|
{publicKey}
|
||||||
|
</SmallLink>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,4 +1,5 @@
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
import { iconButtonColor } from "../../styles/Themes";
|
||||||
import { ReactComponent as UpIcon } from "../../icons/arrow-up.svg";
|
import { ReactComponent as UpIcon } from "../../icons/arrow-up.svg";
|
||||||
import { ReactComponent as DownIcon } from "../../icons/arrow-down.svg";
|
import { ReactComponent as DownIcon } from "../../icons/arrow-down.svg";
|
||||||
import { ReactComponent as ZapIcon } from "../../icons/zap.svg";
|
import { ReactComponent as ZapIcon } from "../../icons/zap.svg";
|
||||||
|
@ -9,7 +10,9 @@ import { ReactComponent as MoonIcon } from "../../icons/moon.svg";
|
||||||
import { ReactComponent as SatoshiIcon } from "../../icons/satoshi.svg";
|
import { ReactComponent as SatoshiIcon } from "../../icons/satoshi.svg";
|
||||||
import { ReactComponent as EuroIcon } from "../../icons/euro.svg";
|
import { ReactComponent as EuroIcon } from "../../icons/euro.svg";
|
||||||
import { ReactComponent as BitcoinIcon } from "../../icons/bitcoin.svg";
|
import { ReactComponent as BitcoinIcon } from "../../icons/bitcoin.svg";
|
||||||
import { iconButtonColor } from "../../styles/Themes";
|
import { ReactComponent as EyeOffIcon } from "../../icons/eye-off.svg";
|
||||||
|
import { ReactComponent as ChevronUpIcon } from "../../icons/chevrons-up.svg";
|
||||||
|
import { ReactComponent as ChevronDownIcon } from "../../icons/chevrons-down.svg";
|
||||||
|
|
||||||
export const IconCircle = styled.div`
|
export const IconCircle = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -75,3 +78,21 @@ export const Euro = styled(EuroIcon)`
|
||||||
color: ${iconButtonColor}
|
color: ${iconButtonColor}
|
||||||
/* color: ${({ color }: { color?: string }) => (color ? color : "black")}; */
|
/* color: ${({ color }: { color?: string }) => (color ? color : "black")}; */
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const EyeOff = styled(EyeOffIcon)`
|
||||||
|
height: 18px;
|
||||||
|
color: ${iconButtonColor}
|
||||||
|
/* color: ${({ color }: { color?: string }) => (color ? color : "black")}; */
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ChevronDown = styled(ChevronDownIcon)`
|
||||||
|
height: 18px;
|
||||||
|
color: ${iconButtonColor}
|
||||||
|
/* color: ${({ color }: { color?: string }) => (color ? color : "black")}; */
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ChevronUp = styled(ChevronUpIcon)`
|
||||||
|
height: 18px;
|
||||||
|
color: ${iconButtonColor}
|
||||||
|
/* color: ${({ color }: { color?: string }) => (color ? color : "black")}; */
|
||||||
|
`;
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { cardColor, cardBorderColor } from "../../styles/Themes";
|
import {
|
||||||
|
cardColor,
|
||||||
|
cardBorderColor,
|
||||||
|
subCardColor,
|
||||||
|
smallLinkColor
|
||||||
|
} from "../../styles/Themes";
|
||||||
|
|
||||||
export const Card = styled.div`
|
export const Card = styled.div`
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
background: ${cardColor};
|
background: ${cardColor};
|
||||||
/* background: linear-gradient(#fff, #fcfcfc); */
|
/* background: linear-gradient(#fff, #fcfcfc); */
|
||||||
box-shadow: 0 8px 16px -8px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 8px 16px -8px rgba(0, 0, 0, 0.1);
|
||||||
|
@ -15,8 +21,31 @@ export const Card = styled.div`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Separation = styled.div`
|
export const Separation = styled.div`
|
||||||
height: 2px;
|
height: ${({ height }: { height?: number }) => (height ? height : "2")}px;
|
||||||
background-color: #e6e6e6;
|
background-color: #e6e6e6;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const SubCard = styled.div`
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
background: ${subCardColor};
|
||||||
|
/* padding-bottom: 5px; */
|
||||||
|
border: 1px solid ${cardBorderColor};
|
||||||
|
border-left: ${(props: { color?: string }) =>
|
||||||
|
props.color ? `2px solid ${props.color}` : ""};
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 8px 16px -8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const SmallLink = styled.a`
|
||||||
|
text-decoration: none;
|
||||||
|
color: ${smallLinkColor};
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
|
@ -38,7 +38,7 @@ export const Invoices = () => {
|
||||||
<Card bottom="10px" key={index}>
|
<Card bottom="10px" key={index}>
|
||||||
<p>{`Amount: ${tokens}`}</p>
|
<p>{`Amount: ${tokens}`}</p>
|
||||||
<p>{`Confirmed: ${isConfirmed}`}</p>
|
<p>{`Confirmed: ${isConfirmed}`}</p>
|
||||||
<p>{`Recieved: ${received}`}</p>
|
<p>{`Received: ${received}`}</p>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -63,6 +63,11 @@ export const NodeInfo = () => {
|
||||||
const pendingChainBalance = data.getPendingChainBalance;
|
const pendingChainBalance = data.getPendingChainBalance;
|
||||||
const { confirmedBalance, pendingBalance } = data.getChannelBalance;
|
const { confirmedBalance, pendingBalance } = data.getChannelBalance;
|
||||||
|
|
||||||
|
const formatCB = getValue({ amount: chainBalance, ...priceProps });
|
||||||
|
const formatPB = getValue({ amount: pendingChainBalance, ...priceProps });
|
||||||
|
const formatCCB = getValue({ amount: confirmedBalance, ...priceProps });
|
||||||
|
const formatPCB = getValue({ amount: pendingBalance, ...priceProps });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Title>
|
<Title>
|
||||||
|
@ -72,11 +77,11 @@ export const NodeInfo = () => {
|
||||||
<Separation />
|
<Separation />
|
||||||
<Balance data-tip data-for="balance_tip">
|
<Balance data-tip data-for="balance_tip">
|
||||||
<Zap color={pendingBalance === 0 ? "#FFD300" : "#652EC7"} />
|
<Zap color={pendingBalance === 0 ? "#FFD300" : "#652EC7"} />
|
||||||
{getValue({ amount: confirmedBalance, ...priceProps })}
|
{formatCCB}
|
||||||
</Balance>
|
</Balance>
|
||||||
<Balance data-tip data-for="chain_balance_tip">
|
<Balance data-tip data-for="chain_balance_tip">
|
||||||
<ZapOff color={pendingChainBalance === 0 ? "#FFD300" : "#652EC7"} />
|
<ZapOff color={pendingChainBalance === 0 ? "#FFD300" : "#652EC7"} />
|
||||||
{getValue({ amount: chainBalance, ...priceProps })}
|
{formatCB}
|
||||||
</Balance>
|
</Balance>
|
||||||
<Balance
|
<Balance
|
||||||
data-tip
|
data-tip
|
||||||
|
@ -90,12 +95,12 @@ export const NodeInfo = () => {
|
||||||
<Separation />
|
<Separation />
|
||||||
<ReactTooltip effect={"solid"} place={"right"} />
|
<ReactTooltip effect={"solid"} place={"right"} />
|
||||||
<ReactTooltip id={"balance_tip"} effect={"solid"} place={"right"}>
|
<ReactTooltip id={"balance_tip"} effect={"solid"} place={"right"}>
|
||||||
<div>{`Channel Balance: ${confirmedBalance}`}</div>
|
<div>{`Channel Balance: ${formatCCB}`}</div>
|
||||||
<div>{`Pending Channel Balance: ${pendingBalance}`}</div>
|
<div>{`Pending Channel Balance: ${formatPCB}`}</div>
|
||||||
</ReactTooltip>
|
</ReactTooltip>
|
||||||
<ReactTooltip id={"chain_balance_tip"} effect={"solid"} place={"right"}>
|
<ReactTooltip id={"chain_balance_tip"} effect={"solid"} place={"right"}>
|
||||||
<div>{`Chain Balance: ${chainBalance}`}</div>
|
<div>{`Chain Balance: ${formatCB}`}</div>
|
||||||
<div>{`Pending Chain Balance: ${pendingChainBalance}`}</div>
|
<div>{`Pending Chain Balance: ${formatPB}`}</div>
|
||||||
</ReactTooltip>
|
</ReactTooltip>
|
||||||
<ReactTooltip id={"node_tip"} effect={"solid"} place={"right"}>
|
<ReactTooltip id={"node_tip"} effect={"solid"} place={"right"}>
|
||||||
<div>{`Active Channels: ${activeChannelsCount}`}</div>
|
<div>{`Active Channels: ${activeChannelsCount}`}</div>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import styled from "styled-components";
|
||||||
import { iconButtonBack } from "../../styles/Themes";
|
import { iconButtonBack } from "../../styles/Themes";
|
||||||
|
|
||||||
const SelectedIcon = styled(IconCircle)`
|
const SelectedIcon = styled(IconCircle)`
|
||||||
|
margin: 0 5px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: ${({ selected }: { selected: boolean }) =>
|
background-color: ${({ selected }: { selected: boolean }) =>
|
||||||
selected ? iconButtonBack : ""};
|
selected ? iconButtonBack : ""};
|
||||||
|
|
|
@ -28,8 +28,6 @@ const SettingsProvider = ({ children }: any) => {
|
||||||
const savedTheme = localStorage.getItem("theme") || "light";
|
const savedTheme = localStorage.getItem("theme") || "light";
|
||||||
const savedCurrency = localStorage.getItem("currency") || "sat";
|
const savedCurrency = localStorage.getItem("currency") || "sat";
|
||||||
|
|
||||||
console.log(savedCurrency, savedTheme);
|
|
||||||
|
|
||||||
const setSettings = ({ price, symbol, currency, theme }: ChangeProps) => {
|
const setSettings = ({ price, symbol, currency, theme }: ChangeProps) => {
|
||||||
updateSettings((prevState: any) => {
|
updateSettings((prevState: any) => {
|
||||||
const newState = { ...prevState };
|
const newState = { ...prevState };
|
||||||
|
|
|
@ -58,7 +58,7 @@ export const GET_CHANNELS = gql`
|
||||||
localBalance
|
localBalance
|
||||||
localReserve
|
localReserve
|
||||||
partnerPublicKey
|
partnerPublicKey
|
||||||
recieved
|
received
|
||||||
remoteBalance
|
remoteBalance
|
||||||
remoteReserve
|
remoteReserve
|
||||||
sent
|
sent
|
||||||
|
@ -78,6 +78,30 @@ export const GET_CHANNELS = gql`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const GET_PENDING_CHANNELS = gql`
|
||||||
|
query GetPendingChannels {
|
||||||
|
getPendingChannels {
|
||||||
|
isActive
|
||||||
|
isClosing
|
||||||
|
isOpening
|
||||||
|
localBalance
|
||||||
|
localReserve
|
||||||
|
partnerPublicKey
|
||||||
|
received
|
||||||
|
remoteBalance
|
||||||
|
remoteReserve
|
||||||
|
sent
|
||||||
|
partnerNodeInfo {
|
||||||
|
alias
|
||||||
|
capacity
|
||||||
|
channelCount
|
||||||
|
color
|
||||||
|
lastUpdate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const GET_INVOICES = gql`
|
export const GET_INVOICES = gql`
|
||||||
query GetInvoices {
|
query GetInvoices {
|
||||||
getInvoices {
|
getInvoices {
|
||||||
|
|
|
@ -33,7 +33,9 @@ export const getPercent = (local: number, remote: number): number => {
|
||||||
const total = remote + local;
|
const total = remote + local;
|
||||||
const percent = (local / total) * 100;
|
const percent = (local / total) * 100;
|
||||||
|
|
||||||
console.log(Math.round(percent));
|
if (remote === 0 && local === 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return Math.round(percent);
|
return Math.round(percent);
|
||||||
};
|
};
|
||||||
|
|
1
src/icons/chevrons-down.svg
Normal file
1
src/icons/chevrons-down.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevrons-down"><polyline points="7 13 12 18 17 13"></polyline><polyline points="7 6 12 11 17 6"></polyline></svg>
|
After Width: | Height: | Size: 317 B |
1
src/icons/chevrons-up.svg
Normal file
1
src/icons/chevrons-up.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevrons-up"><polyline points="17 11 12 6 7 11"></polyline><polyline points="17 18 12 13 7 18"></polyline></svg>
|
After Width: | Height: | Size: 316 B |
1
src/icons/eye-off.svg
Normal file
1
src/icons/eye-off.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-eye-off"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>
|
After Width: | Height: | Size: 460 B |
|
@ -6,6 +6,7 @@ import { NotFound } from "../../views/notFound/NotFound";
|
||||||
import { ChannelView } from "../../views/channels/ChannelView";
|
import { ChannelView } from "../../views/channels/ChannelView";
|
||||||
import { InvoiceView } from "../../views/invoices/InvoiceView";
|
import { InvoiceView } from "../../views/invoices/InvoiceView";
|
||||||
import { SettingsView } from "../../views/settings/Settings";
|
import { SettingsView } from "../../views/settings/Settings";
|
||||||
|
import { PendingChannelView } from "../../views/channels/PendingChannels";
|
||||||
|
|
||||||
const ContentStyle = styled.div`
|
const ContentStyle = styled.div`
|
||||||
/* display: flex;
|
/* display: flex;
|
||||||
|
@ -23,6 +24,7 @@ export const Content = () => {
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/" render={() => <Home />} />
|
<Route exact path="/" render={() => <Home />} />
|
||||||
<Route path="/channels" render={() => <ChannelView />} />
|
<Route path="/channels" render={() => <ChannelView />} />
|
||||||
|
<Route path="/pendingChannels" render={() => <PendingChannelView />} />
|
||||||
<Route path="/invoices" render={() => <InvoiceView />} />
|
<Route path="/invoices" render={() => <InvoiceView />} />
|
||||||
<Route path="/settings" render={() => <SettingsView />} />
|
<Route path="/settings" render={() => <SettingsView />} />
|
||||||
<Route path="*" render={() => <NotFound />} />
|
<Route path="*" render={() => <NotFound />} />
|
||||||
|
|
|
@ -39,6 +39,9 @@ export const Navigation = () => {
|
||||||
<p>
|
<p>
|
||||||
<Link to="/channels">Channels</Link>
|
<Link to="/channels">Channels</Link>
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
<Link to="/pendingChannels">Pending Channels</Link>
|
||||||
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<Link to="/invoices">Invoices</Link>
|
<Link to="/invoices">Invoices</Link>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -2,7 +2,7 @@ import theme from "styled-theming";
|
||||||
|
|
||||||
export const backgroundColor = theme("mode", {
|
export const backgroundColor = theme("mode", {
|
||||||
light: "#fafafa",
|
light: "#fafafa",
|
||||||
dark: "#0D0C1D"
|
dark: "#1b1c22"
|
||||||
});
|
});
|
||||||
|
|
||||||
export const textColor = theme("mode", {
|
export const textColor = theme("mode", {
|
||||||
|
@ -12,27 +12,32 @@ export const textColor = theme("mode", {
|
||||||
|
|
||||||
export const cardColor = theme("mode", {
|
export const cardColor = theme("mode", {
|
||||||
light: "white",
|
light: "white",
|
||||||
dark: "#120338"
|
dark: "#25262c"
|
||||||
|
});
|
||||||
|
|
||||||
|
export const subCardColor = theme("mode", {
|
||||||
|
light: "white",
|
||||||
|
dark: "#1b1c22"
|
||||||
});
|
});
|
||||||
|
|
||||||
export const cardBorderColor = theme("mode", {
|
export const cardBorderColor = theme("mode", {
|
||||||
light: "#e6e6e6",
|
light: "#f5f5f5",
|
||||||
dark: "#22075e"
|
dark: "transparent"
|
||||||
});
|
});
|
||||||
|
|
||||||
export const progressBackground = theme("mode", {
|
export const progressBackground = theme("mode", {
|
||||||
light: "rgba(0, 0, 0, 0.05)",
|
light: "rgba(0, 0, 0, 0.05)",
|
||||||
dark: "rgba(0, 0, 0, 0.05)"
|
dark: "rgba(0, 0, 0, 1)"
|
||||||
});
|
});
|
||||||
|
|
||||||
export const progressLeft = theme("mode", {
|
export const progressFirst = theme("mode", {
|
||||||
light: "#faad14",
|
light: "#ffa940",
|
||||||
dark: "#440bd4"
|
dark: "#ffa940"
|
||||||
});
|
});
|
||||||
|
|
||||||
export const progressRight = theme("mode", {
|
export const progressSecond = theme("mode", {
|
||||||
light: "#fadb14",
|
light: "#1890ff",
|
||||||
dark: "#fe6b35"
|
dark: "#1890ff"
|
||||||
});
|
});
|
||||||
|
|
||||||
export const iconButtonColor = theme("mode", {
|
export const iconButtonColor = theme("mode", {
|
||||||
|
@ -49,3 +54,8 @@ export const iconButtonBack = theme("mode", {
|
||||||
light: "#f5f5f5",
|
light: "#f5f5f5",
|
||||||
dark: "#0D0C1D"
|
dark: "#0D0C1D"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const smallLinkColor = theme("mode", {
|
||||||
|
light: "#9254de",
|
||||||
|
dark: "#adc6ff"
|
||||||
|
});
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Channels } from "../../components/channels/Channels";
|
import { Channels } from "../../components/channels/channels/Channels";
|
||||||
|
import { PendingChannels } from "../../components/channels/pendingChannels/PendingChannels";
|
||||||
|
|
||||||
export const ChannelView = () => {
|
export const ChannelView = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Channels />
|
<Channels />
|
||||||
|
<PendingChannels />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
10
src/views/channels/PendingChannels.tsx
Normal file
10
src/views/channels/PendingChannels.tsx
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import React from "react";
|
||||||
|
import { PendingChannels } from "../../components/channels/pendingChannels/PendingChannels";
|
||||||
|
|
||||||
|
export const PendingChannelView = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<PendingChannels />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
Loading…
Add table
Reference in a new issue