mirror of
https://github.com/lightninglabs/lightning-terminal.git
synced 2026-08-13 12:33:36 +02:00
feat: implement multi-colored dot icon
This commit is contained in:
parent
011620b064
commit
05c769c25c
7 changed files with 119 additions and 23 deletions
16
app/src/__stories__/StatusDot.stories.tsx
Normal file
16
app/src/__stories__/StatusDot.stories.tsx
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import React from 'react';
|
||||
import StatusDot from 'components/common/StatusDot';
|
||||
|
||||
export default {
|
||||
title: 'Components/Status Dot',
|
||||
component: StatusDot,
|
||||
parameters: { centered: true },
|
||||
};
|
||||
|
||||
export const Success = () => <StatusDot status="success" />;
|
||||
|
||||
export const Warn = () => <StatusDot status="warn" />;
|
||||
|
||||
export const Error = () => <StatusDot status="error" />;
|
||||
|
||||
export const Idle = () => <StatusDot status="idle" />;
|
||||
|
|
@ -4,18 +4,7 @@ import { renderWithProviders } from 'util/tests';
|
|||
import ChannelRow from 'components/loop/ChannelRow';
|
||||
|
||||
describe('ChannelRow component', () => {
|
||||
const channel: Channel = {
|
||||
active: true,
|
||||
capacity: 15000000,
|
||||
chanId: '150633093070848',
|
||||
localBalance: 9990950,
|
||||
remoteBalance: 5000000,
|
||||
remotePubkey: '02ac59099da6d4bd818e6a81098f5d54580b7c3aa8255c707fa0f95ca89b02cb8c',
|
||||
uptime: 97,
|
||||
localPercent: 67,
|
||||
balancePercent: 67,
|
||||
balanceLevel: BalanceLevel.warn,
|
||||
};
|
||||
let channel: Channel;
|
||||
|
||||
const render = () => {
|
||||
const result = renderWithProviders(<ChannelRow channel={channel} />);
|
||||
|
|
@ -24,6 +13,21 @@ describe('ChannelRow component', () => {
|
|||
};
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
channel = {
|
||||
active: true,
|
||||
capacity: 15000000,
|
||||
chanId: '150633093070848',
|
||||
localBalance: 9990950,
|
||||
remoteBalance: 5000000,
|
||||
remotePubkey: '02ac59099da6d4bd818e6a81098f5d54580b7c3aa8255c707fa0f95ca89b02cb8c',
|
||||
uptime: 97,
|
||||
localPercent: 67,
|
||||
balancePercent: 67,
|
||||
balanceLevel: BalanceLevel.warn,
|
||||
};
|
||||
});
|
||||
|
||||
it('should display the remote balance', () => {
|
||||
const { getByText } = render();
|
||||
expect(getByText(channel.remoteBalance.toLocaleString())).toBeInTheDocument();
|
||||
|
|
@ -48,4 +52,22 @@ describe('ChannelRow component', () => {
|
|||
const { getByText } = render();
|
||||
expect(getByText(channel.capacity.toLocaleString())).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display correct dot icon for an inactive channel', () => {
|
||||
channel.active = false;
|
||||
const { getByText, getByLabelText } = render();
|
||||
expect(getByText('dot.svg')).toBeInTheDocument();
|
||||
expect(getByLabelText('idle')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.each<[BalanceLevel, string]>([
|
||||
[BalanceLevel.good, 'success'],
|
||||
[BalanceLevel.warn, 'warn'],
|
||||
[BalanceLevel.bad, 'error'],
|
||||
])('should display correct dot icon for a "%s" balance', (level, label) => {
|
||||
channel.balanceLevel = level;
|
||||
const { getByText, getByLabelText } = render();
|
||||
expect(getByText('dot.svg')).toBeInTheDocument();
|
||||
expect(getByLabelText(label)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class SwapAction {
|
|||
case SwapState.FAILED:
|
||||
return 'Failed';
|
||||
case SwapState.INVOICE_SETTLED:
|
||||
return 'Invoice Settles';
|
||||
return 'Invoice Settled';
|
||||
}
|
||||
|
||||
return 'Unknown';
|
||||
|
|
|
|||
31
app/src/components/common/StatusDot.tsx
Normal file
31
app/src/components/common/StatusDot.tsx
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import React from 'react';
|
||||
import { styled } from 'components/theme';
|
||||
import { Dot } from './icons';
|
||||
|
||||
const Styled = {
|
||||
DotIcon: styled(Dot)`
|
||||
&.success {
|
||||
color: ${props => props.theme.colors.green};
|
||||
}
|
||||
&.warn {
|
||||
color: ${props => props.theme.colors.orange};
|
||||
}
|
||||
&.error {
|
||||
color: ${props => props.theme.colors.pink};
|
||||
}
|
||||
&.idle {
|
||||
color: ${props => props.theme.colors.gray};
|
||||
}
|
||||
`,
|
||||
};
|
||||
|
||||
interface Props {
|
||||
status: 'success' | 'warn' | 'error' | 'idle';
|
||||
}
|
||||
|
||||
const StatusDot: React.FC<Props> = ({ status }) => {
|
||||
const { DotIcon } = Styled;
|
||||
return <DotIcon className={status} aria-label={status} />;
|
||||
};
|
||||
|
||||
export default StatusDot;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { CSSProperties } from 'react';
|
||||
import { Channel } from 'types/state';
|
||||
import { BalanceLevel, Channel } from 'types/state';
|
||||
import { Column, Row } from 'components/common/grid';
|
||||
import { Dot } from 'components/common/icons';
|
||||
import StatusDot from 'components/common/StatusDot';
|
||||
import { Title } from 'components/common/text';
|
||||
import { styled } from 'components/theme';
|
||||
import ChannelBalance from './ChannelBalance';
|
||||
|
|
@ -36,11 +36,6 @@ const Styled = {
|
|||
`,
|
||||
};
|
||||
|
||||
interface Props {
|
||||
channel: Channel;
|
||||
style?: CSSProperties;
|
||||
}
|
||||
|
||||
export const ChannelRowHeader: React.FC = () => (
|
||||
<Row>
|
||||
<Column right>
|
||||
|
|
@ -62,13 +57,31 @@ export const ChannelRowHeader: React.FC = () => (
|
|||
</Row>
|
||||
);
|
||||
|
||||
const ChannelDot: React.FC<{ channel: Channel }> = ({ channel }) => {
|
||||
if (!channel.active) return <StatusDot status="idle" />;
|
||||
|
||||
switch (channel.balanceLevel) {
|
||||
case BalanceLevel.good:
|
||||
return <StatusDot status="success" />;
|
||||
case BalanceLevel.warn:
|
||||
return <StatusDot status="warn" />;
|
||||
case BalanceLevel.bad:
|
||||
return <StatusDot status="error" />;
|
||||
}
|
||||
};
|
||||
|
||||
interface Props {
|
||||
channel: Channel;
|
||||
style?: CSSProperties;
|
||||
}
|
||||
|
||||
const ChannelRow: React.FC<Props> = ({ channel, style }) => {
|
||||
const { Row, Column, StatusIcon, Balance } = Styled;
|
||||
return (
|
||||
<Row style={style}>
|
||||
<Column right>
|
||||
<StatusIcon>
|
||||
<Dot />
|
||||
<ChannelDot channel={channel} />
|
||||
</StatusIcon>
|
||||
{channel.remoteBalance.toLocaleString()}
|
||||
</Column>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react';
|
||||
import { Swap } from 'types/state';
|
||||
import { Column, Row } from 'components/common/grid';
|
||||
import StatusDot from 'components/common/StatusDot';
|
||||
import { SmallText } from 'components/common/text';
|
||||
import { styled } from 'components/theme';
|
||||
|
||||
|
|
@ -10,9 +11,21 @@ const Styled = {
|
|||
`,
|
||||
SmallText: styled(SmallText)`
|
||||
line-height: 1;
|
||||
margin-left: 10px;
|
||||
`,
|
||||
};
|
||||
|
||||
const SwapDot: React.FC<{ swap: Swap }> = ({ swap }) => {
|
||||
switch (swap.status) {
|
||||
case 'Success':
|
||||
return <StatusDot status="success" />;
|
||||
case 'Failed':
|
||||
return <StatusDot status="error" />;
|
||||
default:
|
||||
return <StatusDot status="warn" />;
|
||||
}
|
||||
};
|
||||
|
||||
interface Props {
|
||||
swaps: Swap[];
|
||||
}
|
||||
|
|
@ -26,6 +39,7 @@ const LoopHistory: React.FC<Props> = ({ swaps }) => {
|
|||
{recentSwaps.map(swap => (
|
||||
<Row key={swap.id}>
|
||||
<Column cols={6}>
|
||||
<SwapDot swap={swap} />
|
||||
<SmallText>{swap.createdOn.toLocaleDateString()}</SmallText>
|
||||
</Column>
|
||||
<RightColumn cols={6}>
|
||||
|
|
|
|||
|
|
@ -114,8 +114,8 @@ export const loopListSwaps: LOOP.ListSwapsResponse.AsObject = {
|
|||
amt: 500000 + i * 5000,
|
||||
id: `f4eb118383c2b09d8c7289ce21c25900cfb4545d46c47ed23a31ad2aa57ce83${i}`,
|
||||
idBytes: '9OsRg4PCsJ2MconOIcJZAM+0VF1GxH7SOjGtKqV86DU=',
|
||||
type: (i % 3) as any,
|
||||
state: i as any,
|
||||
type: (i % 3) as LOOP.SwapStatus.AsObject['type'],
|
||||
state: (i % 7) as LOOP.SwapStatus.AsObject['state'],
|
||||
initiationTime: 1586390353623905000 + i * 100000000000000,
|
||||
lastUpdateTime: 1586398369729857000,
|
||||
htlcAddress: 'bcrt1qzu4077erkr78k52yuf2rwkk6ayr6m3wtazdfz2qqmd7taa5vvy9s5d75gd',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue