Browse Source

feat(bitcoind): split bitcoind sidebar into tabs with rpc user/pass

master
jamaljsr 5 years ago
parent
commit
49cbf9b322
  1. 23
      src/components/designer/bitcoind/ActionsTab.tsx
  2. 81
      src/components/designer/bitcoind/BitcoindDetails.tsx
  3. 66
      src/components/designer/bitcoind/ConnectTab.tsx
  4. 66
      src/components/designer/bitcoind/InfoTab.tsx
  5. 7
      src/components/designer/bitcoind/MineBlocksInput.tsx
  6. 25
      src/i18n/locales/en-US.json
  7. 25
      src/i18n/locales/es.json

23
src/components/designer/bitcoind/ActionsTab.tsx

@ -0,0 +1,23 @@
import React from 'react';
import { BitcoinNode, Status } from 'shared/types';
import { OpenTerminalButton } from 'components/terminal';
import MineBlocksInput from './MineBlocksInput';
interface Props {
node: BitcoinNode;
}
const ActionsTab: React.FC<Props> = ({ node }) => {
return (
<>
{node.status === Status.Started && (
<>
<MineBlocksInput node={node} />
<OpenTerminalButton node={node} />
</>
)}
</>
);
};
export default ActionsTab;

81
src/components/designer/bitcoind/BitcoindDetails.tsx

@ -1,19 +1,18 @@
import React, { ReactNode } from 'react';
import React, { ReactNode, useState } from 'react';
import { useAsync } from 'react-async-hook';
import { Alert, Icon } from 'antd';
import { usePrefixedTranslation } from 'hooks';
import { BitcoinNode, Status } from 'shared/types';
import { useStoreActions, useStoreState } from 'store';
import { ellipseInner } from 'utils/strings';
import { toSats } from 'utils/units';
import { CopyIcon, DetailsList, Loader, StatusBadge } from 'components/common';
import { DetailValues } from 'components/common/DetailsList';
import { OpenTerminalButton } from 'components/terminal';
import { Loader } from 'components/common';
import SidebarCard from '../SidebarCard';
import MineBlocksInput from './MineBlocksInput';
import ActionsTab from './ActionsTab';
import ConnectTab from './ConnectTab';
import InfoTab from './InfoTab';
const BitcoindDetails: React.FC<{ node: BitcoinNode }> = ({ node }) => {
const { l } = usePrefixedTranslation('cmps.designer.bitcoind.BitcoinDetails');
const [activeTab, setActiveTab] = useState('info');
const { getInfo } = useStoreActions(s => s.bitcoind);
const { chainInfo, walletInfo } = useStoreState(s => s.bitcoind);
const getInfoAsync = useAsync(
@ -25,43 +24,30 @@ const BitcoindDetails: React.FC<{ node: BitcoinNode }> = ({ node }) => {
[node],
);
const details: DetailValues = [
{ label: l('nodeType'), value: node.type },
{ label: l('implementation'), value: node.implementation },
{ label: l('version'), value: `v${node.version}` },
{
label: l('status'),
value: (
<StatusBadge
status={node.status}
text={l(`enums.status.${Status[node.status]}`)}
/>
),
},
];
let extra: ReactNode | undefined;
if (node.status === Status.Started && chainInfo && walletInfo) {
details.push(
{ label: l('rpcHost'), value: `127.0.0.1:${node.ports.rpc}` },
{ label: l('walletBalance'), value: `${walletInfo.balance} BTC` },
{ label: l('blockHeight'), value: chainInfo.blocks },
{
label: l('blockHash'),
value: (
<CopyIcon
label={l('blockHash')}
value={chainInfo.bestblockhash}
text={ellipseInner(chainInfo.bestblockhash)}
/>
),
},
);
extra = <strong>{toSats(walletInfo.balance, true)} sats</strong>;
extra = <strong>{walletInfo.balance} BTC</strong>;
}
const tabHeaders = [
{ key: 'info', tab: l('info') },
{ key: 'connect', tab: l('connect') },
{ key: 'actions', tab: l('actions') },
];
const tabContents: Record<string, ReactNode> = {
info: <InfoTab node={node} />,
connect: <ConnectTab node={node} />,
actions: <ActionsTab node={node} />,
};
return (
<SidebarCard title={node.name} extra={extra}>
<SidebarCard
title={node.name}
extra={extra}
tabList={tabHeaders}
activeTabKey={activeTab}
onTabChange={setActiveTab}
>
{getInfoAsync.loading && <Loader />}
{node.status === Status.Starting && (
<Alert
@ -72,15 +58,6 @@ const BitcoindDetails: React.FC<{ node: BitcoinNode }> = ({ node }) => {
icon={<Icon type="loading" />}
/>
)}
{node.status === Status.Error && node.errorMsg && (
<Alert
type="error"
message={l('startError')}
description={node.errorMsg}
closable={false}
showIcon
/>
)}
{getInfoAsync.error && (
<Alert
type="error"
@ -89,13 +66,7 @@ const BitcoindDetails: React.FC<{ node: BitcoinNode }> = ({ node }) => {
description={getInfoAsync.error.message}
/>
)}
<DetailsList details={details} />
{node.status === Status.Started && (
<>
<MineBlocksInput node={node} />
<OpenTerminalButton node={node} />
</>
)}
{tabContents[activeTab]}
</SidebarCard>
);
};

66
src/components/designer/bitcoind/ConnectTab.tsx

@ -0,0 +1,66 @@
import React from 'react';
import styled from '@emotion/styled';
import { Icon, Tooltip } from 'antd';
import { usePrefixedTranslation } from 'hooks';
import { BitcoinNode, Status } from 'shared/types';
import { useStoreActions } from 'store';
import { CopyIcon, DetailsList } from 'components/common';
import { DetailValues } from 'components/common/DetailsList';
const Styled = {
Link: styled.a`
margin-left: 10px;
color: inherit;
&:hover {
opacity: 1;
}
`,
Icon: styled(Icon)`
margin-left: 5px;
color: #aaa;
`,
};
interface Props {
node: BitcoinNode;
}
const ConnectTab: React.FC<Props> = ({ node }) => {
const { l } = usePrefixedTranslation('cmps.designer.bitcoind.ConnectTab');
const { openInBrowser } = useStoreActions(s => s.app);
if (node.status !== Status.Started) {
return <>{l('notStarted')}</>;
}
const details: DetailValues = [
{ label: l('rpcHost'), value: `http://127.0.0.1:${node.ports.rpc}` },
{ label: l('rpcUser'), value: 'polaruser' },
{ label: l('rpcPass'), value: 'polarpass' },
].map(({ label, value }) => ({
label,
value: <CopyIcon label={label} value={value} text={value} />,
}));
const restDocsUrl =
'https://bitcoin.org/en/developer-reference#remote-procedure-calls-rpcs';
details.push({
label: l('apiDocs'),
value: (
<>
<Tooltip title={restDocsUrl}>
<Styled.Link onClick={() => openInBrowser(restDocsUrl)}>REST</Styled.Link>
</Tooltip>
<Styled.Icon type="book" />
</>
),
});
return (
<>
<DetailsList details={details} />
</>
);
};
export default ConnectTab;

66
src/components/designer/bitcoind/InfoTab.tsx

@ -0,0 +1,66 @@
import React from 'react';
import { Alert } from 'antd';
import { usePrefixedTranslation } from 'hooks';
import { BitcoinNode, Status } from 'shared/types';
import { useStoreState } from 'store';
import { ellipseInner } from 'utils/strings';
import { CopyIcon, DetailsList, StatusBadge } from 'components/common';
import { DetailValues } from 'components/common/DetailsList';
interface Props {
node: BitcoinNode;
}
const InfoTab: React.FC<Props> = ({ node }) => {
const { l } = usePrefixedTranslation('cmps.designer.bitcoind.InfoTab');
const { chainInfo, walletInfo } = useStoreState(s => s.bitcoind);
const details: DetailValues = [
{ label: l('nodeType'), value: node.type },
{ label: l('implementation'), value: node.implementation },
{ label: l('version'), value: `v${node.version}` },
{
label: l('status'),
value: (
<StatusBadge
status={node.status}
text={l(`enums.status.${Status[node.status]}`)}
/>
),
},
];
if (node.status === Status.Started && chainInfo && walletInfo) {
details.push(
{ label: l('spendableBalance'), value: `${walletInfo.balance} BTC` },
{ label: l('immatureBalance'), value: `${walletInfo.immature_balance} BTC` },
{ label: l('blockHeight'), value: chainInfo.blocks },
{
label: l('blockHash'),
value: (
<CopyIcon
label={l('blockHash')}
value={chainInfo.bestblockhash}
text={ellipseInner(chainInfo.bestblockhash)}
/>
),
},
);
}
return (
<>
{node.status === Status.Error && node.errorMsg && (
<Alert
type="error"
message={l('startError')}
description={node.errorMsg}
closable={false}
showIcon
/>
)}
<DetailsList details={details} />
</>
);
};
export default InfoTab;

7
src/components/designer/bitcoind/MineBlocksInput.tsx

@ -9,9 +9,6 @@ import { useStoreActions } from 'store';
const InputGroup = Input.Group;
const Styled = {
FormItem: styled(Form.Item)`
margin-top: 30px;
`,
InputNumber: styled(InputNumber)`
width: 65%;
`,
@ -35,7 +32,7 @@ const MineBlocksInput: React.FC<{ node: BitcoinNode }> = ({ node }) => {
return (
<>
<Styled.FormItem label={l('label')}>
<Form.Item label={l('label')}>
<InputGroup compact>
<Styled.InputNumber
value={value}
@ -51,7 +48,7 @@ const MineBlocksInput: React.FC<{ node: BitcoinNode }> = ({ node }) => {
{l('btn')}
</Styled.Button>
</InputGroup>
</Styled.FormItem>
</Form.Item>
</>
);
};

25
src/i18n/locales/en-US.json

@ -11,17 +11,24 @@
"cmps.common.OpenTerminalButton.title": "Terminal",
"cmps.common.OpenTerminalButton.btn": "Launch",
"cmps.common.OpenTerminalButton.info": "Run '{{cmd}}' commands directly on the node",
"cmps.designer.bitcoind.BitcoinDetails.nodeType": "Node Type",
"cmps.designer.bitcoind.BitcoinDetails.implementation": "Implementation",
"cmps.designer.bitcoind.BitcoinDetails.version": "Version",
"cmps.designer.bitcoind.BitcoinDetails.status": "Status",
"cmps.designer.bitcoind.BitcoinDetails.rpcHost": "RPC Host",
"cmps.designer.bitcoind.BitcoinDetails.walletBalance": "Wallet Balance",
"cmps.designer.bitcoind.BitcoinDetails.blockHeight": "Block Height",
"cmps.designer.bitcoind.BitcoinDetails.blockHash": "Block Hash",
"cmps.designer.bitcoind.BitcoinDetails.info": "Info",
"cmps.designer.bitcoind.BitcoinDetails.connect": "Connect",
"cmps.designer.bitcoind.BitcoinDetails.actions": "Actions",
"cmps.designer.bitcoind.BitcoinDetails.waitingNotice": "Waiting for bitcoind to come online",
"cmps.designer.bitcoind.BitcoinDetails.getInfoErr": "Unable to connect to node",
"cmps.designer.bitcoind.BitcoinDetails.startError": "Unable to connect to bitcoin node",
"cmps.designer.bitcoind.ConnectTab.rpcHost": "RPC Host",
"cmps.designer.bitcoind.ConnectTab.rpcUser": "Username",
"cmps.designer.bitcoind.ConnectTab.rpcPass": "Password",
"cmps.designer.bitcoind.ConnectTab.apiDocs": "API Docs",
"cmps.designer.bitcoind.InfoTab.nodeType": "Node Type",
"cmps.designer.bitcoind.InfoTab.implementation": "Implementation",
"cmps.designer.bitcoind.InfoTab.version": "Version",
"cmps.designer.bitcoind.InfoTab.status": "Status",
"cmps.designer.bitcoind.InfoTab.spendableBalance": "Spendable Balance",
"cmps.designer.bitcoind.InfoTab.immatureBalance": "Immature Balance",
"cmps.designer.bitcoind.InfoTab.blockHeight": "Block Height",
"cmps.designer.bitcoind.InfoTab.blockHash": "Block Hash",
"cmps.designer.bitcoind.InfoTab.startError": "Unable to connect to bitcoin node",
"cmps.designer.bitcoind.MineBlocksInput.label": "Manually Mine Blocks",
"cmps.designer.bitcoind.MineBlocksInput.error": "Unable to mine blocks",
"cmps.designer.bitcoind.MineBlocksInput.btn": "Mine",

25
src/i18n/locales/es.json

@ -11,17 +11,24 @@
"cmps.common.OpenTerminalButton.title": "Terminal",
"cmps.common.OpenTerminalButton.btn": "Lanzamiento",
"cmps.common.OpenTerminalButton.info": "Ejecute los comandos '{{cmd}}' directamente en el nodo",
"cmps.designer.bitcoind.BitcoinDetails.nodeType": "Tipo de nodo",
"cmps.designer.bitcoind.BitcoinDetails.implementation": "Implementación",
"cmps.designer.bitcoind.BitcoinDetails.version": "Versión",
"cmps.designer.bitcoind.BitcoinDetails.status": "Estado",
"cmps.designer.bitcoind.BitcoinDetails.rpcHost": "Host RPC",
"cmps.designer.bitcoind.BitcoinDetails.walletBalance": "Saldo de billetera",
"cmps.designer.bitcoind.BitcoinDetails.blockHeight": "Altura del bloque",
"cmps.designer.bitcoind.BitcoinDetails.blockHash": "Bloquear Hash",
"cmps.designer.bitcoind.BitcoinDetails.info": "Informacion",
"cmps.designer.bitcoind.BitcoinDetails.connect": "Conectar",
"cmps.designer.bitcoind.BitcoinDetails.actions": "Comportamiento",
"cmps.designer.bitcoind.BitcoinDetails.waitingNotice": "Esperando a que bitcoind se conecte",
"cmps.designer.bitcoind.BitcoinDetails.getInfoErr": "No se puede conectar al nodo",
"cmps.designer.bitcoind.BitcoinDetails.startError": "No se puede conectar al nodo bitcoin",
"cmps.designer.bitcoind.ConnectTab.rpcHost": "Host RPC",
"cmps.designer.bitcoind.ConnectTab.rpcUser": "Nombre de usuario",
"cmps.designer.bitcoind.ConnectTab.rpcPass": "Contraseña",
"cmps.designer.bitcoind.ConnectTab.apiDocs": "API Docs",
"cmps.designer.bitcoind.InfoTab.nodeType": "Tipo de nodo",
"cmps.designer.bitcoind.InfoTab.implementation": "Implementación",
"cmps.designer.bitcoind.InfoTab.version": "Versión",
"cmps.designer.bitcoind.InfoTab.status": "Estado",
"cmps.designer.bitcoind.InfoTab.spendableBalance": "Saldo gastable",
"cmps.designer.bitcoind.InfoTab.immatureBalance": "Saldo inmaduro",
"cmps.designer.bitcoind.InfoTab.blockHeight": "Altura del bloque",
"cmps.designer.bitcoind.InfoTab.blockHash": "Bloquear Hash",
"cmps.designer.bitcoind.InfoTab.startError": "No se puede conectar al nodo bitcoin",
"cmps.designer.bitcoind.MineBlocksInput.label": "Bloques de mina manual",
"cmps.designer.bitcoind.MineBlocksInput.error": "Incapaz de extraer bloques",
"cmps.designer.bitcoind.MineBlocksInput.btn": "Mina",

Loading…
Cancel
Save