on master help sign in
Merge pull request #189 from urbit/indigo-admin-helper
938072cFang
src/lib/usePermissionsForPoint.js+2
@@ -30,6 +30,7 @@ export default function usePermissionsForPoint(address, point) {
30 const isGalaxy = pointSize === azimuth.PointSize.Galaxy;
30 const isGalaxy = pointSize === azimuth.PointSize.Galaxy;
31
31
32 const isOwner = eqAddr(address, details.owner);
32 const isOwner = eqAddr(address, details.owner);
33+ const isActiveOwner = isOwner && details.active;
33 const isTransferProxy = eqAddr(address, details.transferProxy);
34 const isTransferProxy = eqAddr(address, details.transferProxy);
34 const isManagementProxy = eqAddr(address, details.managementProxy);
35 const isManagementProxy = eqAddr(address, details.managementProxy);
35 const isSpawnProxy = eqAddr(address, details.spawnProxy);
36 const isSpawnProxy = eqAddr(address, details.spawnProxy);
@@ -43,6 +44,7 @@ export default function usePermissionsForPoint(address, point) {
43
44
44 return {
45 return {
45 isOwner,
46 isOwner,
47+ isActiveOwner,
46 isTransferProxy,
48 isTransferProxy,
47 isManagementProxy,
49 isManagementProxy,
48 canManage,
50 canManage,
src/views/Admin/AdminEditPermissions.js+31−29
@@ -2,6 +2,7 @@ import React, { useState, useCallback } from 'react';
2import { Just, Nothing } from 'folktale/maybe';
2import { Just, Nothing } from 'folktale/maybe';
3import * as need from 'lib/need';
3import * as need from 'lib/need';
4import { Grid } from 'indigo-react';
4import { Grid } from 'indigo-react';
5+import { azimuth } from 'azimuth-js';
5
6
6import { ForwardButton } from 'components/Buttons';
7import { ForwardButton } from 'components/Buttons';
7import { matchBlinky, matchBlinkyDate } from 'components/Blinky';
8import { matchBlinky, matchBlinkyDate } from 'components/Blinky';
@@ -19,6 +20,7 @@ import { PROXY_TYPE, proxyTypeToHuman } from 'lib/proxy';
19import { useLocalRouter } from 'lib/LocalRouter';
20import { useLocalRouter } from 'lib/LocalRouter';
20import { formatDots } from 'lib/dateFormat';
21import { formatDots } from 'lib/dateFormat';
21import capitalize from 'lib/capitalize';
22import capitalize from 'lib/capitalize';
23+import { eqAddr } from 'lib/wallet';
22
24
23//TODO consolidate with azimuth-js' getActivationBlock
25//TODO consolidate with azimuth-js' getActivationBlock
24const getRekeyDate = async (web3, contracts, point) => {
26const getRekeyDate = async (web3, contracts, point) => {
@@ -43,24 +45,25 @@ export default function AdminEditPermissions() {
43 const { pointCursor } = usePointCursor();
45 const { pointCursor } = usePointCursor();
44 const { getDetails } = usePointCache();
46 const { getDetails } = usePointCache();
45
47
48+ const _web3 = need.web3(web3);
49+ const _contracts = need.contracts(contracts);
50+
46 const [rekeyDate, setRekeyDate] = useState(Nothing());
51 const [rekeyDate, setRekeyDate] = useState(Nothing());
47
52
48 const point = need.point(pointCursor);
53 const point = need.point(pointCursor);
54+ const pointSize = azimuth.getPointSize(point);
55+ const isParent = pointSize !== azimuth.PointSize.Planet;
56+ const isSenate = pointSize === azimuth.PointSize.Galaxy;
49 const userAddress = need.wallet(wallet).address;
57 const userAddress = need.wallet(wallet).address;
50
58
51 const details = need.details(getDetails(point));
59 const details = need.details(getDetails(point));
52− const { canManage, canTransfer, canSpawn, canVote } = usePermissionsForPoint(
60+ const { canManage, isOwner } = usePermissionsForPoint(userAddress, point);
53− userAddress,
54− point
55− );
56
61
57 useLifecycle(() => {
62 useLifecycle(() => {
58− getRekeyDate(need.web3(web3), need.contracts(contracts), point).then(
63+ getRekeyDate(_web3, _contracts, point).then(res => {
59− res => {
60− if (res === null) setRekeyDate(Just(new Date()));
64+ if (res === null) setRekeyDate(Just(new Date()));
61− else setRekeyDate(Just(res));
65+ else setRekeyDate(Just(res));
62− }
63− );
66+ });
64 });
67 });
65
68
66 const goToProxy = useCallback(
69 const goToProxy = useCallback(
@@ -71,8 +74,10 @@ export default function AdminEditPermissions() {
71 const goSetKeys = useCallback(() => push(names.SET_KEYS), [push, names]);
74 const goSetKeys = useCallback(() => push(names.SET_KEYS), [push, names]);
72
75
73 const proxyAction = (proxyType, address, enabled) => {
76 const proxyAction = (proxyType, address, enabled) => {
74− if (address === ETH_ZERO_ADDR) {
77+ if (eqAddr(address, ETH_ZERO_ADDR)) {
75− address = 'Not yet set';
78+ address = 'Not set';
79+ } else if (eqAddr(address, _contracts.delegatedSending.address)) {
80+ address = address + ' (invites contract)';
76 }
81 }
77
82
78 const detail = enabled
83 const detail = enabled
@@ -82,14 +87,17 @@ export default function AdminEditPermissions() {
82 )} proxy.`;
87 )} proxy.`;
83
88
84 return (
89 return (
90+ <>
85− <Grid.Item full>
91+ <Grid.Item full>
86− <ForwardButton
92+ <ForwardButton
87− disabled={!enabled}
93+ disabled={!enabled}
88− onClick={() => goToProxy(proxyType)}
94+ onClick={() => goToProxy(proxyType)}
89− detail={detail}>
95+ detail={detail}>
90− {capitalize(proxyTypeToHuman(proxyType))} Proxy Address
96+ {capitalize(proxyTypeToHuman(proxyType))} Proxy Address
91− </ForwardButton>
97+ </ForwardButton>
92− </Grid.Item>
98+ </Grid.Item>
99+ <Grid.Divider />
100+ </>
93 );
101 );
94 };
102 };
95
103
@@ -114,17 +122,11 @@ export default function AdminEditPermissions() {
114 </Grid.Item>
122 </Grid.Item>
115 <Grid.Divider />
123 <Grid.Divider />
116
124
117− {proxyAction(PROXY_TYPE.MANAGEMENT, details.managementProxy, canManage)}
125+ {proxyAction(PROXY_TYPE.MANAGEMENT, details.managementProxy, isOwner)}
118− <Grid.Divider />
119
126
120− {proxyAction(PROXY_TYPE.SPAWN, details.spawnProxy, canSpawn)}
127+ {isParent && proxyAction(PROXY_TYPE.SPAWN, details.spawnProxy, isOwner)}
121− <Grid.Divider />
122
128
123− {proxyAction(PROXY_TYPE.TRANSFER, details.transferProxy, canTransfer)}
124− <Grid.Divider />
125−
126− {proxyAction(PROXY_TYPE.VOTING, details.votingProxy, canVote)}
129+ {isSenate && proxyAction(PROXY_TYPE.VOTING, details.votingProxy, isOwner)}
127− <Grid.Divider />
128
130
129 <Grid.Item
131 <Grid.Item
130 full
132 full
src/views/Point.js+36−10
@@ -1,7 +1,8 @@
1−import React, { useCallback } from 'react';
1+import React, { useCallback, useMemo } from 'react';
2import { Just } from 'folktale/maybe';
2import { Just } from 'folktale/maybe';
3import * as need from 'lib/need';
3import * as need from 'lib/need';
4import { Grid } from 'indigo-react';
4import { Grid } from 'indigo-react';
5+import { azimuth } from 'azimuth-js';
5
6
6import { usePointCursor } from 'store/pointCursor';
7import { usePointCursor } from 'store/pointCursor';
7import { useHistory } from 'store/history';
8import { useHistory } from 'store/history';
@@ -20,14 +21,17 @@ import Actions from './Point/Actions';
20import { useWallet } from 'store/wallet';
21import { useWallet } from 'store/wallet';
21import usePermissionsForPoint from 'lib/usePermissionsForPoint';
22import usePermissionsForPoint from 'lib/usePermissionsForPoint';
22
23
24+const isPlanet = point =>
25+ azimuth.getPointSize(point) === azimuth.PointSize.Planet;
26+
23export default function Point() {
27export default function Point() {
24− const history = useHistory();
28+ const { push, names } = useHistory();
25 const { pointCursor } = usePointCursor();
29 const { pointCursor } = usePointCursor();
26 const { wallet } = useWallet();
30 const { wallet } = useWallet();
27
31
28 const point = need.point(pointCursor);
32 const point = need.point(pointCursor);
29
33
30− const { canManage } = usePermissionsForPoint(
34+ const { isActiveOwner, canManage } = usePermissionsForPoint(
31 // using empty string should be ok here
35 // using empty string should be ok here
32 wallet.matchWith({
36 wallet.matchWith({
33 Nothing: () => '',
37 Nothing: () => '',
@@ -38,16 +42,40 @@ export default function Point() {
38
42
39 // fetch the invites for the current cursor
43 // fetch the invites for the current cursor
40 const { availableInvites } = useInvites(point);
44 const { availableInvites } = useInvites(point);
41− const availableInvitesText = matchBlinky(availableInvites);
42
45
43 const showActions = Just.hasInstance(wallet);
46 const showActions = Just.hasInstance(wallet);
44
47
45− const goAdmin = useCallback(() => history.push(ROUTE_NAMES.ADMIN), [history]);
48+ const goAdmin = useCallback(() => push(names.ADMIN), [push, names]);
49+
50+ const goInvite = useCallback(() => push(names.INVITE), [push, names]);
46
51
47− const goInvite = useCallback(() => history.push(ROUTE_NAMES.INVITE), [
52+ const goParties = useCallback(() => push(names.INVITES_MANAGE), [
48− history,
53+ push,
54+ names,
49 ]);
55 ]);
50
56
57+ const inviteButton = (() => {
58+ switch (azimuth.getPointSize(point)) {
59+ case azimuth.PointSize.Planet:
60+ const availableInvitesText = matchBlinky(availableInvites);
61+ return (
62+ <FooterButton disabled={!isActiveOwner} onClick={goInvite}>
63+ Invite <sup>{availableInvitesText} available</sup>
64+ </FooterButton>
65+ );
66+ //
67+ case azimuth.PointSize.Star:
68+ return (
69+ <FooterButton disabled={!isActiveOwner} onClick={goParties}>
70+ Manage parties
71+ </FooterButton>
72+ );
73+ //
74+ default:
75+ return null;
76+ }
77+ })();
78+
51 // sync the current cursor
79 // sync the current cursor
52 useSyncOwnedPoints([point]);
80 useSyncOwnedPoints([point]);
53
81
@@ -73,9 +101,7 @@ export default function Point() {
73 )}
101 )}
74 </Grid>
102 </Grid>
75
103
76− <FooterButton disabled={!canManage} onClick={goInvite}>
104+ {inviteButton}
77− Invite <sup>{availableInvitesText} available</sup>
78− </FooterButton>
79 </View>
105 </View>
80 );
106 );
81}
107}