From e2065e1c888508ea780fdb7a6abcbf36532ee11c Mon Sep 17 00:00:00 2001 From: Anthony Potdevin Date: Mon, 8 Aug 2022 22:24:09 -0500 Subject: [PATCH] chore: new view --- src/client/pages/amboss/index.tsx | 40 ++++++ .../src/layouts/navigation/Navigation.tsx | 4 + src/client/src/views/amboss/Backups.tsx | 134 ++++++++++++++++++ src/client/src/views/amboss/Balances.tsx | 92 ++++++++++++ src/client/src/views/amboss/Healthchecks.tsx | 52 +++++++ src/client/src/views/amboss/LoginButton.tsx | 59 ++++++++ .../src/views/tools/backups/Backups.tsx | 89 ------------ 7 files changed, 381 insertions(+), 89 deletions(-) create mode 100644 src/client/pages/amboss/index.tsx create mode 100644 src/client/src/views/amboss/Backups.tsx create mode 100644 src/client/src/views/amboss/Balances.tsx create mode 100644 src/client/src/views/amboss/Healthchecks.tsx create mode 100644 src/client/src/views/amboss/LoginButton.tsx diff --git a/src/client/pages/amboss/index.tsx b/src/client/pages/amboss/index.tsx new file mode 100644 index 00000000..f1690d11 --- /dev/null +++ b/src/client/pages/amboss/index.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { GridWrapper } from '../../src/components/gridWrapper/GridWrapper'; +import { SingleLine } from '../../src/components/generic/Styled'; +import { NextPageContext } from 'next'; +import { getProps } from '../../src/utils/ssr'; +import { AmbossLoginButton } from '../../src/views/amboss/LoginButton'; +import { Backups } from '../../src/views/amboss/Backups'; +import { SectionTitle, Text } from '../../src/components/typography/Styled'; +import { Healthchecks } from '../../src/views/amboss/Healthchecks'; +import { Balances } from '../../src/views/amboss/Balances'; + +const AmbossView = () => ( + <> + + + AMBOSS + + + + + Amboss offers different integration options that can help you monitor your + node, store backups and get historical graphs about your balances. + + +); + +const Wrapped = () => ( + + + + + + +); + +export default Wrapped; + +export async function getServerSideProps(context: NextPageContext) { + return await getProps(context); +} diff --git a/src/client/src/layouts/navigation/Navigation.tsx b/src/client/src/layouts/navigation/Navigation.tsx index e2cb5223..4fdd8e7f 100644 --- a/src/client/src/layouts/navigation/Navigation.tsx +++ b/src/client/src/layouts/navigation/Navigation.tsx @@ -15,6 +15,7 @@ import { Heart, Shuffle, Grid, + Globe, } from 'react-feather'; import { useRouter } from 'next/router'; import { useBaseConnect } from '../../hooks/UseBaseConnect'; @@ -135,6 +136,7 @@ const DONATIONS = '/leaderboard'; const CHAT = '/chat'; const SETTINGS = '/settings'; const SWAP = '/swap'; +const AMBOSS = '/amboss'; interface NavigationProps { isBurger?: boolean; @@ -185,6 +187,7 @@ export const Navigation = ({ isBurger, setOpen }: NavigationProps) => { {renderNavButton('Transactions', TRANS, Server, sidebar)} {renderNavButton('Forwards', FORWARDS, GitPullRequest, sidebar)} {renderNavButton('Chain', CHAIN_TRANS, LinkIcon, sidebar)} + {renderNavButton('Amboss', AMBOSS, Globe, sidebar)} {renderNavButton('Tools', TOOLS, Shield, sidebar)} {renderNavButton('Swap', SWAP, Shuffle, sidebar)} {renderNavButton('Stats', STATS, BarChart2, sidebar)} @@ -201,6 +204,7 @@ export const Navigation = ({ isBurger, setOpen }: NavigationProps) => { {renderBurgerNav('Transactions', TRANS, Server)} {renderBurgerNav('Forwards', FORWARDS, GitPullRequest)} {renderBurgerNav('Chain', CHAIN_TRANS, LinkIcon)} + {renderBurgerNav('Amboss', AMBOSS, Globe)} {renderBurgerNav('Tools', TOOLS, Shield)} {renderBurgerNav('Swap', SWAP, Shuffle)} {renderBurgerNav('Stats', STATS, BarChart2)} diff --git a/src/client/src/views/amboss/Backups.tsx b/src/client/src/views/amboss/Backups.tsx new file mode 100644 index 00000000..490ed92c --- /dev/null +++ b/src/client/src/views/amboss/Backups.tsx @@ -0,0 +1,134 @@ +import { ColorButton } from '../../components/buttons/colorButton/ColorButton'; +import { + Card, + CardWithTitle, + SubTitle, + Separation, + SingleLine, + DarkSubTitle, +} from '../../components/generic/Styled'; +import { Text } from '../../components/typography/Styled'; +import numeral from 'numeral'; +import { toast } from 'react-toastify'; +import { usePushBackupMutation } from '../../graphql/mutations/__generated__/pushBackup.generated'; +import { getErrorContent } from '../../utils/error'; +import { useAmbossUser } from '../../hooks/UseAmbossUser'; +import { getFormatDate, renderLine } from '../../components/generic/helpers'; +import { useToggleConfigMutation } from '../../graphql/mutations/__generated__/toggleConfig.generated'; +import { useGetConfigStateQuery } from '../../graphql/queries/__generated__/getConfigState.generated'; +import { ConfigFields } from '../../graphql/types'; + +const PushBackup = () => { + const [backup, { loading }] = usePushBackupMutation({ + onCompleted: () => toast.success('Backup saved on Amboss'), + onError: error => toast.error(getErrorContent(error)), + refetchQueries: ['GetAmbossUser'], + }); + + return ( + + Push Backup to Amboss + backup()} + loading={loading} + > + Push + + + ); +}; + +export const AmbossBackupsView = () => { + const { user } = useAmbossUser(); + + const renderContent = () => { + if (!user) return null; + + const { + backups: { + remaining_size, + total_size_saved, + last_update, + last_update_size, + }, + } = user; + + const total = Number(total_size_saved) / 1e6; + const remaining = Number(remaining_size) / 1e6; + + return ( + <> + {renderLine( + 'Last Update', + last_update + ? getFormatDate(last_update) + : 'No backups done this month' + )} + {last_update_size + ? renderLine('Last Update Size', `${last_update_size} bytes`) + : null} + + {renderLine( + 'Total Size Saved', + `${numeral(total).format('0.[0000]')} MB` + )} + {renderLine( + 'Remaining Size Available', + `${numeral(remaining).format('0.[0000]')} MB` + )} + + + ); + }; + + return ( + <> + + {renderContent()} + + + ); +}; + +export const Backups = () => { + const { data, loading } = useGetConfigStateQuery({ + onError: err => toast.error(getErrorContent(err)), + }); + + const [toggle, { loading: toggleLoading }] = useToggleConfigMutation({ + refetchQueries: ['GetConfigState'], + onError: err => toast.error(getErrorContent(err)), + }); + + const isEnabled = data?.getConfigState.backup_state || false; + + return ( + + Backups + + + + {isEnabled + ? 'By disabling automatic backups to Amboss, ThunderHub will no longer push encrypted backups.' + : 'By enabling automatic backups to Amboss, ThunderHub will automatically push an encrypted version of your static channel backups (SCB) whenever there is a change that needs backing up.'} + + + toggle({ variables: { field: ConfigFields.Backups } }) + } + > + {isEnabled ? 'Disable' : 'Enable'} + + + + + + ); +}; diff --git a/src/client/src/views/amboss/Balances.tsx b/src/client/src/views/amboss/Balances.tsx new file mode 100644 index 00000000..c3555347 --- /dev/null +++ b/src/client/src/views/amboss/Balances.tsx @@ -0,0 +1,92 @@ +import { toast } from 'react-toastify'; +import { ColorButton } from '../../components/buttons/colorButton/ColorButton'; +import { + Card, + CardWithTitle, + Separation, + SingleLine, + SubTitle, +} from '../../components/generic/Styled'; +import { Text } from '../../components/typography/Styled'; +import { useToggleConfigMutation } from '../../graphql/mutations/__generated__/toggleConfig.generated'; +import { useGetConfigStateQuery } from '../../graphql/queries/__generated__/getConfigState.generated'; +import { ConfigFields } from '../../graphql/types'; +import { getErrorContent } from '../../utils/error'; + +export const Balances = () => { + const { data, loading } = useGetConfigStateQuery({ + onError: err => toast.error(getErrorContent(err)), + }); + + const [toggle, { loading: toggleLoading }] = useToggleConfigMutation({ + refetchQueries: ['GetConfigState'], + onError: err => toast.error(getErrorContent(err)), + }); + + const { + onchain_push_enabled = false, + channels_push_enabled = false, + private_channels_push_enabled = false, + } = data?.getConfigState || {}; + + return ( + + Balances + + + Push Onchain + + toggle({ variables: { field: ConfigFields.OnchainPush } }) + } + > + {onchain_push_enabled ? 'Disable' : 'Enable'} + + + + Push your onchain balance to Amboss to get historical reports. + + + + Push Public Channels + + toggle({ variables: { field: ConfigFields.ChannelsPush } }) + } + > + {channels_push_enabled ? 'Disable' : 'Enable'} + + + + Push your public channel balances to get historical reports. + + + + Push Private Channels + + toggle({ variables: { field: ConfigFields.PrivateChannelsPush } }) + } + > + {private_channels_push_enabled ? 'Disable' : 'Enable'} + + + + Push your private channel balances to get historical reports. + + + + ); +}; diff --git a/src/client/src/views/amboss/Healthchecks.tsx b/src/client/src/views/amboss/Healthchecks.tsx new file mode 100644 index 00000000..f068b774 --- /dev/null +++ b/src/client/src/views/amboss/Healthchecks.tsx @@ -0,0 +1,52 @@ +import { toast } from 'react-toastify'; +import { ColorButton } from '../../components/buttons/colorButton/ColorButton'; +import { + Card, + CardWithTitle, + SingleLine, + SubTitle, +} from '../../components/generic/Styled'; +import { Text } from '../../components/typography/Styled'; +import { useToggleConfigMutation } from '../../graphql/mutations/__generated__/toggleConfig.generated'; +import { useGetConfigStateQuery } from '../../graphql/queries/__generated__/getConfigState.generated'; +import { ConfigFields } from '../../graphql/types'; +import { getErrorContent } from '../../utils/error'; + +export const Healthchecks = () => { + const { data, loading } = useGetConfigStateQuery({ + onError: err => toast.error(getErrorContent(err)), + }); + + const [toggle, { loading: toggleLoading }] = useToggleConfigMutation({ + refetchQueries: ['GetConfigState'], + onError: err => toast.error(getErrorContent(err)), + }); + + const isEnabled = data?.getConfigState.healthcheck_ping_state || false; + + return ( + + Healthchecks + + + + {isEnabled + ? 'By disabling automatic healthcheck pings to Amboss, ThunderHub will no longer ping Amboss.' + : 'By enabling automatic healthcheck pings to Amboss, ThunderHub will consistently ping Amboss to show the liveliness of your node.'} + + + toggle({ variables: { field: ConfigFields.Healthchecks } }) + } + > + {isEnabled ? 'Disable' : 'Enable'} + + + + + ); +}; diff --git a/src/client/src/views/amboss/LoginButton.tsx b/src/client/src/views/amboss/LoginButton.tsx new file mode 100644 index 00000000..1cc0d031 --- /dev/null +++ b/src/client/src/views/amboss/LoginButton.tsx @@ -0,0 +1,59 @@ +import { useEffect } from 'react'; +import { toast } from 'react-toastify'; +import { useAmbossUser } from '../../hooks/UseAmbossUser'; +import { useLoginAmbossMutation } from '../../graphql/mutations/__generated__/loginAmboss.generated'; +import { useGetAmbossLoginTokenLazyQuery } from '../../graphql/queries/__generated__/getAmbossLoginToken.generated'; +import { ColorButton } from '../../components/buttons/colorButton/ColorButton'; + +export const AmbossLoginButton = () => { + const { user } = useAmbossUser(); + + const [login, { loading }] = useLoginAmbossMutation({ + onCompleted: () => toast.success('Logged in'), + onError: () => toast.error('Error logging in'), + refetchQueries: ['GetAmbossUser', 'GetChannels'], + }); + + const [getToken, { data, loading: tokenLoading }] = + useGetAmbossLoginTokenLazyQuery({ + fetchPolicy: 'network-only', + onError: () => toast.error('Error getting auth token'), + }); + + useEffect(() => { + if (!data?.getAmbossLoginToken || tokenLoading) { + return; + } + if (!window?.open) return; + const url = `https://amboss.space/token?key=${data.getAmbossLoginToken}`; + (window as any).open(url, '_blank').focus(); + }, [data, tokenLoading]); + + if (!user) { + return ( + { + if (loading) return; + login(); + }} + disabled={loading} + > + {loading ? 'Loading...' : 'Login'} + + ); + } + + return ( + { + if (tokenLoading) return; + getToken(); + }} + disabled={tokenLoading} + > + {tokenLoading ? 'Loading...' : 'Go To'} + + ); +}; diff --git a/src/client/src/views/tools/backups/Backups.tsx b/src/client/src/views/tools/backups/Backups.tsx index bbf66d27..f9954513 100644 --- a/src/client/src/views/tools/backups/Backups.tsx +++ b/src/client/src/views/tools/backups/Backups.tsx @@ -4,104 +4,15 @@ import { CardTitle, SubTitle, Card, - Separation, - SingleLine, - DarkSubTitle, } from '../../../components/generic/Styled'; import { DownloadBackups } from './DownloadBackups'; import { VerifyBackups } from './VerifyBackups'; import { RecoverFunds } from './RecoverFunds'; import { VerifyBackup } from './VerifyBackup'; -import { useAmbossUser } from '../../../hooks/UseAmbossUser'; -import { getFormatDate, renderLine } from '../../../components/generic/helpers'; -import numeral from 'numeral'; -import { ColorButton } from '../../../components/buttons/colorButton/ColorButton'; -import { usePushBackupMutation } from '../../../graphql/mutations/__generated__/pushBackup.generated'; -import { getErrorContent } from '../../../utils/error'; -import { toast } from 'react-toastify'; - -const PushBackup = () => { - const [backup, { loading }] = usePushBackupMutation({ - onCompleted: () => toast.success('Backup saved on Amboss'), - onError: error => toast.error(getErrorContent(error)), - refetchQueries: ['GetAmbossUser'], - }); - - return ( - - Push Backup to Amboss - backup()} - loading={loading} - > - Push - - - ); -}; - -const AmbossBackupsView = () => { - const { user } = useAmbossUser(); - - const renderContent = () => { - if (!user) return null; - - const { - backups: { - remaining_size, - total_size_saved, - last_update, - last_update_size, - }, - } = user; - - const total = Number(total_size_saved) / 1e6; - const remaining = Number(remaining_size) / 1e6; - - return ( - <> - {renderLine( - 'Last Update', - last_update - ? getFormatDate(last_update) - : 'No backups done this month' - )} - {last_update_size - ? renderLine('Last Update Size', `${last_update_size} bytes`) - : null} - - {renderLine( - 'Total Size Saved', - `${numeral(total).format('0.[0000]')} MB` - )} - {renderLine( - 'Remaining Size Available', - `${numeral(remaining).format('0.[0000]')} MB` - )} - - - ); - }; - - return ( - - - Amboss Backups - - - {renderContent()} - - - - ); -}; export const BackupsView = () => { return ( <> - Backups