on master help sign in
rework file names
commitc2ab9d2862035795280d7273508be5dcd8f21ff8 authorLiam Fitzgerald <liam@urizen.co> dateWed 8 Jan 2020, 23:10 (7 years ago) parent8982cf8
5 files changed+197−197
src/views/Invite/Cohort.js+153−31 src/views/Invite/Inviter.js+40 src/views/Invite/Url.js+2−2 src/views/Party/ShowParty.js−162 src/views/Point.js+2−2
src/views/Invite/Cohort.js+153−31
@@ -1,40 +1,162 @@
1−import React, { useState } from 'react';
2−import { Grid } from 'indigo-react';
1+import React, { useMemo, useEffect, useCallback, useState } from 'react';
2+import { Grid, Flex } from 'indigo-react';
3+import * as ob from 'urbit-ob';
4+import { Just } from 'folktale/maybe';
5+import cn from 'classnames';
36
4−import Tabs from 'components/Tabs';
7+import { usePointCursor } from 'store/pointCursor';
8+import { usePointCache } from 'store/pointCache';
59
6−import InviteMail from 'views/Invite/Email';
7−import InviteUrl from 'views/Invite/Url';
10+import View from 'components/View';
11+import BarGraph from 'components/BarGraph';
12+import InviteSigilList from 'components/InviteSigilList';
13+import MaybeSigil from 'components/MaybeSigil';
14+import { matchBlinky } from 'components/Blinky';
15+import Chip from 'components/Chip';
16+import Crumbs from 'components/Crumbs';
17+
18+import { useLocalRouter } from 'lib/LocalRouter';
19+import useInvites from 'lib/useInvites';
20+import * as need from 'lib/need';
21+
22+import { ReactComponent as SearchIcon } from 'assets/search.svg';
23+
24+function CohortMember({ point, className }) {
25+ const { sentInvites } = useInvites(point);
26+ const patp = useMemo(() => ob.patp(point), [point]);
27+ const colors = ['#000000', '#FFFFFF'];
28+
29+ return (
30+ <Flex justify="between" className={cn('b1 b-gray2', className)}>
31+ <Flex.Item className="w9 h9">
32+ <MaybeSigil patp={Just(patp)} size={64} colors={colors} />
33+ </Flex.Item>
34+
35+ <Flex.Item
36+ flex={1}
37+ justify="evenly"
38+ as={Flex}
39+ col
40+ className="mono f6 ph4">
41+ <Flex.Item>{patp}</Flex.Item>
42+ <Flex.Item>{matchBlinky(sentInvites)} points invited</Flex.Item>
43+ </Flex.Item>
44+ </Flex>
45+ );
46+}
47+function CohortList({ points, className }) {
48+ const { syncInvites } = usePointCache();
49+
50+ const [query, setQuery] = useState('');
51+
52+ useEffect(() => {
53+ points.map(syncInvites);
54+ }, [points, syncInvites]);
55+
56+ const handleChange = useCallback(
57+ e => {
58+ setQuery(e.target.value);
59+ e.preventDefault();
60+ },
61+ [setQuery]
62+ );
63+
64+ const visiblePoints = useMemo(
65+ () =>
66+ points.filter(p => {
67+ const patp = ob.patp(p).slice(1);
68+ return patp.startsWith(query);
69+ }),
70+ [query, points]
71+ );
872
9−const InviteCohort = () => {
10− const [tab, setTab] = useState(NAMES.MAIL);
1173 return (
12− <Grid.Item
13− full
14− as={Tabs}
15− tabClassName="t-center flex1"
16− className="flex1"
17− views={VIEWS}
18− options={OPTIONS}
19− currentTab={tab}
20− onTabChange={setTab}
21− />
74+ <Grid gap={3} className={cn('mt1', className)}>
75+ <Grid.Item align="center" full as={Flex} className="b b-gray2 b1">
76+ <Flex.Item>
77+ <SearchIcon className="p2" />
78+ </Flex.Item>
79+
80+ <Flex.Item
81+ flex={1}
82+ as={'input'}
83+ value={query}
84+ onChange={handleChange}
85+ className="b-none"
86+ />
87+ </Grid.Item>
88+ <>
89+ {visiblePoints.map((p, idx) => (
90+ <Grid.Item key={p} half={(idx % 2) + 1} as={CohortMember} point={p} />
91+ ))}
92+ </>
93+ </Grid>
2294 );
23−};
95+}
2496
25−const NAMES = {
26− MAIL: 'MAIL',
27− URL: 'URL',
28−};
97+export default function InviteCohort() {
98+ const { pop } = useLocalRouter();
2999
30−const VIEWS = {
31− [NAMES.MAIL]: InviteMail,
32− [NAMES.URL]: InviteUrl,
33−};
100+ const { pointCursor } = usePointCursor();
101+ const point = need.point(pointCursor);
34102
35−const OPTIONS = [
36− { text: 'Email', value: NAMES.MAIL },
37− { text: 'URL', value: NAMES.URL },
38−];
103+ const {
104+ acceptedInvites,
105+ acceptedPoints,
106+ pendingPoints,
107+ availableInvites,
108+ sentInvites,
109+ } = useInvites(point);
39110
40−export default InviteCohort;
111+ const _acceptedPoints = acceptedPoints.getOrElse([]);
112+ const _pendingPoints = pendingPoints.getOrElse([]);
113+ const _pendingInvites = _pendingPoints.length;
114+ const _acceptedInvites = _acceptedPoints.length;
115+ const _totalInvites = availableInvites
116+ .map(a => sentInvites.getOrElse(0) + a)
117+ .getOrElse(0);
118+
119+ return (
120+ <View pop={pop} inset>
121+ <Grid gap={3}>
122+ <Grid.Item
123+ full
124+ as={Crumbs}
125+ className="mb1"
126+ routes={[
127+ { text: ob.patp(point), action: () => pop() },
128+ { text: 'Invite Group' },
129+ ]}
130+ />
131+
132+ <Grid.Item full>Invite Group</Grid.Item>
133+ <Grid.Item full>
134+ <Flex align="center">
135+ <Flex.Item>
136+ {_acceptedInvites + _pendingInvites} / {_totalInvites}
137+ </Flex.Item>
138+ {_pendingInvites && (
139+ <Flex.Item as={Chip} color="yellow">
140+ {_pendingInvites} pending
141+ </Flex.Item>
142+ )}
143+ </Flex>
144+ </Grid.Item>
145+ <Grid.Item
146+ full
147+ as={BarGraph}
148+ available={availableInvites}
149+ sent={sentInvites}
150+ accepted={acceptedInvites}
151+ />
152+ <Grid.Item
153+ full
154+ as={InviteSigilList}
155+ pendingPoints={pendingPoints}
156+ acceptedPoints={acceptedPoints}
157+ />
158+ <Grid.Item full as={CohortList} points={_acceptedPoints} />
159+ </Grid>
160+ </View>
161+ );
162+}
src/views/Invite/Inviter.jsnew file+40
@@ -0,0 +1,40 @@
1+import React, { useState } from 'react';
2+import { Grid } from 'indigo-react';
3+
4+import Tabs from 'components/Tabs';
5+
6+import InviteMail from 'views/Invite/Email';
7+import InviteUrl from 'views/Invite/Url';
8+
9+const Inviter = () => {
10+ const [tab, setTab] = useState(NAMES.MAIL);
11+ return (
12+ <Grid.Item
13+ full
14+ as={Tabs}
15+ tabClassName="t-center flex1"
16+ className="flex1"
17+ views={VIEWS}
18+ options={OPTIONS}
19+ currentTab={tab}
20+ onTabChange={setTab}
21+ />
22+ );
23+};
24+
25+const NAMES = {
26+ MAIL: 'MAIL',
27+ URL: 'URL',
28+};
29+
30+const VIEWS = {
31+ [NAMES.MAIL]: InviteMail,
32+ [NAMES.URL]: InviteUrl,
33+};
34+
35+const OPTIONS = [
36+ { text: 'Email', value: NAMES.MAIL },
37+ { text: 'URL', value: NAMES.URL },
38+];
39+
40+export default Inviter;
src/views/Invite/Url.js+2−2
@@ -30,7 +30,7 @@ const InviteUrl = () => {
3030 }
3131 }, [generateInvites]);
3232
33− const renderGenerateButton = () => {
33+ const renderGenerateButton = useCallback(() => {
3434 if (error) {
3535 return (
3636 <Grid.Item full className="mt4 p3 bg-red3 white f5">
@@ -66,7 +66,7 @@ const InviteUrl = () => {
6666 default:
6767 return null;
6868 }
69− };
69+ }, [txStatus, error, generateInvite]);
7070
7171 const url = `https://bridge.urbit.org/#${get(invites, '[0].ticket', '')}`;
7272
src/views/Party/ShowParty.jsdeleted−162
@@ -1,162 +0,0 @@
1−import React, { useMemo, useEffect, useCallback, useState } from 'react';
2−import { Grid, Flex } from 'indigo-react';
3−import * as ob from 'urbit-ob';
4−import { Just } from 'folktale/maybe';
5−import cn from 'classnames';
6−
7−import { usePointCursor } from 'store/pointCursor';
8−import { usePointCache } from 'store/pointCache';
9−
10−import View from 'components/View';
11−import BarGraph from 'components/BarGraph';
12−import InviteSigilList from 'components/InviteSigilList';
13−import MaybeSigil from 'components/MaybeSigil';
14−import { matchBlinky } from 'components/Blinky';
15−import Chip from 'components/Chip';
16−import Crumbs from 'components/Crumbs';
17−
18−import { useLocalRouter } from 'lib/LocalRouter';
19−import useInvites from 'lib/useInvites';
20−import * as need from 'lib/need';
21−
22−import { ReactComponent as SearchIcon } from 'assets/search.svg';
23−
24−function PartyItem({ point, className }) {
25− const { sentInvites } = useInvites(point);
26− const patp = useMemo(() => ob.patp(point), [point]);
27− const colors = ['#000000', '#FFFFFF'];
28−
29− return (
30− <Flex justify="between" className={cn('b1 b-gray2', className)}>
31− <Flex.Item className="w9 h9">
32− <MaybeSigil patp={Just(patp)} size={64} colors={colors} />
33− </Flex.Item>
34−
35− <Flex.Item
36− flex={1}
37− justify="evenly"
38− as={Flex}
39− col
40− className="mono f6 ph4">
41− <Flex.Item>{patp}</Flex.Item>
42− <Flex.Item>{matchBlinky(sentInvites)} points invited</Flex.Item>
43− </Flex.Item>
44− </Flex>
45− );
46−}
47−function PartyList({ points, className }) {
48− const { syncInvites } = usePointCache();
49−
50− const [query, setQuery] = useState('');
51−
52− useEffect(() => {
53− points.map(syncInvites);
54− }, [points, syncInvites]);
55−
56− const handleChange = useCallback(
57− e => {
58− setQuery(e.target.value);
59− e.preventDefault();
60− },
61− [setQuery]
62− );
63−
64− const visiblePoints = useMemo(
65− () =>
66− points.filter(p => {
67− const patp = ob.patp(p).slice(1);
68− return patp.startsWith(query);
69− }),
70− [query, points]
71− );
72−
73− return (
74− <Grid gap={3} className={cn('mt1', className)}>
75− <Grid.Item align="center" full as={Flex} className="b b-gray2 b1">
76− <Flex.Item>
77− <SearchIcon className="p2" />
78− </Flex.Item>
79−
80− <Flex.Item
81− flex={1}
82− as={'input'}
83− value={query}
84− onChange={handleChange}
85− className="b-none"
86− />
87− </Grid.Item>
88− <>
89− {visiblePoints.map((p, idx) => (
90− <Grid.Item key={p} half={(idx % 2) + 1} as={PartyItem} point={p} />
91− ))}
92− </>
93− </Grid>
94− );
95−}
96−
97−export default function ShowParty() {
98− const { pop } = useLocalRouter();
99−
100− const { pointCursor } = usePointCursor();
101− const point = need.point(pointCursor);
102−
103− const {
104− acceptedInvites,
105− acceptedPoints,
106− pendingPoints,
107− availableInvites,
108− sentInvites,
109− } = useInvites(point);
110−
111− const _acceptedPoints = acceptedPoints.getOrElse([]);
112− const _pendingPoints = pendingPoints.getOrElse([]);
113− const _pendingInvites = _pendingPoints.length;
114− const _acceptedInvites = _acceptedPoints.length;
115− const _totalInvites = availableInvites
116− .map(a => sentInvites.getOrElse(0) + a)
117− .getOrElse(0);
118−
119− return (
120− <View pop={pop} inset>
121− <Grid gap={3}>
122− <Grid.Item
123− full
124− as={Crumbs}
125− className="mb1"
126− routes={[
127− { text: ob.patp(point), action: () => pop() },
128− { text: 'Invite Group' },
129− ]}
130− />
131−
132− <Grid.Item full>Invite Group</Grid.Item>
133− <Grid.Item full>
134− <Flex align="center">
135− <Flex.Item>
136− {_acceptedInvites + _pendingInvites} / {_totalInvites}
137− </Flex.Item>
138− {_pendingInvites && (
139− <Flex.Item as={Chip} color="yellow">
140− {_pendingInvites} pending
141− </Flex.Item>
142− )}
143− </Flex>
144− </Grid.Item>
145− <Grid.Item
146− full
147− as={BarGraph}
148− available={availableInvites}
149− sent={sentInvites}
150− accepted={acceptedInvites}
151− />
152− <Grid.Item
153− full
154− as={InviteSigilList}
155− pendingPoints={pendingPoints}
156− acceptedPoints={acceptedPoints}
157− />
158− <Grid.Item full as={PartyList} points={_acceptedPoints} />
159− </Grid>
160− </View>
161− );
162−}
src/views/Point.js+2−2
@@ -25,7 +25,7 @@ import useCurrentPermissions from 'lib/useCurrentPermissions';
2525import { useLocalRouter } from 'lib/LocalRouter';
2626import useKeyfileGenerator from 'lib/useKeyfileGenerator';
2727
28−import InviteCohort from 'views/Invite/Cohort';
28+import Inviter from 'views/Invite/Inviter';
2929
3030export default function Point() {
3131 const { pop, push, names } = useLocalRouter();
@@ -220,7 +220,7 @@ export default function Point() {
220220 Add Members
221221 </Grid.Item>
222222 )}
223− {showInviteForm && <InviteCohort />}
223+ {showInviteForm && <Inviter />}
224224 </>
225225 )}
226226 </Grid>