chore: changes and config for ssr and nextjs (#26)

* test: change docker to yarn

* test: change api handler url

* fix: image imports in public folder

* fix: add path prefix to links

* chore: update deps

* chore: small fixes

* chore: remove prefetch flag

* chore: remove use size hook

* Revert "chore: remove prefetch flag"

This reverts commit ae7ee3bc23.
This commit is contained in:
Anthony Potdevin 2020-04-16 10:57:22 +02:00 committed by GitHub
parent cd313fbae2
commit 83d9b20205
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 942 additions and 609 deletions

View file

@ -1,20 +1,17 @@
FROM node:11-alpine FROM node:12-alpine
# Create app directory # Create app directory
WORKDIR /usr/src/app WORKDIR /usr/src/app
RUN apk update && apk upgrade \
&& apk --no-cache add --virtual builds-deps build-base python \
&& npm install node-gyp node-pre-gyp
# Install app dependencies # Install app dependencies
COPY package.json /usr/src/app/ COPY package.json /usr/src/app/
RUN npm install --only=prod COPY yarn.lock /usr/src/app/
RUN npm install cross-env RUN yarn --production=true
RUN yarn add cross-env
# Bundle app source # Bundle app source
COPY . /usr/src/app COPY . /usr/src/app
RUN npm run build RUN yarn build
EXPOSE 3000 EXPOSE 3000
CMD [ "npm", "start" ] CMD [ "yarn", "start" ]

View file

@ -14,6 +14,7 @@ module.exports = withBundleAnalyzer({
publicRuntimeConfig: { publicRuntimeConfig: {
nodeEnv: process.env.NODE_ENV || 'development', nodeEnv: process.env.NODE_ENV || 'development',
apiUrl: `${process.env.BASE_PATH || ''}/api/v1`, apiUrl: `${process.env.BASE_PATH || ''}/api/v1`,
apiBaseUrl: `${process.env.API_BASE_URL || ''}/api/v1`,
basePath: process.env.BASE_PATH || '', basePath: process.env.BASE_PATH || '',
npmVersion: process.env.npm_package_version || '0.0.0', npmVersion: process.env.npm_package_version || '0.0.0',
}, },

View file

@ -18,7 +18,7 @@
"author": "", "author": "",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@apollo/react-hooks": "^3.1.4", "@apollo/react-hooks": "^3.1.5",
"apollo-boost": "^0.4.7", "apollo-boost": "^0.4.7",
"apollo-server-micro": "^2.12.0", "apollo-server-micro": "^2.12.0",
"base64url": "^3.0.1", "base64url": "^3.0.1",
@ -29,14 +29,14 @@
"graphql-iso-date": "^3.6.1", "graphql-iso-date": "^3.6.1",
"graphql-rate-limit": "^2.0.1", "graphql-rate-limit": "^2.0.1",
"graphql-tag": "^2.10.3", "graphql-tag": "^2.10.3",
"intersection-observer": "^0.7.0", "intersection-observer": "^0.8.0",
"isomorphic-unfetch": "^3.0.0", "isomorphic-unfetch": "^3.0.0",
"ln-service": "^47.16.0", "ln-service": "^47.16.0",
"lodash.debounce": "^4.0.8", "lodash.debounce": "^4.0.8",
"lodash.merge": "^4.6.2", "lodash.merge": "^4.6.2",
"micro-cors": "^0.1.1", "micro-cors": "^0.1.1",
"next": "^9.3.4", "next": "^9.3.5",
"next-with-apollo": "^5.0.0", "next-with-apollo": "^5.0.1",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"qrcode.react": "^1.0.0", "qrcode.react": "^1.0.0",
"react": "^16.13.1", "react": "^16.13.1",
@ -47,7 +47,7 @@
"react-spinners": "^0.8.1", "react-spinners": "^0.8.1",
"react-spring": "^8.0.27", "react-spring": "^8.0.27",
"react-toastify": "^5.5.0", "react-toastify": "^5.5.0",
"react-tooltip": "^4.2.2", "react-tooltip": "^4.2.3",
"styled-components": "^5.1.0", "styled-components": "^5.1.0",
"styled-react-modal": "^2.0.1", "styled-react-modal": "^2.0.1",
"styled-theming": "^2.2.0", "styled-theming": "^2.2.0",
@ -61,7 +61,7 @@
"@babel/core": "^7.9.0", "@babel/core": "^7.9.0",
"@commitlint/cli": "^8.3.5", "@commitlint/cli": "^8.3.5",
"@commitlint/config-conventional": "^8.3.4", "@commitlint/config-conventional": "^8.3.4",
"@next/bundle-analyzer": "^9.3.4", "@next/bundle-analyzer": "^9.3.5",
"@storybook/addon-actions": "^5.3.18", "@storybook/addon-actions": "^5.3.18",
"@storybook/addon-knobs": "^5.3.18", "@storybook/addon-knobs": "^5.3.18",
"@storybook/addon-viewport": "^5.3.18", "@storybook/addon-viewport": "^5.3.18",

View file

@ -21,6 +21,7 @@ import {
} from '../src/components/stateViews/StateCards'; } from '../src/components/stateViews/StateCards';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css'; import 'react-toastify/dist/ReactToastify.css';
import Head from 'next/head';
toast.configure({ draggable: false }); toast.configure({ draggable: false });
@ -30,7 +31,7 @@ const Wrapper: React.FC = ({ children }) => {
const { theme } = useSettings(); const { theme } = useSettings();
const { loggedIn } = useAccount(); const { loggedIn } = useAccount();
const { pathname } = useRouter(); const { pathname } = useRouter();
const { connected, loading, error } = useConnectionState(); const { loading, error } = useConnectionState();
const isInArray = withoutGrid.includes(pathname); const isInArray = withoutGrid.includes(pathname);
@ -64,13 +65,18 @@ class MyApp extends App<any> {
render() { render() {
const { Component, pageProps, apollo } = this.props; const { Component, pageProps, apollo } = this.props;
return ( return (
<ApolloProvider client={apollo}> <>
<ContextProvider> <Head>
<Wrapper> <title>ThunderHub - Lightning Node Manager</title>
<Component {...pageProps} /> </Head>
</Wrapper> <ApolloProvider client={apollo}>
</ContextProvider> <ContextProvider>
</ApolloProvider> <Wrapper>
<Component {...pageProps} />
</Wrapper>
</ContextProvider>
</ApolloProvider>
</>
); );
} }
} }

View file

@ -37,7 +37,6 @@ export default class MyDocument extends Document {
return ( return (
<Html> <Html>
<Head> <Head>
<title>ThunderHub - Lightning Node Manager</title>
<meta <meta
name="viewport" name="viewport"
content="initial-scale=1.0, width=device-width" content="initial-scale=1.0, width=device-width"

View file

@ -5,7 +5,7 @@ import getConfig from 'next/config';
import Cors from 'micro-cors'; import Cors from 'micro-cors';
const { publicRuntimeConfig } = getConfig(); const { publicRuntimeConfig } = getConfig();
const { apiUrl } = publicRuntimeConfig; const { apiBaseUrl } = publicRuntimeConfig;
const cors = Cors({ const cors = Cors({
origin: true, origin: true,
@ -19,7 +19,7 @@ const apolloServer = new ApolloServer({
}, },
}); });
const handler = apolloServer.createHandler({ path: apiUrl }); const handler = apolloServer.createHandler({ path: apiBaseUrl });
export const config = { export const config = {
api: { api: {

View file

@ -4,6 +4,7 @@ import { useAccount } from '../src/context/AccountContext';
import { SessionLogin } from '../src/views/login/SessionLogin'; import { SessionLogin } from '../src/views/login/SessionLogin';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { HomePageView } from '../src/views/homepage/HomePage'; import { HomePageView } from '../src/views/homepage/HomePage';
import { appendBasePath } from '../src/utils/basePath';
const ContextApp: React.FC = () => { const ContextApp: React.FC = () => {
const { push } = useRouter(); const { push } = useRouter();
@ -11,7 +12,7 @@ const ContextApp: React.FC = () => {
if (loggedIn) { if (loggedIn) {
if (admin === '' || viewOnly !== '' || sessionAdmin !== '') { if (admin === '' || viewOnly !== '' || sessionAdmin !== '') {
push('/home'); push(appendBasePath('/home'));
} }
} }

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 54 KiB

View file

@ -12,6 +12,7 @@ import { useStatusDispatch } from '../../context/StatusContext';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { LoadingCard } from '../loading/LoadingCard'; import { LoadingCard } from '../loading/LoadingCard';
import { appendBasePath } from '../../utils/basePath';
const PasswordInput = dynamic(() => import('./views/Password'), { const PasswordInput = dynamic(() => import('./views/Password'), {
ssr: false, ssr: false,
@ -114,7 +115,7 @@ export const Auth = ({ type, status, callback, setStatus }: AuthProps) => {
dispatchState({ type: 'disconnected' }); dispatchState({ type: 'disconnected' });
changeAccount(id); changeAccount(id);
push('/'); push(appendBasePath('/'));
}; };
const handleSave = () => { const handleSave = () => {
@ -143,7 +144,7 @@ export const Auth = ({ type, status, callback, setStatus }: AuthProps) => {
dispatchState({ type: 'disconnected' }); dispatchState({ type: 'disconnected' });
changeAccount(id); changeAccount(id);
push('/'); push(appendBasePath('/'));
} }
}; };

View file

@ -10,14 +10,17 @@ import {
colorButtonBorderTwo, colorButtonBorderTwo,
hoverTextColor, hoverTextColor,
themeColors, themeColors,
mediaWidths,
} from '../../../styles/Themes'; } from '../../../styles/Themes';
import { ChevronRight } from '../../generic/Icons'; import { ChevronRight } from '../../generic/Icons';
import ScaleLoader from 'react-spinners/ScaleLoader'; import ScaleLoader from 'react-spinners/ScaleLoader';
interface GeneralProps { interface GeneralProps {
fullWidth?: boolean; fullWidth?: boolean;
mobileFullWidth?: boolean;
buttonWidth?: string; buttonWidth?: string;
withMargin?: string; withMargin?: string;
mobileMargin?: string;
} }
const GeneralButton = styled.button` const GeneralButton = styled.button`
@ -35,6 +38,29 @@ const GeneralButton = styled.button`
margin: ${({ withMargin }) => (withMargin ? withMargin : '0')}; margin: ${({ withMargin }) => (withMargin ? withMargin : '0')};
width: ${({ fullWidth, buttonWidth }: GeneralProps) => width: ${({ fullWidth, buttonWidth }: GeneralProps) =>
fullWidth ? '100%' : buttonWidth ? buttonWidth : 'auto'}; fullWidth ? '100%' : buttonWidth ? buttonWidth : 'auto'};
@media (${mediaWidths.mobile}) {
${({ withMargin, mobileMargin }) =>
mobileMargin
? css`
margin: ${mobileMargin};
`
: withMargin
? css`
margin: ${withMargin};
`
: '0'};
${({ fullWidth, mobileFullWidth }) =>
mobileFullWidth
? css`
width: 100%;
`
: fullWidth
? css`
width: 100%;
`
: ''};
}
`; `;
const StyledArrow = styled.div` const StyledArrow = styled.div`
@ -97,8 +123,10 @@ export interface ColorButtonProps {
arrow?: boolean; arrow?: boolean;
onClick?: any; onClick?: any;
withMargin?: string; withMargin?: string;
mobileMargin?: string;
withBorder?: boolean; withBorder?: boolean;
fullWidth?: boolean; fullWidth?: boolean;
mobileFullWidth?: boolean;
width?: string; width?: string;
} }
@ -110,8 +138,10 @@ export const ColorButton = ({
selected, selected,
arrow, arrow,
withMargin, withMargin,
mobileMargin,
withBorder, withBorder,
fullWidth, fullWidth,
mobileFullWidth,
width, width,
onClick, onClick,
}: ColorButtonProps) => { }: ColorButtonProps) => {
@ -119,7 +149,9 @@ export const ColorButton = ({
return ( return (
<DisabledButton <DisabledButton
withMargin={withMargin} withMargin={withMargin}
mobileMargin={mobileMargin}
fullWidth={fullWidth} fullWidth={fullWidth}
mobileFullWidth={mobileFullWidth}
buttonWidth={width} buttonWidth={width}
> >
{children} {children}
@ -132,7 +164,9 @@ export const ColorButton = ({
return ( return (
<DisabledButton <DisabledButton
withMargin={withMargin} withMargin={withMargin}
mobileMargin={mobileMargin}
fullWidth={fullWidth} fullWidth={fullWidth}
mobileFullWidth={mobileFullWidth}
buttonWidth={width} buttonWidth={width}
> >
<ScaleLoader height={16} color={themeColors.blue2} /> <ScaleLoader height={16} color={themeColors.blue2} />
@ -146,8 +180,10 @@ export const ColorButton = ({
selected={selected} selected={selected}
onClick={onClick} onClick={onClick}
withMargin={withMargin} withMargin={withMargin}
mobileMargin={mobileMargin}
withBorder={withBorder} withBorder={withBorder}
fullWidth={fullWidth} fullWidth={fullWidth}
mobileFullWidth={mobileFullWidth}
buttonWidth={width} buttonWidth={width}
> >
{children} {children}

View file

@ -12,10 +12,9 @@ import styled from 'styled-components';
import { useAccount } from '../../../context/AccountContext'; import { useAccount } from '../../../context/AccountContext';
import { saveSessionAuth } from '../../../utils/auth'; import { saveSessionAuth } from '../../../utils/auth';
import { useSettings } from '../../../context/SettingsContext'; import { useSettings } from '../../../context/SettingsContext';
import { textColorMap, mediaDimensions } from '../../../styles/Themes'; import { textColorMap } from '../../../styles/Themes';
import { ColorButton } from '../colorButton/ColorButton'; import { ColorButton } from '../colorButton/ColorButton';
import { Input } from '../../input/Input'; import { Input } from '../../input/Input';
import { useSize } from '../../../hooks/UseSize';
const RadioText = styled.div` const RadioText = styled.div`
margin-left: 10px; margin-left: 10px;
@ -43,7 +42,6 @@ export const LoginModal = ({
callback, callback,
variables, variables,
}: LoginProps) => { }: LoginProps) => {
const { width } = useSize();
const { theme } = useSettings(); const { theme } = useSettings();
const [pass, setPass] = useState<string>(''); const [pass, setPass] = useState<string>('');
@ -84,7 +82,8 @@ export const LoginModal = ({
<ResponsiveLine> <ResponsiveLine>
<Sub4Title>Password:</Sub4Title> <Sub4Title>Password:</Sub4Title>
<Input <Input
withMargin={width <= mediaDimensions.mobile ? '0' : '0 0 0 16px'} withMargin={'0 0 0 16px'}
mobileMargin={'0'}
type={'password'} type={'password'}
onChange={e => setPass(e.target.value)} onChange={e => setPass(e.target.value)}
/> />

View file

@ -11,6 +11,7 @@ interface SecureButtonProps extends ColorButtonProps {
variables: {}; variables: {};
color?: string; color?: string;
withMargin?: string; withMargin?: string;
mobileMargin?: string;
arrow?: boolean; arrow?: boolean;
} }

View file

@ -6,10 +6,8 @@ import {
import { useQuery } from '@apollo/react-hooks'; import { useQuery } from '@apollo/react-hooks';
import { useAccount } from '../../context/AccountContext'; import { useAccount } from '../../context/AccountContext';
import { GET_CAN_CONNECT } from '../../graphql/query'; import { GET_CAN_CONNECT } from '../../graphql/query';
import { useRouter } from 'next/router';
export const ConnectionCheck = () => { export const ConnectionCheck = () => {
const { push } = useRouter();
const { connected } = useConnectionState(); const { connected } = useConnectionState();
const dispatch = useConnectionDispatch(); const dispatch = useConnectionDispatch();
@ -20,10 +18,6 @@ export const ConnectionCheck = () => {
cert, cert,
}; };
// useEffect(() => {
// !loggedIn && push('/');
// }, [loggedIn]);
const { data, loading } = useQuery(GET_CAN_CONNECT, { const { data, loading } = useQuery(GET_CAN_CONNECT, {
variables: { auth }, variables: { auth },
skip: connected || !loggedIn, skip: connected || !loggedIn,

View file

@ -28,6 +28,7 @@ export const CardTitle = styled.div`
export interface CardProps { export interface CardProps {
bottom?: string; bottom?: string;
cardPadding?: string; cardPadding?: string;
mobileCardPadding?: string;
} }
export const Card = styled.div` export const Card = styled.div`
@ -38,6 +39,19 @@ export const Card = styled.div`
border: 1px solid ${cardBorderColor}; border: 1px solid ${cardBorderColor};
margin-bottom: ${({ bottom }: CardProps) => (bottom ? bottom : '25px')}; margin-bottom: ${({ bottom }: CardProps) => (bottom ? bottom : '25px')};
width: 100%; width: 100%;
@media (${mediaWidths.mobile}) {
${({ cardPadding, mobileCardPadding }) =>
mobileCardPadding
? css`
margin: ${mobileCardPadding};
`
: cardPadding
? css`
margin: ${cardPadding};
`
: ''};
}
`; `;
interface SeparationProps { interface SeparationProps {

View file

@ -5,13 +5,15 @@ import {
colorButtonBorder, colorButtonBorder,
inputBackgroundColor, inputBackgroundColor,
inputBorderColor, inputBorderColor,
mediaWidths,
} from '../../styles/Themes'; } from '../../styles/Themes';
interface InputProps { interface InputProps {
color?: string; color?: string;
withMargin?: string; withMargin?: string;
mobileMargin?: string;
fullWidth?: boolean; fullWidth?: boolean;
inputWidth?: string; mobileFullWidth?: boolean;
maxWidth?: string; maxWidth?: string;
} }
@ -30,10 +32,32 @@ export const StyledInput = styled.input`
css` css`
max-width: ${maxWidth}; max-width: ${maxWidth};
`} `}
width: ${({ fullWidth, inputWidth }: InputProps) => width: ${({ fullWidth }: InputProps) => (fullWidth ? '100%' : 'auto')};
fullWidth ? '100%' : inputWidth ? inputWidth : 'auto'};
margin: ${({ withMargin }) => (withMargin ? withMargin : '0')}; margin: ${({ withMargin }) => (withMargin ? withMargin : '0')};
@media (${mediaWidths.mobile}) {
${({ withMargin, mobileMargin }) =>
mobileMargin
? css`
margin: ${mobileMargin};
`
: withMargin
? css`
margin: ${withMargin};
`
: ''};
${({ fullWidth, mobileFullWidth }) =>
mobileFullWidth
? css`
width: 100%;
`
: fullWidth
? css`
width: 100%;
`
: ''};
}
&:hover { &:hover {
border: 1px solid border: 1px solid
${({ color }: InputProps) => (color ? color : colorButtonBorder)}; ${({ color }: InputProps) => (color ? color : colorButtonBorder)};
@ -52,8 +76,9 @@ interface InputCompProps {
placeholder?: string; placeholder?: string;
color?: string; color?: string;
withMargin?: string; withMargin?: string;
mobileMargin?: string;
fullWidth?: boolean; fullWidth?: boolean;
width?: string; mobileFullWidth?: boolean;
maxWidth?: string; maxWidth?: string;
onChange: (e: any) => void; onChange: (e: any) => void;
} }
@ -64,8 +89,9 @@ export const Input = ({
placeholder, placeholder,
color, color,
withMargin, withMargin,
mobileMargin,
mobileFullWidth,
fullWidth = true, fullWidth = true,
width,
maxWidth, maxWidth,
onChange, onChange,
}: InputCompProps) => { }: InputCompProps) => {
@ -76,9 +102,10 @@ export const Input = ({
value={value} value={value}
color={color} color={color}
withMargin={withMargin} withMargin={withMargin}
mobileMargin={mobileMargin}
onChange={e => onChange(e)} onChange={e => onChange(e)}
fullWidth={fullWidth} fullWidth={fullWidth}
inputWidth={width} mobileFullWidth={mobileFullWidth}
maxWidth={maxWidth} maxWidth={maxWidth}
/> />
); );

View file

@ -77,8 +77,13 @@ export const Link = ({
); );
} }
const linkProps = {
href: `${basePath}${to}`,
...(basePath !== '' ? { prefetch: false } : {}),
};
return ( return (
<RouterLink href={`${basePath}${to}`}> <RouterLink {...linkProps}>
<CorrectLink {...props}>{children}</CorrectLink> <CorrectLink {...props}>{children}</CorrectLink>
</RouterLink> </RouterLink>
); );

View file

@ -0,0 +1,31 @@
import React from 'react';
import styled from 'styled-components';
import { mediaWidths } from '../../styles/Themes';
const HideMobile = styled.div`
@media (${mediaWidths.mobile}) {
display: none;
}
`;
const HideDesktop = styled.div`
display: none;
@media (${mediaWidths.mobile}) {
display: unset;
}
`;
interface ViewSwitchProps {
hideMobile?: boolean;
}
export const ViewSwitch: React.FC<ViewSwitchProps> = ({
hideMobile,
children,
}) => {
return hideMobile ? (
<HideMobile>{children}</HideMobile>
) : (
<HideDesktop>{children}</HideDesktop>
);
};

View file

@ -1,28 +0,0 @@
import { useState, useEffect } from 'react';
import debounce from 'lodash.debounce';
const getSize = () => {
const isClient = typeof window === 'object';
return {
width: isClient ? window.innerWidth : 0,
height: isClient ? window.innerHeight : 0,
};
};
export const useSize = () => {
const [windowSize, setWindowSize] = useState(getSize());
useEffect(() => {
const handleResize = () => {
setWindowSize(getSize());
};
handleResize();
const debouncedHandle = debounce(handleResize, 250);
window.addEventListener('resize', debouncedHandle);
return () => window.removeEventListener('resize', debouncedHandle);
}, []);
return windowSize;
};

View file

@ -0,0 +1,57 @@
import styled, { css } from 'styled-components';
import { headerTextColor, themeColors, mediaWidths } from '../../styles/Themes';
import { SingleLine } from '../../components/generic/Styled';
export const HeaderStyle = styled.div`
padding: 16px 0;
`;
export const IconPadding = styled.div`
padding-right: 6px;
margin-bottom: -4px;
`;
export const HeaderTitle = styled.div`
color: ${headerTextColor};
font-weight: 800;
display: flex;
align-items: center;
justify-content: center;
${({ withPadding }: { withPadding: boolean }) =>
withPadding &&
css`
@media (${mediaWidths.mobile}) {
margin-bottom: 16px;
}
`}
`;
export const IconWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
width: 24px;
height: 24px;
`;
export const LinkWrapper = styled.div`
color: ${headerTextColor};
margin: ${({ last }: { last?: boolean }) =>
last ? '0 16px 0 4px' : '0 4px'};
:hover {
color: ${themeColors.blue2};
}
`;
export const HeaderLine = styled(SingleLine)`
@media (${mediaWidths.mobile}) {
${({ loggedIn }: { loggedIn: boolean }) =>
!loggedIn &&
css`
width: 100%;
flex-direction: column;
`}
}
`;

View file

@ -1,15 +1,8 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import styled, { css } from 'styled-components'; import { headerColor, headerTextColor } from '../../styles/Themes';
import {
headerColor,
headerTextColor,
themeColors,
mediaWidths,
mediaDimensions,
} from '../../styles/Themes';
import { HomeButton } from '../../views/homepage/HomePage.styled'; import { HomeButton } from '../../views/homepage/HomePage.styled';
import { useAccount } from '../../context/AccountContext'; import { useAccount } from '../../context/AccountContext';
import { SingleLine, ResponsiveLine } from '../../components/generic/Styled'; import { SingleLine } from '../../components/generic/Styled';
import { import {
Cpu, Cpu,
MenuIcon, MenuIcon,
@ -18,60 +11,24 @@ import {
Circle, Circle,
} from '../../components/generic/Icons'; } from '../../components/generic/Icons';
import { BurgerMenu } from '../../components/burgerMenu/BurgerMenu'; import { BurgerMenu } from '../../components/burgerMenu/BurgerMenu';
import { useSize } from '../../hooks/UseSize';
import { useTransition, animated } from 'react-spring'; import { useTransition, animated } from 'react-spring';
import { Section } from '../../components/section/Section'; import { Section } from '../../components/section/Section';
import { useStatusState } from '../../context/StatusContext'; import { useStatusState } from '../../context/StatusContext';
import { Link } from '../../components/link/Link'; import { Link } from '../../components/link/Link';
import { ViewSwitch } from '../../components/viewSwitch/ViewSwitch';
const HeaderStyle = styled.div` import {
padding: 16px 0; IconWrapper,
`; LinkWrapper,
HeaderStyle,
const IconPadding = styled.div` HeaderLine,
padding-right: 6px; HeaderTitle,
margin-bottom: -4px; IconPadding,
`; } from './Header.styled';
const HeaderTitle = styled.div`
color: ${headerTextColor};
font-weight: 800;
display: flex;
align-items: center;
justify-content: center;
${({ withPadding }: { withPadding: boolean }) =>
withPadding &&
css`
@media (${mediaWidths.mobile}) {
margin-bottom: 16px;
}
`}
`;
const IconWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
width: 24px;
height: 24px;
`;
const LinkWrapper = styled.div`
color: ${headerTextColor};
margin: ${({ last }: { last?: boolean }) =>
last ? '0 16px 0 4px' : '0 4px'};
:hover {
color: ${themeColors.blue2};
}
`;
const AnimatedBurger = animated(MenuIcon); const AnimatedBurger = animated(MenuIcon);
const AnimatedClose = animated(XSvg); const AnimatedClose = animated(XSvg);
export const Header = () => { export const Header = () => {
const { width } = useSize();
const { loggedIn } = useAccount(); const { loggedIn } = useAccount();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const { syncedToChain } = useStatusState(); const { syncedToChain } = useStatusState();
@ -82,9 +39,9 @@ export const Header = () => {
leave: { opacity: 0 }, leave: { opacity: 0 },
}); });
const renderLoggedIn = () => { const renderLoggedIn = () => (
if (width <= mediaDimensions.mobile) { <>
return ( <ViewSwitch>
<IconWrapper onClick={() => setOpen(prev => !prev)}> <IconWrapper onClick={() => setOpen(prev => !prev)}>
{transitions.map(({ item, key, props }) => {transitions.map(({ item, key, props }) =>
item ? ( item ? (
@ -94,16 +51,16 @@ export const Header = () => {
) )
)} )}
</IconWrapper> </IconWrapper>
); </ViewSwitch>
} <ViewSwitch hideMobile={true}>
return ( <Circle
<Circle size={'12px'}
size={'12px'} strokeWidth={'0'}
strokeWidth={'0'} fillcolor={syncedToChain ? '#95de64' : '#ff7875'}
fillcolor={syncedToChain ? '#95de64' : '#ff7875'} />
/> </ViewSwitch>
); </>
}; );
const renderLoggedOut = () => ( const renderLoggedOut = () => (
<> <>
@ -124,18 +81,13 @@ export const Header = () => {
</> </>
); );
const HeaderWrapper =
width <= mediaDimensions.mobile && !loggedIn ? ResponsiveLine : SingleLine;
return ( return (
<> <>
<Section withColor={true} color={headerColor} textColor={headerTextColor}> <Section withColor={true} color={headerColor} textColor={headerTextColor}>
<HeaderStyle> <HeaderStyle>
<HeaderWrapper> <HeaderLine loggedIn={loggedIn}>
<Link to={loggedIn ? '/home' : '/'} underline={'transparent'}> <Link to={loggedIn ? '/home' : '/'} underline={'transparent'}>
<HeaderTitle <HeaderTitle withPadding={!loggedIn}>
withPadding={width <= mediaDimensions.mobile && !loggedIn}
>
<IconPadding> <IconPadding>
<Cpu color={'white'} /> <Cpu color={'white'} />
</IconPadding> </IconPadding>
@ -145,11 +97,13 @@ export const Header = () => {
<SingleLine> <SingleLine>
{loggedIn ? renderLoggedIn() : renderLoggedOut()} {loggedIn ? renderLoggedIn() : renderLoggedOut()}
</SingleLine> </SingleLine>
</HeaderWrapper> </HeaderLine>
</HeaderStyle> </HeaderStyle>
</Section> </Section>
{open && width <= mediaDimensions.mobile && ( {open && (
<BurgerMenu open={open} setOpen={setOpen} /> <ViewSwitch>
<BurgerMenu open={open} setOpen={setOpen} />
</ViewSwitch>
)} )}
</> </>
); );

6
src/utils/basePath.tsx Normal file
View file

@ -0,0 +1,6 @@
import getConfig from 'next/config';
const { publicRuntimeConfig } = getConfig();
const { basePath } = publicRuntimeConfig;
export const appendBasePath = (url: string): string => `${basePath}${url}`;

View file

@ -1,12 +1,12 @@
import React, { useState, ReactNode } from 'react'; import React, { useState } from 'react';
import { import {
Card, Card,
CardWithTitle, CardWithTitle,
SubTitle, SubTitle,
SingleLine,
Separation, Separation,
DarkSubTitle, DarkSubTitle,
ColorButton, ColorButton,
ResponsiveLine,
} from '../../../components/generic/Styled'; } from '../../../components/generic/Styled';
import styled from 'styled-components'; import styled from 'styled-components';
import { import {
@ -23,9 +23,8 @@ import { SendOnChainCard } from './sendOnChain/SendOnChain';
import { ReceiveOnChainCard } from './receiveOnChain/ReceiveOnChain'; import { ReceiveOnChainCard } from './receiveOnChain/ReceiveOnChain';
import { LoadingCard } from '../../../components/loading/LoadingCard'; import { LoadingCard } from '../../../components/loading/LoadingCard';
import { AdminSwitch } from '../../../components/adminSwitch/AdminSwitch'; import { AdminSwitch } from '../../../components/adminSwitch/AdminSwitch';
import { useSize } from '../../../hooks/UseSize';
import { Price } from '../../../components/price/Price'; import { Price } from '../../../components/price/Price';
import { mediaWidths, mediaDimensions } from '../../../styles/Themes'; import { mediaWidths } from '../../../styles/Themes';
import { useStatusState } from '../../../context/StatusContext'; import { useStatusState } from '../../../context/StatusContext';
const Tile = styled.div` const Tile = styled.div`
@ -34,34 +33,22 @@ const Tile = styled.div`
justify-content: space-between; justify-content: space-between;
align-items: ${({ startTile }: { startTile?: boolean }) => align-items: ${({ startTile }: { startTile?: boolean }) =>
startTile ? 'flex-start' : 'flex-end'}; startTile ? 'flex-start' : 'flex-end'};
@media (${mediaWidths.mobile}) {
width: 100%;
flex-direction: row;
align-items: flex-end;
margin: 0 0 8px;
}
`; `;
const ButtonRow = styled.div` const ButtonRow = styled.div`
display: flex; display: flex;
`; `;
const Responsive = styled(SingleLine)`
@media (${mediaWidths.mobile}) {
flex-direction: column;
}
`;
const sectionColor = '#FFD300'; const sectionColor = '#FFD300';
interface WrapperProps {
width?: number;
children: ReactNode;
}
const ResponsiveWrapper = ({ children, width = 0 }: WrapperProps) => {
if (width <= mediaDimensions.mobile) {
return <Responsive>{children}</Responsive>;
}
return <>{children}</>;
};
export const AccountInfo = () => { export const AccountInfo = () => {
const { width } = useSize();
const [state, setState] = useState<string>('none'); const [state, setState] = useState<string>('none');
const { const {
@ -124,43 +111,41 @@ export const AccountInfo = () => {
const showChain = const showChain =
state === 'send_chain' || state === 'receive_chain' || state === 'none'; state === 'send_chain' || state === 'receive_chain' || state === 'none';
const renderBalances = (current: JSX.Element, pending: JSX.Element) => (
<>
<Tile>
<DarkSubTitle>Current Balance</DarkSubTitle>
<div>{formatCCB}</div>
</Tile>
<Tile>
<DarkSubTitle>Pending Balance</DarkSubTitle>
<div>{formatPCB}</div>
</Tile>
</>
);
const renderButtons = (send: string, receive: string) => (
<>
<ColorButton color={sectionColor} onClick={() => setState(send)}>
<UpArrow />
</ColorButton>
<ColorButton color={sectionColor} onClick={() => setState(receive)}>
<DownArrow />
</ColorButton>
</>
);
const renderLnAccount = () => ( const renderLnAccount = () => (
<SingleLine> <ResponsiveLine>
<ResponsiveWrapper width={width}> <Zap color={channelPending === 0 ? sectionColor : '#652EC7'} />
<Zap color={channelPending === 0 ? sectionColor : '#652EC7'} /> <Tile startTile={true}>
<Tile startTile={true}> <DarkSubTitle>Account</DarkSubTitle>
<DarkSubTitle>Account</DarkSubTitle> <div>Lightning</div>
<div>Lightning</div> </Tile>
</Tile> {renderBalances(formatCCB, formatPCB)}
</ResponsiveWrapper>
<ResponsiveWrapper width={width}>
<Tile>
<DarkSubTitle>Current Balance</DarkSubTitle>
<div>{formatCCB}</div>
</Tile>
<Tile>
<DarkSubTitle>Pending Balance</DarkSubTitle>
<div>{formatPCB}</div>
</Tile>
</ResponsiveWrapper>
<AdminSwitch> <AdminSwitch>
<ButtonRow> <ButtonRow>
{showLn && showChain && ( {showLn && showChain && renderButtons('send_ln', 'receive_ln')}
<ResponsiveWrapper width={width}>
<ColorButton
color={sectionColor}
onClick={() => setState('send_ln')}
>
<UpArrow />
</ColorButton>
<ColorButton
color={sectionColor}
onClick={() => setState('receive_ln')}
>
<DownArrow />
</ColorButton>
</ResponsiveWrapper>
)}
{showLn && !showChain && ( {showLn && !showChain && (
<ColorButton color={sectionColor} onClick={() => setState('none')}> <ColorButton color={sectionColor} onClick={() => setState('none')}>
<XSvg /> <XSvg />
@ -168,46 +153,20 @@ export const AccountInfo = () => {
)} )}
</ButtonRow> </ButtonRow>
</AdminSwitch> </AdminSwitch>
</SingleLine> </ResponsiveLine>
); );
const renderChainAccount = () => ( const renderChainAccount = () => (
<SingleLine> <ResponsiveLine>
<ResponsiveWrapper width={width}> <Anchor color={chainPending === 0 ? sectionColor : '#652EC7'} />
<Anchor color={chainPending === 0 ? sectionColor : '#652EC7'} /> <Tile startTile={true}>
<Tile startTile={true}> <DarkSubTitle>Account</DarkSubTitle>
<DarkSubTitle>Account</DarkSubTitle> <div>Bitcoin</div>
<div>Bitcoin</div> </Tile>
</Tile> {renderBalances(formatCB, formatPB)}
</ResponsiveWrapper>
<ResponsiveWrapper width={width}>
<Tile>
<DarkSubTitle>Current Balance</DarkSubTitle>
<div>{formatCB}</div>
</Tile>
<Tile>
<DarkSubTitle>Pending Balance</DarkSubTitle>
<div>{formatPB}</div>
</Tile>
</ResponsiveWrapper>
<AdminSwitch> <AdminSwitch>
<ButtonRow> <ButtonRow>
{showLn && showChain && ( {showLn && showChain && renderButtons('send_chain', 'receive_chain')}
<ResponsiveWrapper width={width}>
<ColorButton
color={sectionColor}
onClick={() => setState('send_chain')}
>
<UpArrow />
</ColorButton>
<ColorButton
color={sectionColor}
onClick={() => setState('receive_chain')}
>
<DownArrow />
</ColorButton>
</ResponsiveWrapper>
)}
{!showLn && showChain && ( {!showLn && showChain && (
<ColorButton color={sectionColor} onClick={() => setState('none')}> <ColorButton color={sectionColor} onClick={() => setState('none')}>
<XSvg /> <XSvg />
@ -215,7 +174,7 @@ export const AccountInfo = () => {
)} )}
</ButtonRow> </ButtonRow>
</AdminSwitch> </AdminSwitch>
</SingleLine> </ResponsiveLine>
); );
return ( return (
@ -223,7 +182,7 @@ export const AccountInfo = () => {
<CardWithTitle> <CardWithTitle>
<SubTitle>Resume</SubTitle> <SubTitle>Resume</SubTitle>
<Card> <Card>
<SingleLine> <ResponsiveLine>
<Pocket <Pocket
color={ color={
chainPending === 0 && channelPending === 0 chainPending === 0 && channelPending === 0
@ -235,17 +194,8 @@ export const AccountInfo = () => {
<DarkSubTitle>Account</DarkSubTitle> <DarkSubTitle>Account</DarkSubTitle>
<div>Total</div> <div>Total</div>
</Tile> </Tile>
<ResponsiveWrapper width={width}> {renderBalances(totalB, totalPB)}
<Tile> </ResponsiveLine>
<DarkSubTitle>Current Balance</DarkSubTitle>
<div>{totalB}</div>
</Tile>
<Tile>
<DarkSubTitle>Pending Balance</DarkSubTitle>
<div>{totalPB}</div>
</Tile>
</ResponsiveWrapper>
</SingleLine>
</Card> </Card>
</CardWithTitle> </CardWithTitle>
<CardWithTitle> <CardWithTitle>

View file

@ -14,8 +14,7 @@ import QRCode from 'qrcode.react';
import { ColorButton } from '../../../../components/buttons/colorButton/ColorButton'; import { ColorButton } from '../../../../components/buttons/colorButton/ColorButton';
import CopyToClipboard from 'react-copy-to-clipboard'; import CopyToClipboard from 'react-copy-to-clipboard';
import { Input } from '../../../../components/input/Input'; import { Input } from '../../../../components/input/Input';
import { useSize } from '../../../../hooks/UseSize'; import { mediaWidths } from '../../../../styles/Themes';
import { mediaWidths, mediaDimensions } from '../../../../styles/Themes';
const Responsive = styled.div` const Responsive = styled.div`
display: flex; display: flex;
@ -51,7 +50,6 @@ const Column = styled.div`
`; `;
export const CreateInvoiceCard = ({ color }: { color: string }) => { export const CreateInvoiceCard = ({ color }: { color: string }) => {
const { width } = useSize();
const [amount, setAmount] = useState(0); const [amount, setAmount] = useState(0);
const [request, setRequest] = useState(''); const [request, setRequest] = useState('');
@ -90,7 +88,8 @@ export const CreateInvoiceCard = ({ color }: { color: string }) => {
<NoWrapTitle>Amount to receive:</NoWrapTitle> <NoWrapTitle>Amount to receive:</NoWrapTitle>
<Input <Input
placeholder={'Sats'} placeholder={'Sats'}
withMargin={width <= mediaDimensions.mobile ? '0 0 16px' : '0 0 0 24px'} withMargin={'0 0 0 16px'}
mobileMargin={'0 0 16px'}
color={color} color={color}
type={'number'} type={'number'}
onChange={e => setAmount(Number(e.target.value))} onChange={e => setAmount(Number(e.target.value))}
@ -99,10 +98,11 @@ export const CreateInvoiceCard = ({ color }: { color: string }) => {
callback={createInvoice} callback={createInvoice}
variables={{ amount }} variables={{ amount }}
disabled={amount === 0} disabled={amount === 0}
withMargin={width <= mediaDimensions.mobile ? '' : '0 0 0 16px'} withMargin={'0 0 0 16px'}
mobileMargin={'0'}
arrow={true} arrow={true}
loading={loading} loading={loading}
fullWidth={width <= mediaDimensions.mobile} mobileFullWidth={true}
> >
Create Invoice Create Invoice
</SecureButton> </SecureButton>

View file

@ -12,7 +12,6 @@ import { toast } from 'react-toastify';
import { getErrorContent } from '../../../../utils/error'; import { getErrorContent } from '../../../../utils/error';
import { SecureButton } from '../../../../components/buttons/secureButton/SecureButton'; import { SecureButton } from '../../../../components/buttons/secureButton/SecureButton';
import { Input } from '../../../../components/input/Input'; import { Input } from '../../../../components/input/Input';
import { useSize } from '../../../../hooks/UseSize';
import Modal from '../../../../components/modal/ReactModal'; import Modal from '../../../../components/modal/ReactModal';
import { useAccount } from '../../../../context/AccountContext'; import { useAccount } from '../../../../context/AccountContext';
import { ColorButton } from '../../../../components/buttons/colorButton/ColorButton'; import { ColorButton } from '../../../../components/buttons/colorButton/ColorButton';
@ -21,10 +20,8 @@ import {
getNodeLink, getNodeLink,
} from '../../../../components/generic/Helpers'; } from '../../../../components/generic/Helpers';
import { Price } from '../../../../components/price/Price'; import { Price } from '../../../../components/price/Price';
import { mediaDimensions } from '../../../../styles/Themes';
export const PayCard = ({ setOpen }: { setOpen: () => void }) => { export const PayCard = ({ setOpen }: { setOpen: () => void }) => {
const { width } = useSize();
const [request, setRequest] = useState(''); const [request, setRequest] = useState('');
const [modalOpen, setModalOpen] = useState(false); const [modalOpen, setModalOpen] = useState(false);
@ -81,16 +78,16 @@ export const PayCard = ({ setOpen }: { setOpen: () => void }) => {
<Sub4Title>Invoice:</Sub4Title> <Sub4Title>Invoice:</Sub4Title>
<Input <Input
placeholder={'Lightning Invoice'} placeholder={'Lightning Invoice'}
withMargin={ withMargin={'0 0 0 24px'}
width <= mediaDimensions.mobile ? '0 0 16px' : '0 0 0 24px' mobileMargin={'0 0 16px'}
}
onChange={e => setRequest(e.target.value)} onChange={e => setRequest(e.target.value)}
/> />
<ColorButton <ColorButton
disabled={request === ''} disabled={request === ''}
withMargin={width <= mediaDimensions.mobile ? '0' : '0 0 0 16px'} withMargin={'0 0 0 16px'}
mobileMargin={'0'}
loading={decodeLoading} loading={decodeLoading}
fullWidth={width <= mediaDimensions.mobile} mobileFullWidth={true}
onClick={() => { onClick={() => {
decode({ variables: { request, auth } }); decode({ variables: { request, auth } });
}} }}

View file

@ -11,14 +11,12 @@ import styled from 'styled-components';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { getErrorContent } from '../../../../utils/error'; import { getErrorContent } from '../../../../utils/error';
import { SecureButton } from '../../../../components/buttons/secureButton/SecureButton'; import { SecureButton } from '../../../../components/buttons/secureButton/SecureButton';
import { useSize } from '../../../../hooks/UseSize';
import CopyToClipboard from 'react-copy-to-clipboard'; import CopyToClipboard from 'react-copy-to-clipboard';
import { ColorButton } from '../../../../components/buttons/colorButton/ColorButton'; import { ColorButton } from '../../../../components/buttons/colorButton/ColorButton';
import { import {
MultiButton, MultiButton,
SingleButton, SingleButton,
} from '../../../../components/buttons/multiButton/MultiButton'; } from '../../../../components/buttons/multiButton/MultiButton';
import { mediaDimensions } from '../../../../styles/Themes';
const ButtonRow = styled.div` const ButtonRow = styled.div`
width: auto; width: auto;
@ -30,8 +28,6 @@ const TitleWithSpacing = styled(NoWrapTitle)`
`; `;
export const ReceiveOnChainCard = () => { export const ReceiveOnChainCard = () => {
const { width } = useSize();
const [nested, setNested] = useState(false); const [nested, setNested] = useState(false);
const [received, setReceived] = useState(false); const [received, setReceived] = useState(false);
@ -55,11 +51,9 @@ export const ReceiveOnChainCard = () => {
onCopy={() => toast.success('Address Copied')} onCopy={() => toast.success('Address Copied')}
> >
<ColorButton <ColorButton
fullWidth={width <= mediaDimensions.mobile}
arrow={true} arrow={true}
withMargin={ withMargin={'0 0 0 16px'}
width <= mediaDimensions.mobile ? '8px 0 0' : '0 0 0 16px' mobileMargin={'16px 0 0'}
}
> >
Copy Copy
</ColorButton> </ColorButton>
@ -93,12 +87,11 @@ export const ReceiveOnChainCard = () => {
callback={createAddress} callback={createAddress}
variables={{ nested }} variables={{ nested }}
disabled={received} disabled={received}
withMargin={ withMargin={'0 0 0 16px'}
width <= mediaDimensions.mobile ? '16px 0 0' : '0 0 0 16px' mobileMargin={'16px 0 0'}
}
arrow={true} arrow={true}
loading={loading} loading={loading}
fullWidth={width <= mediaDimensions.mobile} mobileFullWidth={true}
> >
Create Address Create Address
</SecureButton> </SecureButton>

View file

@ -15,13 +15,12 @@ import { getErrorContent } from '../../../../utils/error';
import { useBitcoinState } from '../../../../context/BitcoinContext'; import { useBitcoinState } from '../../../../context/BitcoinContext';
import { SecureButton } from '../../../../components/buttons/secureButton/SecureButton'; import { SecureButton } from '../../../../components/buttons/secureButton/SecureButton';
import { Input } from '../../../../components/input/Input'; import { Input } from '../../../../components/input/Input';
import { useSize } from '../../../../hooks/UseSize';
import { import {
MultiButton, MultiButton,
SingleButton, SingleButton,
} from '../../../../components/buttons/multiButton/MultiButton'; } from '../../../../components/buttons/multiButton/MultiButton';
import { Price, getPrice } from '../../../../components/price/Price'; import { Price, getPrice } from '../../../../components/price/Price';
import { mediaWidths, mediaDimensions } from '../../../../styles/Themes'; import { mediaWidths } from '../../../../styles/Themes';
import { useSettings } from '../../../../context/SettingsContext'; import { useSettings } from '../../../../context/SettingsContext';
import Modal from '../../../../components/modal/ReactModal'; import Modal from '../../../../components/modal/ReactModal';
import { ColorButton } from '../../../../components/buttons/colorButton/ColorButton'; import { ColorButton } from '../../../../components/buttons/colorButton/ColorButton';
@ -51,7 +50,6 @@ export const SendOnChainCard = ({ setOpen }: { setOpen: () => void }) => {
const [modalOpen, setModalOpen] = useState(false); const [modalOpen, setModalOpen] = useState(false);
const { width } = useSize();
const [address, setAddress] = useState(''); const [address, setAddress] = useState('');
const [tokens, setTokens] = useState(0); const [tokens, setTokens] = useState(0);
const [type, setType] = useState('none'); const [type, setType] = useState('none');
@ -109,7 +107,8 @@ export const SendOnChainCard = ({ setOpen }: { setOpen: () => void }) => {
<NoWrapTitle>Send to Address:</NoWrapTitle> <NoWrapTitle>Send to Address:</NoWrapTitle>
<Input <Input
placeholder={'Address'} placeholder={'Address'}
withMargin={width <= mediaDimensions.mobile ? '' : '0 0 0 24px'} withMargin={'0 0 0 24px'}
mobileMargin={'0'}
onChange={e => setAddress(e.target.value)} onChange={e => setAddress(e.target.value)}
/> />
</ResponsiveLine> </ResponsiveLine>

View file

@ -16,12 +16,9 @@ import { getErrorContent } from '../../../../utils/error';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { ColorButton } from '../../../../components/buttons/colorButton/ColorButton'; import { ColorButton } from '../../../../components/buttons/colorButton/ColorButton';
import { Input } from '../../../../components/input/Input'; import { Input } from '../../../../components/input/Input';
import { useSize } from '../../../../hooks/UseSize';
import { Price } from '../../../../components/price/Price'; import { Price } from '../../../../components/price/Price';
import { mediaDimensions } from '../../../../styles/Themes';
export const DecodeCard = ({ color }: { color: string }) => { export const DecodeCard = ({ color }: { color: string }) => {
const { width } = useSize();
const [request, setRequest] = useState(''); const [request, setRequest] = useState('');
const { host, viewOnly, cert, sessionAdmin } = useAccount(); const { host, viewOnly, cert, sessionAdmin } = useAccount();
@ -70,9 +67,8 @@ export const DecodeCard = ({ color }: { color: string }) => {
<Sub4Title>Request:</Sub4Title> <Sub4Title>Request:</Sub4Title>
<Input <Input
placeholder={'Lightning Invoice'} placeholder={'Lightning Invoice'}
withMargin={ withMargin={'0 0 0 24px'}
width <= mediaDimensions.mobile ? '0 0 8px' : '0 0 0 24px' mobileMargin={'0 0 16px'}
}
color={color} color={color}
value={request} value={request}
onChange={e => setRequest(e.target.value)} onChange={e => setRequest(e.target.value)}
@ -80,10 +76,11 @@ export const DecodeCard = ({ color }: { color: string }) => {
<ColorButton <ColorButton
color={color} color={color}
disabled={request === ''} disabled={request === ''}
withMargin={width <= mediaDimensions.mobile ? '0' : '0 0 0 16px'} withMargin={'0 0 0 16px'}
mobileMargin={'0'}
arrow={true} arrow={true}
loading={loading} loading={loading}
fullWidth={width <= mediaDimensions.mobile} mobileFullWidth={true}
onClick={() => { onClick={() => {
setRequest(''); setRequest('');
decode({ variables: { request, auth } }); decode({ variables: { request, auth } });

View file

@ -16,13 +16,12 @@ import { useBitcoinState } from '../../../../context/BitcoinContext';
import styled from 'styled-components'; import styled from 'styled-components';
import { SecureButton } from '../../../../components/buttons/secureButton/SecureButton'; import { SecureButton } from '../../../../components/buttons/secureButton/SecureButton';
import { Input } from '../../../../components/input/Input'; import { Input } from '../../../../components/input/Input';
import { useSize } from '../../../../hooks/UseSize';
import { import {
SingleButton, SingleButton,
MultiButton, MultiButton,
} from '../../../../components/buttons/multiButton/MultiButton'; } from '../../../../components/buttons/multiButton/MultiButton';
import { Price } from '../../../../components/price/Price'; import { Price } from '../../../../components/price/Price';
import { mediaWidths, mediaDimensions } from '../../../../styles/Themes'; import { mediaWidths } from '../../../../styles/Themes';
const ResponsiveWrap = styled(SingleLine)` const ResponsiveWrap = styled(SingleLine)`
@media (${mediaWidths.mobile}) { @media (${mediaWidths.mobile}) {
@ -36,7 +35,6 @@ interface OpenChannelProps {
} }
export const OpenChannelCard = ({ color, setOpenCard }: OpenChannelProps) => { export const OpenChannelCard = ({ color, setOpenCard }: OpenChannelProps) => {
const { width } = useSize();
const [size, setSize] = useState(0); const [size, setSize] = useState(0);
const [fee, setFee] = useState(0); const [fee, setFee] = useState(0);
const [publicKey, setPublicKey] = useState(''); const [publicKey, setPublicKey] = useState('');
@ -79,7 +77,8 @@ export const OpenChannelCard = ({ color, setOpenCard }: OpenChannelProps) => {
<Input <Input
placeholder={'Public Key'} placeholder={'Public Key'}
color={color} color={color}
withMargin={width <= mediaDimensions.mobile ? '' : '0 0 0 8px'} withMargin={'0 0 0 8px'}
mobileMargin={'0'}
onChange={e => setPublicKey(e.target.value)} onChange={e => setPublicKey(e.target.value)}
/> />
</ResponsiveLine> </ResponsiveLine>
@ -95,7 +94,8 @@ export const OpenChannelCard = ({ color, setOpenCard }: OpenChannelProps) => {
<Input <Input
placeholder={'Sats'} placeholder={'Sats'}
color={color} color={color}
withMargin={width <= mediaDimensions.mobile ? '' : '0 0 0 8px'} withMargin={'0 0 0 8px'}
mobileMargin={'0'}
type={'number'} type={'number'}
onChange={e => setSize(Number(e.target.value))} onChange={e => setSize(Number(e.target.value))}
/> />

View file

@ -16,8 +16,6 @@ import { InvoicePie } from './InvoicePie';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { getErrorContent } from '../../../../utils/error'; import { getErrorContent } from '../../../../utils/error';
import { LoadingCard } from '../../../../components/loading/LoadingCard'; import { LoadingCard } from '../../../../components/loading/LoadingCard';
import { useSize } from '../../../../hooks/UseSize';
import { mediaDimensions } from '../../../../styles/Themes';
import { GET_IN_OUT } from '../../../../graphql/query'; import { GET_IN_OUT } from '../../../../graphql/query';
// import { getWaterfall } from './Helpers'; // import { getWaterfall } from './Helpers';
@ -82,7 +80,6 @@ const timeMap: { [key: string]: string } = {
}; };
export const FlowBox = () => { export const FlowBox = () => {
const { width } = useSize();
const [isTime, setIsTime] = useState<string>('month'); const [isTime, setIsTime] = useState<string>('month');
const [isType, setIsType] = useState<string>('amount'); const [isType, setIsType] = useState<string>('amount');
@ -122,10 +119,7 @@ export const FlowBox = () => {
<SubTitle>Invoices and Payments Report</SubTitle> <SubTitle>Invoices and Payments Report</SubTitle>
<ButtonRow {...buttonProps} /> <ButtonRow {...buttonProps} />
</CardTitle> </CardTitle>
<Card <Card bottom={'10px'} mobileCardPadding={'8px 0'}>
bottom={'10px'}
cardPadding={width <= mediaDimensions.mobile ? '8px 0' : undefined}
>
<p>{`Your node has not forwarded any payments ${timeMap[isTime]}.`}</p> <p>{`Your node has not forwarded any payments ${timeMap[isTime]}.`}</p>
</Card> </Card>
</CardWithTitle> </CardWithTitle>
@ -178,10 +172,7 @@ export const FlowBox = () => {
<SubTitle>Invoices and Payments Report</SubTitle> <SubTitle>Invoices and Payments Report</SubTitle>
<ButtonRow {...buttonProps} /> <ButtonRow {...buttonProps} />
</CardTitle> </CardTitle>
<Card <Card bottom={'10px'} mobileCardPadding={'8px 0'}>
bottom={'10px'}
cardPadding={width <= mediaDimensions.mobile ? '8px 0' : undefined}
>
<FlowReport {...props} /> <FlowReport {...props} />
</Card> </Card>
</CardWithTitle> </CardWithTitle>
@ -190,9 +181,7 @@ export const FlowBox = () => {
<CardTitle> <CardTitle>
<Sub4Title>Total</Sub4Title> <Sub4Title>Total</Sub4Title>
</CardTitle> </CardTitle>
<Card <Card mobileCardPadding={'8px'}>
cardPadding={width <= mediaDimensions.mobile ? '8px' : undefined}
>
<FlowPie {...flowProps} /> <FlowPie {...flowProps} />
</Card> </Card>
</HalfCardWithTitle> </HalfCardWithTitle>
@ -201,9 +190,7 @@ export const FlowBox = () => {
<CardTitle> <CardTitle>
<Sub4Title>Invoices</Sub4Title> <Sub4Title>Invoices</Sub4Title>
</CardTitle> </CardTitle>
<Card <Card mobileCardPadding={'8px'}>
cardPadding={width <= mediaDimensions.mobile ? '8px' : undefined}
>
<InvoicePie {...pieProps} /> <InvoicePie {...pieProps} />
</Card> </Card>
</HalfCardWithTitle> </HalfCardWithTitle>

View file

@ -9,8 +9,7 @@ import {
CardTitle, CardTitle,
} from '../../../../components/generic/Styled'; } from '../../../../components/generic/Styled';
import { ButtonRow } from './Buttons'; import { ButtonRow } from './Buttons';
import { mediaWidths, mediaDimensions } from '../../../../styles/Themes'; import { mediaWidths } from '../../../../styles/Themes';
import { useSize } from '../../../../hooks/UseSize';
export const CardContent = styled.div` export const CardContent = styled.div`
height: 100%; height: 100%;
@ -40,7 +39,6 @@ const mappedTypes = ['Amount', 'Fees', 'Value'];
const buttonBorder = '#6938f1'; const buttonBorder = '#6938f1';
export const ForwardBox = () => { export const ForwardBox = () => {
const { width } = useSize();
const [isTime, setIsTime] = useState<string>('week'); const [isTime, setIsTime] = useState<string>('week');
const [isType, setIsType] = useState<string>('amount'); const [isType, setIsType] = useState<string>('amount');
@ -64,7 +62,7 @@ export const ForwardBox = () => {
<SubTitle>Foward Report</SubTitle> <SubTitle>Foward Report</SubTitle>
<ButtonRow {...buttonProps} /> <ButtonRow {...buttonProps} />
</CardTitle> </CardTitle>
<Card cardPadding={width <= mediaDimensions.mobile ? '8px' : undefined}> <Card mobileCardPadding={'8px'}>
<Row> <Row>
<ForwardReport {...props} /> <ForwardReport {...props} />
<ForwardChannelsReport {...props} /> <ForwardChannelsReport {...props} />

View file

@ -18,16 +18,13 @@ import {
chartGridColor, chartGridColor,
chartAxisColor, chartAxisColor,
liquidityBarColor, liquidityBarColor,
mediaDimensions,
} from '../../../../styles/Themes'; } from '../../../../styles/Themes';
import { LoadingCard } from '../../../../components/loading/LoadingCard'; import { LoadingCard } from '../../../../components/loading/LoadingCard';
import { getPrice } from '../../../../components/price/Price'; import { getPrice } from '../../../../components/price/Price';
import { useSize } from '../../../../hooks/UseSize';
import { usePriceState } from '../../../../context/PriceContext'; import { usePriceState } from '../../../../context/PriceContext';
import { GET_LIQUID_REPORT } from '../../../../graphql/query'; import { GET_LIQUID_REPORT } from '../../../../graphql/query';
export const LiquidReport = () => { export const LiquidReport = () => {
const { width } = useSize();
const { host, viewOnly, cert, sessionAdmin } = useAccount(); const { host, viewOnly, cert, sessionAdmin } = useAccount();
const auth = { const auth = {
host, host,
@ -62,7 +59,7 @@ export const LiquidReport = () => {
return ( return (
<CardWithTitle> <CardWithTitle>
<SubTitle>Liquidity Report</SubTitle> <SubTitle>Liquidity Report</SubTitle>
<Card cardPadding={width <= mediaDimensions.mobile ? '8px 0' : undefined}> <Card mobileCardPadding={'8px 0'}>
<VictoryChart <VictoryChart
height={100} height={100}
domainPadding={10} domainPadding={10}

View file

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import styled, { keyframes } from 'styled-components'; import styled, { keyframes } from 'styled-components';
import { fontColors, mediaWidths } from '../../styles/Themes'; import { fontColors, mediaWidths } from '../../styles/Themes';
import { appendBasePath } from '../../utils/basePath';
export const Headline = styled.div` export const Headline = styled.div`
display: flex; display: flex;
@ -35,7 +36,9 @@ const flicker = keyframes`
100% { opacity: 0; } 100% { opacity: 0; }
`; `;
const HeadlineImage = () => <img src={'/static/images/ThunderHub.svg'} />; const HeadlineImage = () => (
<img src={appendBasePath('/static/images/ThunderHub.svg')} />
);
export const StyledImage = styled(HeadlineImage)` export const StyledImage = styled(HeadlineImage)`
width: 500px; width: 500px;

View file

@ -7,6 +7,7 @@ import {
TextSection, TextSection,
} from './Sections.styled'; } from './Sections.styled';
import { Text } from '../../../components/typography/Styled'; import { Text } from '../../../components/typography/Styled';
import { appendBasePath } from '../../../utils/basePath';
export const InfoSection = () => { export const InfoSection = () => {
return ( return (
@ -21,14 +22,16 @@ export const InfoSection = () => {
</Text> </Text>
</TextSection> </TextSection>
<ImageSection> <ImageSection>
<ImagePlace src={'/static/images/Transactions.png'} /> <ImagePlace
src={appendBasePath('/static/images/Transactions.png')}
/>
</ImageSection> </ImageSection>
</InfoRow> </InfoRow>
</Section> </Section>
<Section padding={'48px 0'}> <Section padding={'48px 0'}>
<InfoRow reverse={true}> <InfoRow reverse={true}>
<ImageSection> <ImageSection>
<ImagePlace src={'/static/images/Transactions.png'} /> <ImagePlace src={appendBasePath('/static/images/Reports.png')} />
</ImageSection> </ImageSection>
<TextSection> <TextSection>
<h2>Transaction Reports</h2> <h2>Transaction Reports</h2>
@ -51,14 +54,14 @@ export const InfoSection = () => {
</Text> </Text>
</TextSection> </TextSection>
<ImageSection> <ImageSection>
<ImagePlace src={'/static/images/Transactions.png'} /> <ImagePlace src={appendBasePath('/static/images/Channels.png')} />
</ImageSection> </ImageSection>
</InfoRow> </InfoRow>
</Section> </Section>
<Section padding={'48px 0'}> <Section padding={'48px 0'}>
<InfoRow reverse={true}> <InfoRow reverse={true}>
<ImageSection> <ImageSection>
<ImagePlace src={'/static/images/Transactions.png'} /> <ImagePlace src={appendBasePath('/static/images/Forwards.png')} />
</ImageSection> </ImageSection>
<TextSection> <TextSection>
<h2>Forwarded Payments</h2> <h2>Forwarded Payments</h2>
@ -80,7 +83,7 @@ export const InfoSection = () => {
</Text> </Text>
</TextSection> </TextSection>
<ImageSection> <ImageSection>
<ImagePlace src={'/static/images/Transactions.png'} /> <ImagePlace src={appendBasePath('/static/images/NightLight.png')} />
</ImageSection> </ImageSection>
</InfoRow> </InfoRow>
</Section> </Section>

View file

@ -17,8 +17,6 @@ import {
SingleButton, SingleButton,
} from '../../components/buttons/multiButton/MultiButton'; } from '../../components/buttons/multiButton/MultiButton';
import { Input } from '../../components/input/Input'; import { Input } from '../../components/input/Input';
import { mediaDimensions } from '../../styles/Themes';
import { useSize } from '../../hooks/UseSize';
import { useMutation } from '@apollo/react-hooks'; import { useMutation } from '@apollo/react-hooks';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { getErrorContent } from '../../utils/error'; import { getErrorContent } from '../../utils/error';
@ -31,8 +29,6 @@ export const AddPeer = () => {
const [key, setKey] = useState<string>(''); const [key, setKey] = useState<string>('');
const [socket, setSocket] = useState<string>(''); const [socket, setSocket] = useState<string>('');
const { width } = useSize();
const [addPeer, { loading }] = useMutation(ADD_PEER, { const [addPeer, { loading }] = useMutation(ADD_PEER, {
onError: error => toast.error(getErrorContent(error)), onError: error => toast.error(getErrorContent(error)),
onCompleted: () => { onCompleted: () => {
@ -62,9 +58,8 @@ export const AddPeer = () => {
<Sub4Title style={{ whiteSpace: 'nowrap' }}>Peer Public Key:</Sub4Title> <Sub4Title style={{ whiteSpace: 'nowrap' }}>Peer Public Key:</Sub4Title>
<Input <Input
placeholder={'Peer Public Key'} placeholder={'Peer Public Key'}
withMargin={ withMargin={'0 0 0 24px'}
width <= mediaDimensions.mobile ? '0 0 16px' : '0 0 0 24px' mobileMargin={'0 0 16px'}
}
onChange={e => setKey(e.target.value)} onChange={e => setKey(e.target.value)}
/> />
</ResponsiveLine> </ResponsiveLine>
@ -72,9 +67,8 @@ export const AddPeer = () => {
<Sub4Title style={{ whiteSpace: 'nowrap' }}>Peer Socket:</Sub4Title> <Sub4Title style={{ whiteSpace: 'nowrap' }}>Peer Socket:</Sub4Title>
<Input <Input
placeholder={'Socket'} placeholder={'Socket'}
withMargin={ withMargin={'0 0 0 24px'}
width <= mediaDimensions.mobile ? '0 0 16px' : '0 0 0 24px' mobileMargin={'0 0 16px'}
}
onChange={e => setSocket(e.target.value)} onChange={e => setSocket(e.target.value)}
/> />
</ResponsiveLine> </ResponsiveLine>

View file

@ -19,6 +19,7 @@ import { useConnectionDispatch } from '../../context/ConnectionContext';
import { useStatusDispatch } from '../../context/StatusContext'; import { useStatusDispatch } from '../../context/StatusContext';
import { Auth } from '../../components/auth'; import { Auth } from '../../components/auth';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { appendBasePath } from '../../utils/basePath';
export const AccountSettings = () => { export const AccountSettings = () => {
const [status, setStatus] = useState('none'); const [status, setStatus] = useState('none');
@ -85,7 +86,7 @@ export const AccountSettings = () => {
type: 'disconnected', type: 'disconnected',
}); });
changeAccount(accountId); changeAccount(accountId);
push('/'); push(appendBasePath('/'));
} }
}} }}
> >

View file

@ -20,6 +20,7 @@ import { AlertCircle } from '../../components/generic/Icons';
import { useConnectionDispatch } from '../../context/ConnectionContext'; import { useConnectionDispatch } from '../../context/ConnectionContext';
import { useStatusDispatch } from '../../context/StatusContext'; import { useStatusDispatch } from '../../context/StatusContext';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { appendBasePath } from '../../utils/basePath';
export const ButtonRow = styled.div` export const ButtonRow = styled.div`
width: auto; width: auto;
@ -122,7 +123,7 @@ export const DangerView = () => {
type: 'disconnected', type: 'disconnected',
}); });
changeAccount(id); changeAccount(id);
push('/'); push(appendBasePath('/'));
}; };
const renderSwitch = () => { const renderSwitch = () => {
@ -156,7 +157,7 @@ export const DangerView = () => {
onClick={() => { onClick={() => {
deleteStorage(); deleteStorage();
refreshAccount(); refreshAccount();
push('/'); push(appendBasePath('/'));
}} }}
> >
Delete All Delete All

View file

@ -22,7 +22,7 @@ const StyledMethodBoxes = styled.div`
margin: 0 0 -24px 0; margin: 0 0 -24px 0;
flex-wrap: wrap; flex-wrap: wrap;
overflow: hidden; overflow: hidden;
height: 24px; height: 23px;
`; `;
const StyledMethod = styled.div` const StyledMethod = styled.div`

View file

@ -19,6 +19,7 @@ import { renderLine } from '../../components/generic/Helpers';
import { chartColors } from '../../styles/Themes'; import { chartColors } from '../../styles/Themes';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { encode } from '../../utils/Helpers'; import { encode } from '../../utils/Helpers';
import { appendBasePath } from '../../utils/basePath';
type ActionType = { type ActionType = {
type: 'addFilter' | 'addSort' | 'removeSort' | 'removeFilter' | 'changeLimit'; type: 'addFilter' | 'addSort' | 'removeSort' | 'removeFilter' | 'changeLimit';
@ -95,10 +96,10 @@ export const OfferFilters = ({ offerFilters }: FilterProps) => {
const handleSave = () => { const handleSave = () => {
const stringFormat = JSON.stringify(filterState); const stringFormat = JSON.stringify(filterState);
const encoded = encode(stringFormat); const encoded = encode(stringFormat);
push(`/trading?filter=${encoded}`); push(appendBasePath(`/trading?filter=${encoded}`));
}; };
const handleRemoveAll = () => push('/trading'); const handleRemoveAll = () => push(appendBasePath('/trading'));
const handleRemove = (removeKey: string) => { const handleRemove = (removeKey: string) => {
dispatch({ type: 'removeFilter', removeKey }); dispatch({ type: 'removeFilter', removeKey });

836
yarn.lock

File diff suppressed because it is too large Load diff