on master help sign in
ui: address Design team feedback

- sort TX newest first - Window should be same height as the others - the header should be sticky, the internal body should be scrollable with overflow hidden - set the TX hash to use the monospace - isntead of the arrow link, use the L2 layer indicator - update the usage of Point --> Planet or Star; e.g., Point Issued --> Planet Spawned - use the Indigo Node icon - in the dropdown, show the first 4 for the ETH address - empty state: No transactions yet - loading state: use the Indigo loading spinner - use the status badges from the top of Figma doc

commit2f5bbeb7719239de70fb7662445c03f9b1801204 authortomholford <tomholford@users.noreply.github.com> dateWed 27 Oct 2021, 19:57 (5 years ago) parentc3c8a37
4 files changed+152−82
src/lib/constants.ts+3−3 src/views/Transactions/TransactionHistory.scss+45−8 src/views/Transactions/TransactionHistory.tsx+71−66 src/views/Transactions/TransactionRow.tsx+33−5
src/lib/constants.ts+3−3
@@ -131,20 +131,20 @@ const DEFAULT_CSV_NAME = 'urbit_invites.csv';
131131const TRANSACTION_STATUS_ICONS = {
132132 confirmed: 'Checkmark',
133133 pending: 'Clock',
134− sending: 'ArrowEast',
134+ sending: 'ArrowNorth',
135135 failed: 'X',
136136 unknown: 'NullIcon',
137137};
138138
139139const TRANSACTION_TYPE_ICONS = {
140− spawn: 'ArrowEast',
140+ spawn: 'Node',
141141 'configure-keys': 'BootNode',
142142 'transfer-point': 'Swap',
143143 'set-management-proxy': 'ArrowRefresh',
144144};
145145
146146const TRANSACTION_TYPE_TITLES = {
147− spawn: 'Point Issued',
147+ spawn: 'Point Spawned',
148148 'configure-keys': 'Network Keys Configured',
149149 'transfer-point': 'Point Transferred',
150150 'set-management-proxy': 'Management Key Changed',
src/views/Transactions/TransactionHistory.scss+45−8
@@ -13,10 +13,16 @@
1313}
1414
1515.transaction-history {
16−
1716 .loading {
17+ &> svg {
18+ width: 24px;
19+ height: 24px;
20+ }
21+ }
22+
23+ .loading, .no-results {
1824 width: 100%;
19− min-height: 400px;
25+ min-height: 500px;
2026 display: flex;
2127 flex-flow: column nowrap;
2228 justify-content: center;
@@ -74,6 +80,15 @@
7480
7581 .transaction-container {
7682 width: 100%;
83+ height: 550px;
84+ overflow-y: scroll;
85+
86+ // hide the vertical scrollbar
87+ -ms-overflow-style: none; /* IE and Edge */
88+ scrollbar-width: none; /* Firefox */
89+ &::-webkit-scrollbar {
90+ display: none; /* Chrome */
91+ }
7792 }
7893
7994 .address-row {
@@ -112,9 +127,8 @@
112127
113128 .sigil {
114129 background-color: black;
115− height: 14px;
116− width: 14px;
117− padding: 4px;
130+ border-radius: 2px;
131+ padding: 6px;
118132 }
119133 }
120134
@@ -196,11 +210,27 @@
196210 }
197211 }
198212
213+ &.confirmed {
214+ width: 92px;
215+ background: #009F65;
216+ }
217+
218+ &.sending {
219+ width: 74px;
220+ background: #00000033;
221+ color: black;
222+
223+ svg {
224+ path {
225+ fill: black;
226+ }
227+ }
228+ }
229+
199230 &.failed {
200231 background-color: rgb(246,200,196);
201232 color: rgb(236,81,66);
202233 width: 58px;
203−
204234
205235 svg {
206236 path {
@@ -213,7 +243,6 @@
213243 background-color: $rollup-yellow;
214244 color: #000;
215245 width: 100px;
216−
217246
218247 svg {
219248 path {
@@ -230,9 +259,17 @@
230259 flex-direction: row;
231260 justify-content: space-between;
232261 align-items: center;
262+
263+ .hash-container {
264+ display: flex;
265+ flex-flow: row nowrap;
266+ justify-content: space-between;
267+ align-items: center;
268+ width: 31%;
269+ }
233270
234271 .hash {
235− font-family: Inter;
272+ font-family: Source Code Pro;
236273 font-size: 14px;
237274 font-style: normal;
238275 font-weight: 400;
src/views/Transactions/TransactionHistory.tsx+71−66
@@ -14,12 +14,11 @@ import { RollerTransaction } from '@urbit/roller-api';
1414
1515import './TransactionHistory.scss';
1616import { TransactionRow } from './TransactionRow';
17−import { Box, Row } from '@tlon/indigo-react';
17+import { Box, LoadingSpinner, Row } from '@tlon/indigo-react';
1818import { PatpRow } from './PatpRow';
1919import Dropdown from 'components/L2/Dropdowns/Dropdown';
2020import Sigil from 'components/Sigil';
2121import { AddressRow } from './AddressRow';
22−import { abbreviateAddress } from 'lib/utils/address';
2322
2423interface GroupedTransactions {
2524 [ship: string]: RollerTransaction[];
@@ -36,7 +35,7 @@ const TransactionHistory = () => {
3635 const [selectedPatp, setSelectedPatp] = useState<string | null>(null);
3736
3837 const shortAddress = useMemo(() => {
39− return abbreviateAddress(address);
38+ return address.slice(0, 6);
4039 }, [address]);
4140
4241 const fetchTransactions = useCallback(async () => {
@@ -85,75 +84,81 @@ const TransactionHistory = () => {
8584 className="transaction-history"
8685 header={<L2BackHeader />}>
8786 <Window>
88− {loading ? (
89− <Box className={'loading'}>Loading...</Box>
90− ) : (
91− <>
92− <HeaderPane>
93− <Box className="transaction-header">
94− <h5>Transactions</h5>
95− <Dropdown
96− className="transaction-dropdown"
97− open={dropdownOpen}
98− value={selectedPatp ? selectedPatp : shortAddress}
99− toggleOpen={() => setDropdownOpen(!dropdownOpen)}>
100− <Box className="divider" />
101− <Box className="points">
102− <Row className="entry" onClick={() => selectPatp(null)}>
103− <Box>{shortAddress}</Box>
104− <Row>
105− <Box
106− background="black"
107− borderRadius="2px"
108− width="24px"
109− height="24px"></Box>
110− </Row>
87+ <>
88+ <HeaderPane>
89+ <Box className="transaction-header">
90+ <h5>Transactions</h5>
91+ <Dropdown
92+ className="transaction-dropdown"
93+ open={dropdownOpen}
94+ value={selectedPatp ? selectedPatp : shortAddress}
95+ toggleOpen={() => setDropdownOpen(!dropdownOpen)}>
96+ <Box className="divider" />
97+ <Box className="points">
98+ <Row className="entry" onClick={() => selectPatp(null)}>
99+ <Box>{shortAddress}</Box>
100+ <Row>
101+ <Box
102+ background="black"
103+ borderRadius="2px"
104+ width="24px"
105+ height="24px"></Box>
111106 </Row>
112− {txPatps.map(patp => {
113− return (
114− <Row
115− className="entry"
116− onClick={() => selectPatp(patp)}
117− key={patp}>
118− <Box>{patp}</Box>
119− <Row>
120− <Box className="sigil">
121− <Sigil
122− icon
123− patp={patp}
124− size={1}
125− colors={['#000', '#FFF']}
126− />
127− </Box>
128− </Row>
107+ </Row>
108+ {txPatps.map(patp => {
109+ return (
110+ <Row
111+ className="entry"
112+ onClick={() => selectPatp(patp)}
113+ key={patp}>
114+ <Box>{patp}</Box>
115+ <Row>
116+ <Box className="sigil">
117+ <Sigil
118+ icon
119+ patp={patp}
120+ size={1}
121+ colors={['#000', '#FFF']}
122+ />
123+ </Box>
129124 </Row>
130− );
131− })}
132− </Box>
133− </Dropdown>
125+ </Row>
126+ );
127+ })}
128+ </Box>
129+ </Dropdown>
130+ </Box>
131+ </HeaderPane>
132+ <BodyPane>
133+ {loading ? (
134+ <Box className={'loading'}>
135+ <LoadingSpinner />
134136 </Box>
135− </HeaderPane>
136− <BodyPane>
137+ ) : (
137138 <Box className="transaction-container">
138139 {!selectedPatp && <AddressRow address={address} />}
139− {filteredPatps.map(patp => {
140− return (
141− <Box key={patp}>
142− <PatpRow patp={patp} />
143− {txnsByPatp[patp]
144− .sort((a, b) => {
145− return a.time - b.time;
146− })
147− .map(tx => (
148− <TransactionRow key={tx.time} {...tx} />
149− ))}
150− </Box>
151− );
152− })}
140+ {filteredPatps && filteredPatps.length > 0 ? (
141+ filteredPatps.map(patp => {
142+ return (
143+ <Box key={patp}>
144+ <PatpRow patp={patp} />
145+ {txnsByPatp[patp]
146+ .sort((a, b) => {
147+ return a.time - b.time;
148+ })
149+ .map(tx => (
150+ <TransactionRow key={tx.time} {...tx} />
151+ ))}
152+ </Box>
153+ );
154+ })
155+ ) : (
156+ <Box className="no-results">No transactions yet</Box>
157+ )}
153158 </Box>
154− </BodyPane>
155− </>
156− )}
159+ )}
160+ </BodyPane>
161+ </>
157162 </Window>
158163 </View>
159164 );
src/views/Transactions/TransactionRow.tsx+33−5
@@ -1,4 +1,5 @@
11import cn from 'classnames';
2+import * as ob from 'urbit-ob';
23import { Box, Icon, Row } from '@tlon/indigo-react';
34import { RollerTransaction } from '@urbit/roller-api';
45import { format, fromUnixTime } from 'date-fns';
@@ -11,8 +12,11 @@ import {
1112import { abbreviateAddress } from 'lib/utils/address';
1213import { useMemo } from 'react';
1314import { useRollerStore } from 'store/roller';
15+import LayerIndicator from 'components/L2/LayerIndicator';
16+import { isPlanet, isStar } from 'lib/utils/point';
1417
1518export const TransactionRow = ({
19+ ship,
1620 type,
1721 hash,
1822 status,
@@ -20,9 +24,24 @@ export const TransactionRow = ({
2024}: RollerTransaction) => {
2125 const { nextRoll } = useRollerStore();
2226
27+ // For spawn events (associated with the spawner), we want to show the spawnee tier;
28+ // For all other events we will show the event's ship's tier
29+ const pointLabel = useMemo(() => {
30+ const azimuthIndex = ob.patp2dec(`~${ship}`);
31+ if (type === 'spawn') {
32+ return isStar(azimuthIndex) ? 'Planet' : 'Star';
33+ } else {
34+ return isStar(azimuthIndex)
35+ ? 'Star'
36+ : isPlanet(azimuthIndex)
37+ ? 'Planet'
38+ : 'Galaxy';
39+ }
40+ }, [ship, type]);
41+
2342 const label = useMemo(() => {
24− return TRANSACTION_TYPE_TITLES[type] || type;
25− }, [type]);
43+ return TRANSACTION_TYPE_TITLES[type].replace('Point', pointLabel) || type;
44+ }, [pointLabel, type]);
2645
2746 const icon = useMemo(() => {
2847 return <Icon icon={TRANSACTION_TYPE_ICONS[type] || 'Bug'} />;
@@ -62,10 +81,16 @@ export const TransactionRow = ({
6281 <span>
6382 <Icon icon={TRANSACTION_STATUS_ICONS[status] || 'Bug'} />
6483 </span>
65− <span>{status === 'pending' ? nextRoll : titleize(status)}</span>
84+ <span>
85+ {status === 'pending'
86+ ? nextRoll
87+ : status === 'confirmed'
88+ ? 'Completed'
89+ : titleize(status)}
90+ </span>
6691 </div>
6792 );
68− }, [status, nextRoll]);
93+ }, [nextRoll, status]);
6994
7095 return (
7196 <Box className="transaction-row">
@@ -76,7 +101,10 @@ export const TransactionRow = ({
76101 <Box className="status">{statusBadge}</Box>
77102 </Row>
78103 <Row className="info-row">
79− <Box className="hash">{shortHash}</Box>
104+ <Box className="hash-container">
105+ <Box className="hash">{shortHash}</Box>
106+ <LayerIndicator layer={2} size={'sm'} />
107+ </Box>
80108 <Box className="date" title={longDate}>
81109 {shortDate}
82110 </Box>