on master help sign in
Merge branch 'mino' into new-sigil-js
commitc6db5dd19d5be349233f691224f0a03b35e7d6da authorMatt Condon (shrugs) <mattgcondon@gmail.com> dateTue 23 Jul 2019, 12:36 (7 years ago) parentc50a97da77fa97
53 files changed+175−2415
DEVELOPMENT.md+99 README.md+23−119 src/components/old/Anchor.js−28 src/components/old/Base.js−180 src/components/old/Blockie.js−17 src/components/old/Breadcrumb.js−9 src/components/old/BreadcrumbItem.js−9 src/components/old/Button.js−21 src/components/old/Checkbox.js−50 src/components/old/CheckboxButton.js−55 src/components/old/Code.js−34 src/components/old/Col.js−23 src/components/old/DropdownDivider.js−11 src/components/old/DropdownItem.js−35 src/components/old/FlexCol.js−23 src/components/old/FlexRow.js−17 src/components/old/Form.js−23 src/components/old/H1.js−25 src/components/old/H2.js−23 src/components/old/H3.js−23 src/components/old/H4.js−23 src/components/old/HorizontalSelector.js−51 src/components/old/InnerLabel.js−25 src/components/old/InnerLabelDropdown.js−115 src/components/old/Input.js−67 src/components/old/InputCaption.js−25 src/components/old/Label.js−23 src/components/old/P.js−34 src/components/old/PointList.js−32 src/components/old/ProtoAnchor.js−27 src/components/old/ProtoButton.js−39 src/components/old/ProtoInput.js−66 src/components/old/ProtoTextarea.js−62 src/components/old/RenderedPoint.js−57 src/components/old/Row.js−23 src/components/old/RowCol.js−25 src/components/old/ShowBlockie.js−70 src/components/old/Spacing.js−25 src/components/old/Textarea.js−67 src/components/old/UploadButton.js−31 src/components/old/ValidatedBlockie.js−64 src/components/old/ValidatedSigil.js−75 src/components/old/Warning.js−23 src/components/old/advancedInput.js−147 src/lib/constants.js+1−1 src/lib/useEthereumTransaction.js+2−1 src/lib/usePermissionsForPoint.js+10−3 src/views/GenKeyfile.js−142 src/views/Point.js+12−3 src/views/Point/Actions.js−188 src/views/Point/KeysAndMetadata.js−151 src/views/Points.js+27−2 src/views/ViewPoint.js+1−3
DEVELOPMENT.mdnew file+99
@@ -0,0 +1,99 @@
1+# Development notes
2+
3+## Install / Build
4+
5+Clone the repo, and use a simple `npm install`. You can then use a `npm run build` to create an optimised static build (serve it with e.g. [serve](http://npmjs.com/package/serve), or with python as described above).
6+
7+## General notes
8+
9+For development, use `npm run pilot` to get going after a `npm install`. This
10+will boot up a [Ganache](https://github.com/trufflesuite/ganache-cli) node in the background, deploy the Azimuth contracts to
11+it, and fire up a local webserver. Bridge will be served on `localhost:3000`.
12+
13+Note that one of our dependencies itself depends on a library called
14+`handle-thing` which breaks under the Ledger support requirements (see below)
15+on node 11.1.0, so make sure you're using some other node version.
16+
17+You can use [nvm](https://github.com/creationix/nvm), for example, and do:
18+
19+```
20+$ nvm install 11.0.0
21+$ nvm use v11.0.0
22+```
23+
24+before running `npm run pilot`.
25+
26+## Useful accounts
27+
28+The ecliptic owner is the only account that's able to create galaxies, so
29+it's a good place to get started. On the testnet, it's the address:
30+
31+```
32+0x6DEfFb0caFDB11D175F123F6891AA64F01c24F7d
33+```
34+
35+You can authenticate as it using the following mnemonic:
36+
37+```
38+benefit crew supreme gesture quantum web media hazard theory mercy wing kitten
39+```
40+
41+Under that mnemonic, Ganache will also auto-populate the following accounts
42+with 100 ETH:
43+
44+```
45+0x6deffb0cafdb11d175f123f6891aa64f01c24f7d
46+0xd53208cf45fc9bd7938b200bff8814a26146688f
47+0x7b2a2d51e4d8fac602e20a5f6907ff9fbd88e1fd
48+0xf48062ae8bafd6ef19cd6cb89db93a0d0ca6ce26
49+0xf84a77aeb351c49dfa87e805a659d2daddff7606
50+0x167e357cf8b845370d0d408f9b389b66185b7b5b
51+0xcbecf3abc9878f07afc851aead2d8f1c436cc71d
52+0x0afc0c3f4eeea500871f464ca71eef5e54a9af36
53+0x6d654ef2489674d21aed428e8a4ad8ca4820f125
54+0x218f6f87683db546ad47a5dc8b480e5a9b694866
55+```
56+
57+To play around with any of these, authenticate using the same mnemonic, but
58+use a custom HD path of `m/44'/60'/0'/0/1`, `m/44'/60'/0'/0/2`, and so on.
59+
60+## Initial development state
61+
62+You can also tweak a couple of things to change your development state
63+somewhat (say, for example, you want to start on the points list screen, instead
64+of having to re-authenticate whenever you make a change or refresh the page):
65+
66+- The `.env.development` file contains environment variables that you can
67+ provide to the application when it's running in development. You can access
68+ them via `process.env.REACT_APP_<whatever>`.
69+
70+- Set `REACT_APP_STUB_LOCAL='true'` in `.env.development` to enabled stubbing of
71+ certain methods throughout the app.
72+
73+- The top of the Bridge component in `src/Bridge.js` can be tweaked for setting
74+ your initial state. You can provide a specific wallet,
75+ network type, and so on.
76+
77+## HTTPS
78+
79+For development, you can enable HTTPS on localhost without a certificate for
80+Chrome by pasting the following into the URL bar:
81+
82+```
83+chrome://flags/#allow-insecure-localhost
84+```
85+
86+In Firefox, you may need to allow connecting to the unsecured local node
87+websocket. Do this by going to `about:config` and setting the
88+`network.websocket.allowInsecureFromHTTPS` flag to `true`.
89+
90+Additionally you need to run with the `HTTPS` environment variable set to
91+`true`. Note that `npm run pilot` will handle this automatically.
92+
93+## Releases
94+
95+To generate a release `bridge-$VERSION.zip` file, use a simple `npm run release`.
96+
97+This will pack the build directory together with the README, `bridge-https.py`
98+script, and also generate a set of checksums for the build directory. You can
99+verify the checksums on e.g. MacOS via `shasum -c checksums.txt`.
README.md+23−119
@@ -6,147 +6,51 @@ An application for interacting with Azimuth.
66
77## Usage
88
9+The latest version of Bridge is accessible online at [bridge.azimuth.network](https://bridge.azimuth.network). No setup needed.
10+
11+If you would rather host Bridge on your own machine, read on.
12+
913### Requirements
1014
1115Python 3.7.2
1216
1317### Instructions
1418
15−#### Install
19+#### Download
1620
17−1. [Download a release](https://github.com/urbit/bridge/releases)
21+1. [Download a release](https://github.com/urbit/bridge/releases/latest)
18222. Unzip it (`bridge-$version.zip`)
19233. Open up your command line interface (Terminal on MacOS, Command Prompt on Windows)
20244. `cd` into the `bridge-$version` directory
2125
22−Follow the instructions below to run Bridge.
23−
24−#### Run Bridge
26+#### Verify checksums
2527
26−If you plan to authenticate and sign transactions with a Master Ticket, BIP39 mnemonic, Ethereum private key, or keystore file:
27−
28−1. `cd` into the `bridge-$version` directory
29−2. Run `python3 -m http.server 5000 --bind 127.0.0.1`
30−3. Navigate to http://localhost:5000 using a web browser to access Bridge (we recommend using Firefox or Chrome)
31−
32−#### Run Bridge with Ledger support
33−
34−If you plan to authenticate and sign transactions with a [Ledger](https://www.ledger.com/), Bridge must be serving over HTTPS on localhost. This requires self-signed certificates. To do this:
35−
36−1. Install [mkcert](https://github.com/FiloSottile/mkcert)
37−2. If you're using Firefox, additionally install [nss](https://github.com/nss-dev/nss)
38−3. Install a local certificate authority via `mkcert -install`
39−4. From the `bridge-$version` directory, run `mkcert localhost` to generate a certificate valid for localhost. This will produce two files: `localhost.pem`, the local certificate, and `localhost-key.pem`, its corresponding private key
40−5. Run `python bridge-https.py`
41−6. Navigate to https://localhost:4443 in a web browser to access Bridge
42−
43−### Verify checksums
44−
45−To validate your downloaded file's integrity, compare the lines in checksum.txt to SHA-256 hashes of the `bridge-$version` directory's contents.
28+Optionally, to validate your downloaded file's integrity, compare the lines in checksum.txt to SHA-256 hashes of the `bridge-$version` directory's contents.
4629
4730- On MacOS: `shasum -a 256 -c checksums.txt .`
4831- On Linux: `sha256sum -c checksums.txt .`
4932- On Windows: Go into the `build` directory and verify files individually with `CertUtil -hashFile [file_name] SHA256`
5033
51−## Development notes
52−
53−### Install / Build
54−
55−Clone the repo, and use a simple `npm install`. You can then use a `npm run build` to create an optimised static build (serve it with e.g. [serve][serv]).
56−
57−### General notes
58−
59−For development, use `npm run pilot` to get going after a `npm install`. This
60−will boot up a Ganache node in the background, deploy the Azimuth contracts to
61−it, and fire up a local webserver. Bridge will be served on `localhost:3000`.
62−
63−Note that one of our dependencies itself depends on a library called
64−`handle-thing` which breaks under the Ledger support requirements (see below)
65−on node 11.1.0, so make sure you're using some other node version.
66−
67−You can use [nvm](https://github.com/creationix/nvm), for example, and do:
68−
69−```
70−$ nvm install 11.0.0
71−$ nvm use v11.0.0
72−```
73−
74−before running `npm run pilot`.
75−
76−### Useful accounts
77−
78−The ecliptic owner is the only account that's able to create galaxies, so
79−it's a good place to get started. On the testnet, it's the address:
80−
81−```
82−0x6DEfFb0caFDB11D175F123F6891AA64F01c24F7d
83−```
84−
85−You can authenticate as it using the following mnemonic:
86−
87−```
88−benefit crew supreme gesture quantum web media hazard theory mercy wing kitten
89−```
90−
91−Under that mnemonic, Ganache will also auto-populate the following accounts
92−with 100 ETH:
93−
94−```
95−0x6deffb0cafdb11d175f123f6891aa64f01c24f7d
96−0xd53208cf45fc9bd7938b200bff8814a26146688f
97−0x7b2a2d51e4d8fac602e20a5f6907ff9fbd88e1fd
98−0xf48062ae8bafd6ef19cd6cb89db93a0d0ca6ce26
99−0xf84a77aeb351c49dfa87e805a659d2daddff7606
100−0x167e357cf8b845370d0d408f9b389b66185b7b5b
101−0xcbecf3abc9878f07afc851aead2d8f1c436cc71d
102−0x0afc0c3f4eeea500871f464ca71eef5e54a9af36
103−0x6d654ef2489674d21aed428e8a4ad8ca4820f125
104−0x218f6f87683db546ad47a5dc8b480e5a9b694866
105−```
106−
107−To play around with any of these, authenticate using the same mnemonic, but
108−use a custom HD path of `m/44'/60'/0'/0/1`, `m/44'/60'/0'/0/2`, and so on.
109−
110−### Initial development state
111−
112−You can also tweak a couple of things to change your development state
113−somewhat (say, for example, you want to start on the points list screen, instead
114−of having to re-authenticate whenever you make a change or refresh the page):
115−
116−- The `.env.development` file contains environment variables that you can
117− provide to the application when it's running in development. You can access
118− them via `process.env.REACT_APP_<whatever>`.
119−
120−- Set `REACT_APP_STUB_LOCAL='true'` in `.env.development` to enabled stubbing of
121− certain methods throughout the app.
122−
123−- The top of the Bridge component in `src/Bridge.js` can be tweaked for setting
124− your initial state. You can provide a specific wallet,
125− network type, and so on.
126−
127−### HTTPS
34+#### Run Bridge
12835
129−For development, you can enable HTTPS on localhost without a certificate for
130−Chrome by pasting the following into the URL bar:
36+1. `cd` into the `bridge-$version` directory
37+2. Run `python3 -m http.server 5000 --bind 127.0.0.1`
38+3. Navigate to http://localhost:5000 using a web browser to access Bridge (we recommend using Firefox or Chrome)
13139
132−```
133−chrome://flags/#allow-insecure-localhost
134−```
40+#### Ledger support
13541
136−In Firefox, you may need to allow connecting to the unsecured local node
137−websocket. Do this by going to `about:config` and setting the
138−`network.websocket.allowInsecureFromHTTPS` flag to `true`.
42+If you plan to authenticate with a [Ledger](https://www.ledger.com/), Bridge must be serving over HTTPS on localhost. This requires self-signed certificates. To do this:
13943
140−Additionally you need to run with the `HTTPS` environment variable set to
141−`true`. Note that `npm run pilot` will handle this automatically.
44+1. Install [mkcert](https://github.com/FiloSottile/mkcert)
45+2. Install a local certificate authority via `mkcert -install`
46+3. From the `bridge-$version` directory, run `mkcert localhost` to generate a certificate valid for localhost. This will produce two files: `localhost.pem`, the local certificate, and `localhost-key.pem`, its corresponding private key
47+4. Run `python bridge-https.py`
48+5. Navigate to https://localhost:4443 in a web browser to access Bridge
14249
143−### Releases
50+## Bridge without internet access
14451
145−To generate a release `bridge-$VERSION.zip` file, use a simple `npm run release`.
52+A proper "offline mode" for the latest iteration of Bridge is still being worked on. In the mean time, if you need to use Bridge on an airgapped machine, use [Bridge v1.4.1](https://github.com/urbit/bridge/releases/tag/v1.4.1).
14653
147−This will pack the build directory together with the README, `bridge-https.py`
148−script, and also generate a set of checksums for the build directory. You can
149−verify the checksums on e.g. OS X via `shasum -c checksums.txt`.
54+## Development
15055
151−[rele]: https://github.com/urbit/bridge/releases/latest
152−[serv]: http://npmjs.com/package/serve
56+See [development.md](DEVELOPMENT.md).
src/components/old/Anchor.jsdeleted−28
@@ -1,28 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−import ProtoAnchor from './ProtoAnchor';
5−
6−const Anchor = props => {
7− return (
8− <ProtoAnchor {...props} prop-disabled={`${props['prop-disabled']}`}>
9− {props.children}
10− </ProtoAnchor>
11− );
12−};
13−
14−Anchor.propTypes = {
15− 'prop-disabled': PropTypes.bool,
16− 'prop-color': PropTypes.string,
17− 'prop-size': PropTypes.string,
18− 'prop-type': PropTypes.string,
19−};
20−
21−Anchor.defaultProps = {
22− 'prop-disabled': false,
23− 'prop-color': 'black',
24− 'prop-size': 'md',
25− 'prop-type': 'link',
26−};
27−
28−export default Anchor;
src/components/old/Base.jsdeleted−180
@@ -1,180 +0,0 @@
1−// Helpers
2−import {
3− simpleValidatorWrapper,
4− validateMnemonic,
5− validateNotEmpty,
6− validateEthereumAddress,
7− validateGalaxy,
8− validatePoint,
9− validateTicket,
10− validateNetworkKey,
11− validateNetworkSeed,
12− validateShard,
13−} from '../../lib/validators';
14−
15−import { prependSig } from '../../lib/transformers';
16−
17−// Buttons
18−import Button from './Button';
19−import UploadButton from './UploadButton';
20−// import Checkbox from './Checkbox';
21−import CheckboxButton from './CheckboxButton';
22−import Anchor from './Anchor';
23−// import ToggleButton from './ToggleButton';
24−
25−// Input
26−import Form from './Form';
27−import Label from './Label';
28−import InnerLabel from './InnerLabel';
29−import InputCaption from './InputCaption';
30−import Input from './Input';
31−import Textarea from './Textarea';
32−import advancedInput from './advancedInput';
33−
34−// Dropdowns
35−import DropdownItem from './DropdownItem';
36−import DropdownDivider from './DropdownDivider';
37−import InnerLabelDropdown from './InnerLabelDropdown';
38−
39−// Option selectors
40−import HorizontalSelector from './HorizontalSelector';
41−
42−// Path Control
43−import Breadcrumb from './Breadcrumb';
44−import BreadcrumbItem from './BreadcrumbItem';
45−
46−// Layout
47−import Col from './Col';
48−import Row from './Row';
49−// import FlexRow from './FlexRow';
50−// import FlexCol from './FlexCol';
51−import Spacing from './Spacing';
52−
53−// Type
54−import H1 from './H1';
55−import H2 from './H2';
56−import H3 from './H3';
57−import H4 from './H4';
58−import P from './P';
59−import Code from './Code';
60−import Warning from './Warning';
61−
62−// Misc
63−import ValidatedSigil from './ValidatedSigil';
64−import ValidatedBlockie from './ValidatedBlockie';
65−import ShowBlockie from './ShowBlockie';
66−
67−// HOC validated form components
68−
69−const RequiredInput = advancedInput({
70− WrappedComponent: Input,
71− validators: [validateNotEmpty],
72−});
73−
74−const NetworkKeyInput = advancedInput({
75− WrappedComponent: Input,
76− validators: [validateNotEmpty, validateNetworkKey],
77−});
78−
79−const NetworkSeedInput = advancedInput({
80− WrappedComponent: Input,
81− validators: [validateNotEmpty, validateNetworkSeed],
82−});
83−
84−const AddressInput = advancedInput({
85− WrappedComponent: Input,
86− validators: [validateEthereumAddress, validateNotEmpty],
87−});
88−
89−const MnemonicInput = advancedInput({
90− WrappedComponent: Textarea,
91− validators: [validateMnemonic, validateNotEmpty],
92−});
93−
94−const GalaxyInput = advancedInput({
95− WrappedComponent: Input,
96− validators: [validateGalaxy, validateNotEmpty],
97− transformers: [prependSig],
98−});
99−
100−const PointInput = advancedInput({
101− WrappedComponent: Input,
102− validators: [validatePoint, validateNotEmpty],
103− transformers: [prependSig],
104−});
105−
106−const TicketInput = advancedInput({
107− WrappedComponent: Input,
108− validators: [validateTicket, validateNotEmpty],
109− transformers: [prependSig],
110−});
111−
112−const VerifyTicketInput = matchingTicket =>
113− advancedInput({
114− WrappedComponent: Input,
115− validators: [
116− validateTicket,
117− validateNotEmpty,
118−
119− // TODO: This should be in /lib/validators, but we'd need a way for
120− // validators to compare against dynamic values
121− m =>
122− simpleValidatorWrapper({
123− prevMessage: m,
124− validator: d => d === matchingTicket,
125− errorMessage: 'This does not match the provided master ticket',
126− }),
127− ],
128− transformers: [prependSig],
129− });
130−
131−const ShardInput = advancedInput({
132− WrappedComponent: Input,
133− validators: [validateShard],
134− transformers: [],
135−});
136−
137−export {
138− Button,
139− CheckboxButton,
140− UploadButton,
141− Anchor,
142− InputCaption,
143− Form,
144− Label,
145− Input,
146− InnerLabel,
147− Textarea,
148− AddressInput,
149− MnemonicInput,
150− GalaxyInput,
151− PointInput,
152− TicketInput,
153− VerifyTicketInput,
154− ShardInput,
155− RequiredInput,
156− NetworkKeyInput,
157− NetworkSeedInput,
158− advancedInput,
159− ValidatedSigil,
160− ValidatedBlockie,
161− ShowBlockie,
162− DropdownItem,
163− DropdownDivider,
164− InnerLabelDropdown,
165− HorizontalSelector,
166− Breadcrumb,
167− BreadcrumbItem,
168− Col,
169− Row,
170− // FlexRow,
171− // FlexCol,
172− Spacing,
173− H1,
174− H2,
175− H3,
176− H4,
177− P,
178− Code,
179− Warning,
180−};
src/components/old/Blockie.jsdeleted−17
@@ -1,17 +0,0 @@
1−import React from 'react';
2−import makeBlockie from 'ethereum-blockies-base64';
3−
4−const isValidAddress = address => /^0x[0-9a-fA-F]{40}$/.test(address);
5−
6−const Blockie = props =>
7− isValidAddress(props.address) ? (
8− <img
9− className={`s-10 ${props.className}`}
10− alt={props.address}
11− src={makeBlockie(props.address)}
12− />
13− ) : (
14− <div className={`s-10 ${props.className}`} />
15− );
16−
17−export default Blockie;
src/components/old/Breadcrumb.jsdeleted−9
@@ -1,9 +0,0 @@
1−import React from 'react';
2−
3−const Breadcrumb = ({ disabled, onClick, className, children }) => (
4− <div className={`flex ${className}`} onClick={onClick} disabled={disabled}>
5− {children}
6− </div>
7−);
8−
9−export default Breadcrumb;
src/components/old/BreadcrumbItem.jsdeleted−9
@@ -1,9 +0,0 @@
1−import React from 'react';
2−
3−const BreadcrumbItem = ({ disabled, onClick, className, children }) => (
4− <div className={`${className}`} onClick={onClick} disabled={disabled}>
5− {children}
6− </div>
7−);
8−
9−export default BreadcrumbItem;
src/components/old/Button.jsdeleted−21
@@ -1,21 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−import ProtoButton from './ProtoButton';
4−
5−const Button = props => {
6− return <ProtoButton {...props}>{props.children}</ProtoButton>;
7−};
8−
9−Button.propTypes = {
10− 'prop-color': PropTypes.string,
11− 'prop-size': PropTypes.string,
12− 'prop-type': PropTypes.string,
13−};
14−
15−Button.defaultProps = {
16− 'prop-color': 'blue',
17− 'prop-size': 'md',
18− 'prop-type': 'solid',
19−};
20−
21−export default Button;
src/components/old/Checkbox.jsdeleted−50
@@ -1,50 +0,0 @@
1−import React from 'react';
2−
3−const CheckBox = ({
4− name,
5− id,
6− title,
7− subtitle,
8− onChange,
9− className,
10− state,
11− children,
12− childContainerClassname,
13− disabled,
14−}) => {
15− const isCheckedClassname = state === true ? 'cb-on' : 'cb-off';
16−
17− return (
18− <div className={`cb flex items-center ${isCheckedClassname} ${className}`}>
19− <label className={'s-6 m-0 mr-4 rel outline-blue'}>
20− <input
21− disabled={disabled}
22− name={name}
23− id={id}
24− type={'checkbox'}
25− className={'none'}
26− checked={state}
27− onChange={onChange}
28− />
29−
30− <svg
31− width="24"
32− height="24"
33− viewBox="0 0 24 24"
34− fill="none"
35− xmlns="http://www.w3.org/2000/svg">
36− <path
37− d="M2 3.55661V0H0V5.55661H12.4182V3.55661H2Z"
38− transform="translate(4 11) rotate(-45)"
39− fill="white"
40− />
41− </svg>
42− </label>
43− <div className={`user-select-none ${childContainerClassname} mt-1`}>
44− {children}
45− </div>
46− </div>
47− );
48−};
49−
50−export default CheckBox;
src/components/old/CheckboxButton.jsdeleted−55
@@ -1,55 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−import ProtoButton from './ProtoButton';
4−
5−const CheckboxButton = props => {
6− const onOff =
7− props.state === true
8− ? 'cb-on br-blue bg-blue outline-blue'
9− : 'bg-transparent br-black outline-blue';
10−
11− const checkmarkState = props.state === true ? 'o-100' : 'o-0';
12−
13− const classes = props.disabled ? 'br-gray-30 bg-gray-10' : onOff;
14−
15− return (
16− <div
17− className={`flex items-center ${props.className}`}
18− style={{ cursor: 'pointer', ...props.style }}
19− onClick={props.onToggle}>
20− <ProtoButton
21− // {...getDomProps(props)}
22− {...props}
23− className={`s-7 p-0 o-blue mr-4 bs-solid bw-2 ${classes}`}>
24− <svg
25− className={checkmarkState}
26− width="24"
27− height="24"
28− viewBox="0 0 24 24"
29− fill="none"
30− xmlns="http://www.w3.org/2000/svg">
31− <path
32− d="M2 3.55661V0H0V5.55661H12.4182V3.55661H2Z"
33− transform="translate(6, 13) rotate(-45)"
34− fill="white"
35− />
36− </svg>
37− </ProtoButton>
38−
39− <div>{props.label}</div>
40− {props.children}
41− </div>
42− );
43−};
44−
45−CheckboxButton.propTypes = {
46− state: PropTypes.bool,
47− className: PropTypes.string,
48−};
49−
50−CheckboxButton.defaultProps = {
51− state: false,
52− className: '',
53−};
54−
55−export default CheckboxButton;
src/components/old/Code.jsdeleted−34
@@ -1,34 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const Code = ({ className, children, style, measure }) => {
5− // const s = getStyles(styleManifest, measure)
6−
7− return (
8− <pre className={`flex ${className}`} style={style}>
9− {children}
10− </pre>
11− );
12−};
13−
14−// const getStyles = (sm, m) => sm[m];
15−//
16−// const styleManifest = {
17−// sm: 'measure-sm',
18−// md: 'measure-md',
19−// lg: 'measure-lg',
20−// }
21−
22−Code.propTypes = {
23− className: PropTypes.string,
24− children: PropTypes.node,
25− style: PropTypes.object,
26−};
27−
28−Code.defaultProps = {
29− className: '',
30− style: {},
31− measure: 'md',
32−};
33−
34−export default Code;
src/components/old/Col.jsdeleted−23
@@ -1,23 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const Col = ({ className, children, style }) => {
5− return (
6− <div className={`col- ${className}`} style={style}>
7− {children}
8− </div>
9− );
10−};
11−
12−Col.propTypes = {
13− className: PropTypes.string,
14− children: PropTypes.node,
15− style: PropTypes.object,
16−};
17−
18−Col.defaultProps = {
19− className: '',
20− style: {},
21−};
22−
23−export default Col;
src/components/old/DropdownDivider.jsdeleted−11
@@ -1,11 +0,0 @@
1−import React from 'react';
2−
3−const DropdownDivider = props => {
4− return (
5− <div className={`br-gray-50 bs-solid bw-0-2-0-2 ${props.className}`}>
6− <div className={`block bs-solid bw-2-0-0-0 br-gray-30 mv-2`} />
7− </div>
8− );
9−};
10−
11−export default DropdownDivider;
src/components/old/DropdownItem.jsdeleted−35
@@ -1,35 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const DropdownItem = props => {
5− const _disabled = props.disabled
6− ? 'gray-50'
7− : 'h-br-blue br-gray-50 h-bg-blue h-white';
8−
9− return (
10− <button
11− disabled={props.disabled}
12− style={props.style}
13− className={`h-10 m-0 p-0 ph-2 bg-white flex align-center items-start bs-solid brw-2 blw-2 btw-0 bbw-0 sans ${_disabled} ${props.className}`}
14− onClick={props.onClick}>
15− {props.children}
16− </button>
17− );
18−};
19−
20−DropdownItem.propTypes = {
21− disabled: PropTypes.bool,
22− onClick: PropTypes.func,
23− className: PropTypes.string,
24− children: PropTypes.node,
25− style: PropTypes.object,
26−};
27−
28−DropdownItem.defaultProps = {
29− className: '',
30− onClick: () => {},
31− disabled: false,
32− style: {},
33−};
34−
35−export default DropdownItem;
src/components/old/FlexCol.jsdeleted−23
@@ -1,23 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const FlexCol = ({ className, children, style }) => {
5− return (
6− <div className={`flex flex-column flex-1 ${className}`} style={style}>
7− {children}
8− </div>
9− );
10−};
11−
12−FlexCol.propTypes = {
13− className: PropTypes.string,
14− children: PropTypes.node,
15− style: PropTypes.object,
16−};
17−
18−FlexCol.defaultProps = {
19− className: '',
20− style: {},
21−};
22−
23−export default FlexCol;
src/components/old/FlexRow.jsdeleted−17
@@ -1,17 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const FlexRow = ({ className, children }) => {
5− return <div className={`flex ${className}`}>{children}</div>;
6−};
7−
8−FlexRow.propTypes = {
9− className: PropTypes.string,
10− children: PropTypes.node,
11−};
12−
13−FlexRow.defaultProps = {
14− className: '',
15−};
16−
17−export default FlexRow;
src/components/old/Form.jsdeleted−23
@@ -1,23 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const Form = ({ className, children, style }) => {
5− return (
6− <form className={`${className}`} style={style}>
7− {children}
8− </form>
9− );
10−};
11−
12−Form.propTypes = {
13− className: PropTypes.string,
14− children: PropTypes.node,
15− style: PropTypes.object,
16−};
17−
18−Form.defaultProps = {
19− className: '',
20− style: {},
21−};
22−
23−export default Form;
src/components/old/H1.jsdeleted−25
@@ -1,25 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const H1 = ({ className, children, style }) => {
5− return (
6− <h1
7− className={`mt-12 pt-6 mb-4 text-700 measure-md ${className}`}
8− style={style}>
9− {children}
10− </h1>
11− );
12−};
13−
14−H1.propTypes = {
15− className: PropTypes.string,
16− children: PropTypes.node,
17− style: PropTypes.object,
18−};
19−
20−H1.defaultProps = {
21− className: '',
22− style: {},
23−};
24−
25−export default H1;
src/components/old/H2.jsdeleted−23
@@ -1,23 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const H2 = ({ className, children, style }) => {
5− return (
6− <h2 className={`mt-8 pt-3 mb-4 measure-md ${className}`} style={style}>
7− {children}
8− </h2>
9− );
10−};
11−
12−H2.propTypes = {
13− className: PropTypes.string,
14− children: PropTypes.node,
15− style: PropTypes.object,
16−};
17−
18−H2.defaultProps = {
19− className: '',
20− style: {},
21−};
22−
23−export default H2;
src/components/old/H3.jsdeleted−23
@@ -1,23 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const H3 = ({ className, children, style }) => {
5− return (
6− <h3 className={`mt-8 pt-3 mb-4 measure-md ${className}`} style={style}>
7− {children}
8− </h3>
9− );
10−};
11−
12−H3.propTypes = {
13− className: PropTypes.string,
14− children: PropTypes.node,
15− style: PropTypes.object,
16−};
17−
18−H3.defaultProps = {
19− className: '',
20− style: {},
21−};
22−
23−export default H3;
src/components/old/H4.jsdeleted−23
@@ -1,23 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const H4 = ({ className, children, style }) => {
5− return (
6− <h4 className={`mt-2 pt-1 mb-2 measure-md ${className}`} style={style}>
7− {children}
8− </h4>
9− );
10−};
11−
12−H4.propTypes = {
13− className: PropTypes.string,
14− children: PropTypes.node,
15− style: PropTypes.object,
16−};
17−
18−H4.defaultProps = {
19− className: '',
20− style: {},
21−};
22−
23−export default H4;
src/components/old/HorizontalSelector.jsdeleted−51
@@ -1,51 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−class HorizontalSelector extends React.Component {
5− constructor(props) {
6− super(props);
7−
8− this.state = {
9− option: this.props.options[0].value,
10− };
11−
12− this.selectOption = this.selectOption.bind(this);
13− }
14−
15− selectOption(opt) {
16− this.props.onChange(opt);
17− this.setState({ option: opt });
18− }
19−
20− getOptionElems() {
21− return this.props.options.map(opt => {
22− let active = opt.value === this.state.option ? 'btn-primary active' : '';
23− return (
24− <button
25− key={opt.value.toString()}
26− className={`btn ${active} h-10 ph-4 flex sans ${this.props.className}`}
27− onClick={() => this.selectOption(opt.value)}>
28− {opt.title}
29− </button>
30− );
31− });
32− }
33−
34− render() {
35− const optionElems = this.getOptionElems();
36−
37− return <div className="btn-group">{optionElems}</div>;
38− }
39−}
40−
41−HorizontalSelector.propTypes = {
42− className: PropTypes.string,
43− options: PropTypes.array,
44−};
45−
46−HorizontalSelector.defaultProps = {
47− className: '',
48− options: [],
49−};
50−
51−export default HorizontalSelector;
src/components/old/InnerLabel.jsdeleted−25
@@ -1,25 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const InnerLabel = ({ children, className, style }) => {
5− return (
6− <div
7− className={`abs tl-0 pt-2 pl-4 fs-3 text-500 sans ${className}`}
8− style={style}>
9− {children}
10− </div>
11− );
12−};
13−
14−InnerLabel.propTypes = {
15− className: PropTypes.string,
16− children: PropTypes.node,
17− style: PropTypes.object,
18−};
19−
20−InnerLabel.defaultProps = {
21− className: '',
22− style: {},
23−};
24−
25−export default InnerLabel;
src/components/old/InnerLabelDropdown.jsdeleted−115
@@ -1,115 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−import { DropdownItem, DropdownDivider } from './Base';
5−
6−class InnerLabelDropdown extends React.Component {
7− constructor(props) {
8− super(props);
9−
10− this.state = {
11− isOpen: false,
12− };
13−
14− this.toggle = this.toggle.bind(this);
15− this.close = this.close.bind(this);
16− }
17−
18− toggle() {
19− this.setState({
20− isOpen: !this.state.isOpen,
21− });
22− }
23−
24− close() {
25− this.setState({
26− isOpen: false,
27− });
28− }
29−
30− selectOption(opt) {
31− this.close();
32− this.props.handleUpdate(opt);
33− }
34−
35− getOptionElems() {
36− return this.props.options.map((opt, i) => {
37− if (opt.type === 'divider') {
38− return <DropdownDivider key={`divider-${i}`} />;
39− } else {
40− return (
41− <DropdownItem
42− key={opt.title}
43− onClick={() => this.selectOption(opt.value)}>
44− {opt.title}
45− </DropdownItem>
46− );
47− }
48− });
49− }
50−
51− render() {
52− const { props, state } = this;
53−
54− const optionElems = this.getOptionElems();
55−
56− const menuVisibility = state.isOpen === true ? 'visible' : 'hidden';
57−
58− const selectedClasses = state.isOpen === true ? 'br-blue' : 'br-gray-50';
59−
60− const fullWidthClass = props.fullWidth ? 'full-width' : '';
61−
62− return (
63− <div className={`rel table ${fullWidthClass} ${props.className}`}>
64− <div
65− className={`fix full o-0 ${menuVisibility}`}
66− onClick={this.close}
67− />
68−
69− <button
70− className={`h-10 mp-0 bg-white outline-blue sans ${fullWidthClass}`}
71− onClick={this.toggle}
72− disabled={props.disabled}>
73− <div className={'flex'}>
74− <div
75− className={`ph-4 flex align-center b-2 br-0 b-solid h-10 ${selectedClasses} ${fullWidthClass}`}>
76− <div className={'text-400 mr-2'}>{props.title}</div>
77− <div className={'text-600'}>{props.currentSelectionTitle}</div>
78− </div>
79− <div className={'white bg-blue s-10 flex-center-all text-sm'}>
80− {'▼'}
81− </div>
82− </div>
83− </button>
84−
85− <div
86− className={`abs flex-column bg-white t-12 l-0 w-100 z-1 ${menuVisibility}`}>
87− <div className={'pv-1 b-solid b-gray-50 b-2 bb-0'} />
88−
89− {optionElems}
90−
91− <div className={'pv-1 b-solid b-gray-50 b-2 bt-0'} />
92− </div>
93− </div>
94− );
95− }
96−}
97−
98−InnerLabelDropdown.propTypes = {
99− disabled: PropTypes.bool,
100− className: PropTypes.string,
101− title: PropTypes.string,
102− style: PropTypes.object,
103− currentSelectionTitle: PropTypes.string,
104− children: PropTypes.node,
105−};
106−
107−InnerLabelDropdown.defaultProps = {
108− disabled: false,
109− className: '',
110− title: '',
111− style: {},
112− currentSelectionTitle: '',
113−};
114−
115−export default InnerLabelDropdown;
src/components/old/Input.jsdeleted−67
@@ -1,67 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−import ProtoInput from './ProtoInput';
4−
5−const Input = props => {
6− const _disabled = props.disabled === true ? 'br-gray-30' : '';
7−
8− // This enables all children of this component to share the state of this
9− // component.
10− const childrenWithProps = React.Children.map(props.children, child => {
11− const propsToPass = {
12− displayPass: props.displayPass,
13− displayFailure: props.displayFailure,
14− focussed: props.focussed,
15− beenFocussed: props.beenFocussed,
16− error: props.error,
17− };
18− return React.cloneElement(child, propsToPass);
19− });
20−
21− const className = props.advanced
22− ? `${props.valClassname} ${props.className}`
23− : `br-gray-50 f-br-blue outline-blue ${props.className}`;
24−
25− return (
26− <div className={'relative'}>
27− <ProtoInput
28− {...props}
29− // prop-focussed={props.focussed.toString()}
30− className={`p-3 b-2 b-solid flex ${_disabled} ${className}`}
31− onChange={e => props.onChange(e.target.value)}
32− />
33− {props.displayFailure === true && props.advanced === true ? (
34− <div className={'yellow text-600 h-6 mt-1 fs-3'}>{props.error}</div>
35− ) : (
36− <div />
37− )}
38− {childrenWithProps}
39− </div>
40− );
41−};
42−
43−Input.propTypes = {
44− focussed: PropTypes.bool,
45− beenFocussed: PropTypes.bool,
46− hasSubmitted: PropTypes.bool,
47− displayPass: PropTypes.bool,
48− displayFailure: PropTypes.bool,
49− advanced: PropTypes.bool,
50− error: PropTypes.string,
51− valClassname: PropTypes.string,
52− size: PropTypes.oneOf(['s', 'm', 'l', 'xl']),
53−};
54−
55−Input.defaultProps = {
56− focussed: false,
57− beenFocussed: false,
58− hasSubmitted: false,
59− displayPass: false,
60− displayFailure: false,
61− advanced: false,
62− error: '',
63− size: 'm',
64− format: 'normal',
65−};
66−
67−export default Input;
src/components/old/InputCaption.jsdeleted−25
@@ -1,25 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const InputCaption = ({ children, className, style }) => {
5− return (
6− <div
7− className={`mt-8 mb-1 text-35 text-400 sans ${className}`}
8− style={style}>
9− {children}
10− </div>
11− );
12−};
13−
14−InputCaption.propTypes = {
15− className: PropTypes.string,
16− children: PropTypes.node,
17− style: PropTypes.object,
18−};
19−
20−InputCaption.defaultProps = {
21− className: '',
22− style: {},
23−};
24−
25−export default InputCaption;
src/components/old/Label.jsdeleted−23
@@ -1,23 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const Label = ({ children, className }) => {
5− return (
6− <div className={`mb-1 mt-8 fs-4 text-600 sans ${className}`}>
7− {children}
8− </div>
9− );
10−};
11−
12−Label.propTypes = {
13− className: PropTypes.string,
14− children: PropTypes.node,
15− style: PropTypes.object,
16−};
17−
18−Label.defaultProps = {
19− className: '',
20− style: {},
21−};
22−
23−export default Label;
src/components/old/P.jsdeleted−34
@@ -1,34 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const P = ({ className, children, style, measure }) => {
5− const s = getStyles(styleManifest, measure);
6−
7− return (
8− <p className={`mb-7 ${s} ${className}`} style={style}>
9− {children}
10− </p>
11− );
12−};
13−
14−const getStyles = (sm, m) => sm[m];
15−
16−const styleManifest = {
17− sm: 'measure-sm',
18− md: 'measure-md',
19− lg: 'measure-lg',
20−};
21−
22−P.propTypes = {
23− className: PropTypes.string,
24− children: PropTypes.node,
25− style: PropTypes.object,
26−};
27−
28−P.defaultProps = {
29− className: '',
30− style: {},
31− measure: 'md',
32−};
33−
34−export default P;
src/components/old/PointList.jsdeleted−32
@@ -1,32 +0,0 @@
1−import React from 'react';
2−import { chunk } from 'lodash';
3−
4−import { usePointCursor } from '../../store/pointCursor';
5−
6−import { Row } from './Base';
7−import RenderedPoint from './RenderedPoint';
8−
9−const PointList = function(props) {
10− const { setPointCursor } = usePointCursor();
11− const { routeHandler, points, loading } = props;
12− const chunks = chunk(points, 3);
13−
14− return points.length === 0 ? (
15− <p>{loading ? 'Loading...' : 'No points to display'}</p>
16− ) : (
17− chunks.map((chunk, idx) => (
18− <Row key={`render-row-${idx}`}>
19− {chunk.map(point => (
20− <RenderedPoint
21− key={point}
22− setPointCursor={setPointCursor}
23− routeHandler={routeHandler}
24− point={point}
25− />
26− ))}
27− </Row>
28− ))
29− );
30−};
31−
32−export default PointList;
src/components/old/ProtoAnchor.jsdeleted−27
@@ -1,27 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const ProtoAnchor = props => {
5− return <a {...props}>{props.children}</a>;
6−};
7−
8−ProtoAnchor.propTypes = {
9− className: PropTypes.string,
10− children: PropTypes.node,
11− autoFocus: PropTypes.bool,
12− style: PropTypes.object,
13− href: PropTypes.string,
14− rel: PropTypes.string,
15− target: PropTypes.oneOf(['_self', '_blank', '_parent', '_top']),
16−};
17−
18−ProtoAnchor.defaultProps = {
19− className: '',
20− autoFocus: false,
21− style: {},
22− href: '',
23− rel: '',
24− target: '_self',
25−};
26−
27−export default ProtoAnchor;
src/components/old/ProtoButton.jsdeleted−39
@@ -1,39 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−import { getDomProps } from '../../lib/base';
4−
5−const ProtoButton = props => {
6− return (
7− <button
8− {...getDomProps(props)}
9− className={`${props.className} sans`}
10− type={props.type}
11− style={props.style}
12− onClick={props.onClick}
13− disabled={props.disabled}
14− autoFocus={props.autoFocus}>
15− {props.children}
16− </button>
17− );
18−};
19−
20−ProtoButton.propTypes = {
21− disabled: PropTypes.bool,
22− onClick: PropTypes.func,
23− className: PropTypes.string,
24− children: PropTypes.node,
25− autofocus: PropTypes.bool,
26− style: PropTypes.object,
27− type: PropTypes.oneOf(['button', 'submit', 'reset']),
28−};
29−
30−ProtoButton.defaultProps = {
31− className: '',
32− autoFocus: false,
33− onClick: () => {},
34− disabled: false,
35− style: {},
36− type: 'button',
37−};
38−
39−export default ProtoButton;
src/components/old/ProtoInput.jsdeleted−66
@@ -1,66 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−import { getDomProps } from '../../lib/base';
5−
6−const ProtoInput = props => {
7− return (
8− <input
9− // getDomProps gets any prop prepended with 'prop-'. Useful here because
10− // one cannot simply pass props like {...props} because the input elem
11− // cannot accept children nodes, which are included in the props arg. It
12− // is doubly useful because it lets the developer control which props are
13− // added to the real DOM.
14− {...getDomProps(props)}
15− className={props.className}
16− onChange={e => props.onChange(e)}
17− onKeyPress={e => props.onKeyPress(e)}
18− onFocus={e => props.onFocus(e)}
19− onBlur={e => props.onBlur(e)}
20− placeholder={props.placeholder}
21− disabled={props.disabled}
22− type={props.type}
23− name={props.name}
24− style={props.style}
25− value={props.value}
26− autoFocus={props.autoFocus}
27− readOnly={props.readOnly}
28− maxLength={props.maxLength}
29− autoComplete={props.autoComplete}
30− />
31− );
32−};
33−
34−ProtoInput.propTypes = {
35− disabled: PropTypes.bool,
36− onChange: PropTypes.func,
37− onBlur: PropTypes.func,
38− onFocus: PropTypes.func,
39− onKeyPress: PropTypes.func,
40− className: PropTypes.string,
41− style: PropTypes.object,
42− children: PropTypes.node,
43− autoFocus: PropTypes.bool,
44− readOnly: PropTypes.bool,
45− name: PropTypes.string,
46− value: PropTypes.string,
47− autoComplete: PropTypes.string,
48− type: PropTypes.string,
49−};
50−
51−ProtoInput.defaultProps = {
52− disabled: false,
53− autoFocus: false,
54− onChange: () => {},
55− onBlur: () => {},
56− onFocus: () => {},
57− onKeyPress: () => {},
58− style: {},
59− className: '',
60− value: '',
61− name: '',
62− autoComplete: 'off',
63− type: 'input',
64−};
65−
66−export default ProtoInput;
src/components/old/ProtoTextarea.jsdeleted−62
@@ -1,62 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−import { getDomProps } from '../../lib/base';
5−
6−const ProtoTextarea = props => {
7− return (
8− <textarea
9− // getDomProps gets any prop prepended with 'prop-'. Useful here because
10− // one cannot simply pass props like {...props} because the input elem
11− // cannot accept children nodes, which are included in the props arg. It
12− // is doubly useful because it lets the developer control which props are
13− // added to the real DOM.
14− {...getDomProps(props)}
15− className={props.className}
16− onChange={e => props.onChange(e)}
17− onKeyPress={e => props.onKeyPress(e)}
18− onFocus={e => props.onFocus(e)}
19− onBlur={e => props.onBlur(e)}
20− placeholder={props.placeholder}
21− name={props.name}
22− style={props.style}
23− value={props.value}
24− autoFocus={props.autoFocus}
25− readOnly={props.readOnly}
26− maxLength={props.maxLength}
27− autoComplete={props.autoComplete}
28− />
29− );
30−};
31−
32−ProtoTextarea.propTypes = {
33− disabled: PropTypes.bool,
34− onChange: PropTypes.func,
35− onBlur: PropTypes.func,
36− onFocus: PropTypes.func,
37− onKeyPress: PropTypes.func,
38− className: PropTypes.string,
39− style: PropTypes.object,
40− children: PropTypes.node,
41− autoFocus: PropTypes.bool,
42− readOnly: PropTypes.bool,
43− name: PropTypes.string,
44− value: PropTypes.string,
45− autoComplete: PropTypes.string,
46−};
47−
48−ProtoTextarea.defaultProps = {
49− disabled: false,
50− autoFocus: false,
51− onChange: () => {},
52− onBlur: () => {},
53− onFocus: () => {},
54− onKeyPress: () => {},
55− style: {},
56− className: '',
57− value: '',
58− name: '',
59− autoComplete: 'off',
60−};
61−
62−export default ProtoTextarea;
src/components/old/RenderedPoint.jsdeleted−57
@@ -1,57 +0,0 @@
1−import React from 'react';
2−import { Just } from 'folktale/maybe';
3−import { Col } from './Base';
4−import { Button } from './Base';
5−import { pour } from 'sigil-js';
6−import * as ob from 'urbit-ob';
7−
8−import { ROUTE_NAMES } from '../../lib/routeNames';
9−import ReactSVGComponents from '../ReactSVGComponents';
10−
11−const RenderedPoint = props => {
12− const { setPointCursor, routeHandler, point } = props;
13−
14− const name = ob.patp(point);
15− const sigil = pour({
16− patp: name,
17− renderer: ReactSVGComponents,
18− size: 128,
19− });
20−
21− return (
22− <Col className={'col-md-3 mb-8'} key={`rendered-${point}`}>
23− <div
24− key={`rendered-sigil-${point}`}
25− className="clickable"
26− onClick={() => {
27− setPointCursor(Just(point));
28− routeHandler(ROUTE_NAMES.POINT);
29− }}>
30− {sigil}
31− </div>
32− <div
33− key={`rendered-name-${point}`}
34− className="clickable"
35− onClick={() => {
36− setPointCursor(Just(point));
37− routeHandler(ROUTE_NAMES.POINT);
38− }}>
39− <code>{name}</code>
40− </div>
41− <div key={`rendered-deets-${point}`}>
42− <Button
43− key={`rendered-deets-button-${point}`}
44− prop-type={'link'}
45− prop-size={'sm'}
46− onClick={() => {
47− setPointCursor(Just(point));
48− routeHandler(ROUTE_NAMES.POINT);
49− }}>
50− {'Details →'}
51− </Button>
52− </div>
53− </Col>
54− );
55−};
56−
57−export default RenderedPoint;
src/components/old/Row.jsdeleted−23
@@ -1,23 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const Row = ({ className, children, style }) => {
5− return (
6− <div className={`row ${className}`} style={style}>
7− {children}
8− </div>
9− );
10−};
11−
12−Row.propTypes = {
13− className: PropTypes.string,
14− children: PropTypes.node,
15− style: PropTypes.object,
16−};
17−
18−Row.defaultProps = {
19− className: '',
20− style: {},
21−};
22−
23−export default Row;
src/components/old/RowCol.jsdeleted−25
@@ -1,25 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−import { Row, Col } from './Base';
5−
6−const RowCol = ({ className, children, style }) => {
7− return (
8− <Row className={`${className}`} style={style}>
9− <Col>{children}</Col>
10− </Row>
11− );
12−};
13−
14−RowCol.propTypes = {
15− className: PropTypes.string,
16− children: PropTypes.node,
17− style: PropTypes.object,
18−};
19−
20−RowCol.defaultProps = {
21− className: '',
22− style: {},
23−};
24−
25−export default RowCol;
src/components/old/ShowBlockie.jsdeleted−70
@@ -1,70 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−import makeBlockie from 'ethereum-blockies-base64';
4−import Button from './Button';
5−import { invert } from '../../lib/state';
6−
7−const isValidAddress = address => /^0x[0-9a-fA-F]{40}$/.test(address);
8−
9−class ShowBlockie extends React.Component {
10− constructor(props) {
11− super(props);
12−
13− this.state = {
14− open: false,
15− };
16−
17− this.toggle = this.toggle.bind(this);
18− // this.close = this.close.bind(this)
19− }
20−
21− toggle = () => this.setState(invert('open', this.state));
22−
23− render() {
24− const { props, state } = this;
25−
26− const display = state.open ? '' : 'super-hidden';
27−
28− const isValid = isValidAddress(props.address);
29−
30− return (
31− <div className={`flex flex-column items-start ${props.className}`}>
32− <Button
33− onClick={this.toggle}
34− disabled={!isValid}
35− prop-type="link"
36− prop-size="sm">
37− {state.open ? 'Hide Blockie' : 'Display Blockie'}
38− </Button>
39− {!isValid ? (
40− <div />
41− ) : (
42− <img
43− className={`${display} mt-2`}
44− alt={props.address}
45− src={makeBlockie(props.address)}
46− style={{
47− width: props.size,
48− height: props.size,
49− }}
50− />
51− )}
52− </div>
53− );
54− }
55−}
56−
57−ShowBlockie.propTypes = {
58− className: PropTypes.string,
59− children: PropTypes.node,
60− style: PropTypes.object,
61−};
62−
63−ShowBlockie.defaultProps = {
64− className: '',
65− style: {},
66− size: 64,
67− address: '',
68−};
69−
70−export default ShowBlockie;
src/components/old/Spacing.jsdeleted−25
@@ -1,25 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−import { isUndefined } from 'lodash';
4−
5−const Spacing = ({ className, children, h, w }) => {
6− const h_cn = isUndefined(h) ? '' : `mt-${h}`;
7− const w_cn = isUndefined(w) ? '' : `ml-${w}`;
8−
9− return <div className={`${h_cn} ${w_cn} ${className}`}>{children}</div>;
10−};
11−
12−Spacing.propTypes = {
13− className: PropTypes.string,
14− children: PropTypes.node,
15− h: PropTypes.number,
16− w: PropTypes.number,
17−};
18−
19−Spacing.defaultProps = {
20− className: '',
21− h: 0,
22− w: 0,
23−};
24−
25−export default Spacing;
src/components/old/Textarea.jsdeleted−67
@@ -1,67 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−import ProtoTextarea from './ProtoTextarea';
4−
5−const Textarea = props => {
6− const _disabled = props.disabled === true ? 'br-gray-30' : '';
7−
8− // This enables all children of this component to share the state of this
9− // component.
10− const childrenWithProps = React.Children.map(props.children, child => {
11− const propsToPass = {
12− displayPass: props.displayPass,
13− displayFailure: props.displayFailure,
14− focussed: props.focussed,
15− beenFocussed: props.beenFocussed,
16− error: props.error,
17− };
18− return React.cloneElement(child, propsToPass);
19− });
20−
21− const className = props.advanced
22− ? `${props.valClassname} ${props.className}`
23− : `br-gray-50 f-br-blue outline-blue ${props.className}`;
24−
25− return (
26− <div className={'relative'}>
27− <ProtoTextarea
28− {...props}
29− // prop-focussed={props.focussed.toString()}
30− className={`p-3 b-2 b-solid flex ${_disabled} ${className}`}
31− onChange={e => props.onChange(e.target.value)}
32− />
33− {props.displayFailure === true && props.advanced === true ? (
34− <div className={'yellow text-600 h-6 mt-1 fs-3 abs'}>{props.error}</div>
35− ) : (
36− <div />
37− )}
38− {childrenWithProps}
39− </div>
40− );
41−};
42−
43−Textarea.propTypes = {
44− focussed: PropTypes.bool,
45− beenFocussed: PropTypes.bool,
46− hasSubmitted: PropTypes.bool,
47− displayPass: PropTypes.bool,
48− displayFailure: PropTypes.bool,
49− advanced: PropTypes.bool,
50− error: PropTypes.string,
51− valClassname: PropTypes.string,
52− size: PropTypes.oneOf(['s', 'm', 'l', 'xl']),
53−};
54−
55−Textarea.defaultProps = {
56− focussed: false,
57− beenFocussed: false,
58− hasSubmitted: false,
59− displayPass: false,
60− displayFailure: false,
61− advanced: false,
62− error: '',
63− size: 'm',
64− format: 'normal',
65−};
66−
67−export default Textarea;
src/components/old/UploadButton.jsdeleted−31
@@ -1,31 +0,0 @@
1−import React from 'react';
2−
3−class UploadButton extends React.Component {
4− constructor(props) {
5− super(props);
6− this.onChange = this.onChange.bind(this);
7− }
8−
9− onChange() {
10− this.props.onChange(this.input);
11− }
12−
13− render() {
14− return (
15− <label className={this.props.className}>
16− <input
17− className={'hidden h-0 w-0 abs'}
18− ref={ref => {
19− this.input = ref;
20− }}
21− onChange={this.onChange}
22− disabled={this.props.disabled}
23− type="file"
24− />
25− {this.props.children}
26− </label>
27− );
28− }
29−}
30−
31−export default UploadButton;
src/components/old/ValidatedBlockie.jsdeleted−64
@@ -1,64 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−import makeBlockie from 'ethereum-blockies-base64';
4−
5−const ValidatedBlockie = ({
6− className,
7− children,
8− style,
9− color,
10− address,
11− size,
12− validator,
13− displayPass,
14− displayFailure,
15− focussed,
16− beenFocussed,
17−}) => {
18− const colorStyle = styleSelector(displayPass, displayFailure, focussed);
19−
20− return (
21− <div className={`${className}`} style={style}>
22− {displayPass ? (
23− <img
24− alt={address}
25− src={makeBlockie(address)}
26− style={{
27− width: size,
28− height: size,
29− }}
30− />
31− ) : (
32− <div
33− className={''}
34− style={{
35− backgroundColor: colorStyle[1],
36− width: size,
37− height: size,
38− }}
39− />
40− )}
41− {children}
42− </div>
43− );
44−};
45−
46−const styleSelector = (pass, fail, focus) => {
47− if (fail === true) return ['#FFFFFF', '#F8C134'];
48− if (pass === true) return ['#FFFFFF', '#2AA779'];
49− if (focus === true) return ['#FFFFFF', '#4330FC'];
50− return ['#FFFFFF', '#7F7F7F'];
51−};
52−
53−ValidatedBlockie.propTypes = {
54− className: PropTypes.string,
55− children: PropTypes.node,
56− style: PropTypes.object,
57−};
58−
59−ValidatedBlockie.defaultProps = {
60− className: '',
61− style: {},
62−};
63−
64−export default ValidatedBlockie;
src/components/old/ValidatedSigil.jsdeleted−75
@@ -1,75 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−import { pour } from 'sigil-js';
5−import * as ob from 'urbit-ob';
6−import ReactSVGComponents from '../ReactSVGComponents';
7−
8−const isValidPatp = patp => {
9− let isValid = false;
10− try {
11− isValid = ob.isValidPatp(patp);
12− } catch (err) {
13− return isValid;
14− }
15− return isValid;
16−};
17−
18−const ValidatedSigil = ({
19− className,
20− children,
21− style,
22− color,
23− patp,
24− size,
25− margin,
26− displayPass,
27− displayFailure,
28− focussed,
29− beenFocussed,
30−}) => {
31− const colorStyle = styleSelector(displayPass, displayFailure, focussed);
32−
33− return (
34− <div className={`${className}`} style={style}>
35− {isValidPatp(patp) ? (
36− pour({
37− patp: patp,
38− renderer: ReactSVGComponents,
39− size: size,
40− colorway: colorStyle,
41− margin: margin,
42− })
43− ) : (
44− <div
45− className={'bg-transparent'}
46− style={{
47− width: size,
48− height: size,
49− }}
50− />
51− )}
52− {children}
53− </div>
54− );
55−};
56−
57−const styleSelector = (pass, fail, focus) => {
58− if (fail === true) return ['#FFFFFF', '#F8C134'];
59− if (pass === true) return ['#FFFFFF', '#2AA779'];
60− if (focus === true) return ['#FFFFFF', '#4330FC'];
61− return ['#FFFFFF', '#7F7F7F'];
62−};
63−
64−ValidatedSigil.propTypes = {
65− className: PropTypes.string,
66− children: PropTypes.node,
67− style: PropTypes.object,
68−};
69−
70−ValidatedSigil.defaultProps = {
71− className: '',
72− style: {},
73−};
74−
75−export default ValidatedSigil;
src/components/old/Warning.jsdeleted−23
@@ -1,23 +0,0 @@
1−import React from 'react';
2−import PropTypes from 'prop-types';
3−
4−const Warning = ({ className, children, style, measure }) => {
5− return (
6− <div className={`mb-7 p-4 bg-yellow break-word ${className}`} style={style}>
7− {children}
8− </div>
9− );
10−};
11−
12−Warning.propTypes = {
13− className: PropTypes.string,
14− children: PropTypes.node,
15− style: PropTypes.object,
16−};
17−
18−Warning.defaultProps = {
19− className: '',
20− style: {},
21−};
22−
23−export default Warning;
src/components/old/advancedInput.jsdeleted−147
@@ -1,147 +0,0 @@
1−import React, { Component } from 'react';
2−import PropTypes from 'prop-types';
3−
4−import { compose, defaultTo } from '../../lib/lib';
5−
6−// =============================================================================
7−// Utils
8−
9−const initMessage = data => ({
10− data: data,
11− pass: true,
12− error: '',
13−});
14−
15−// Validation display triggers
16−const displayTriggers = {
17− eagerSuccess: r => r.pass,
18− eagerFailure: r => !r.pass,
19− tactfulSuccess: r => r.pass && r.beenFocussed,
20− tactfulFailure: r => !r.pass && r.beenFocussed && !r.focussed,
21−};
22−
23−// =============================================================================
24−// AdvancedInput
25−
26−const advancedInput = ({ WrappedComponent, validators, transformers }) => {
27− // set argument defaults
28− validators = defaultTo(validators, []);
29− transformers = defaultTo(transformers, []);
30−
31− class AdvancedInputHOC extends Component {
32− constructor(props) {
33− super(props);
34− this.state = {
35− focussed: false,
36− beenFocussed: false,
37− };
38− this.onFocus = this.onFocus.bind(this);
39− this.onBlur = this.onBlur.bind(this);
40− this.onChange = this.onChange.bind(this);
41− }
42−
43− onFocus = () => this.setState({ focussed: true });
44−
45− onBlur = () => this.setState({ focussed: false, beenFocussed: true });
46−
47− onChange = value => {
48− const { props } = this;
49−
50− // =======================================================================
51− // 0. RUN VALUE TRANSFORMERS
52−
53− // This applies functions to the input value and updates state with the
54− // new value. This is useful for ship/point names which technically
55− // should always have a sig prepending them, but users might not know/care
56− // about such a technicality. ValueTransformers are executed from right to
57− // left.
58− const newValue = compose(...transformers)(value);
59−
60− props.onChange(newValue);
61− };
62−
63− render() {
64− const { state, props } = this;
65−
66− // =======================================================================
67− // RUN VALIDATORS AND DETERMINE STYLES
68−
69− // Run validation chain on the transformed value. Validators are executed
70− // from right to left and exit on the first validation failure.
71−
72− const report = compose(
73− ...validators,
74− initMessage
75− )(props.value);
76−
77− // Makes a uniform data structure to pass to display triggers. This
78− // removes the need to rely on argument order for these functions.
79− const stateReport = {
80− pass: report.pass,
81− beenFocussed: state.beenFocussed,
82− focussed: state.focussed,
83− submitted: props.submitted,
84− };
85−
86− // Determine if the passing validation style or message should be shown
87− const displayPass = displayTriggers.eagerSuccess(stateReport);
88−
89− // Determine if the failing validation style or message should be shown
90− const displayFailure = displayTriggers.tactfulFailure(stateReport);
91−
92− // Generate class strings for validation state. VCN stands for validation
93− // class names
94− const valClassname = styleSelector(displayPass, displayFailure);
95−
96− return (
97− <WrappedComponent
98− {...props}
99− // Events
100− onFocus={this.onFocus}
101− onBlur={this.onBlur}
102− onChange={this.onChange}
103− // stateReport
104− focussed={state.focussed}
105− beenFocussed={state.beenFocussed}
106− displayPass={displayPass}
107− displayFailure={displayFailure}
108− // 'error' prop refers to an error message string, not the presence
109− // of an error.
110− error={report.error}
111− didPass={report.pass}
112− value={props.value}
113− className={props.className}
114− disabled={props.disabled}
115− valClassname={valClassname}
116− advanced={true}
117− />
118− );
119− }
120− }
121−
122− AdvancedInputHOC.propTypes = {
123− className: PropTypes.string,
124− style: PropTypes.object,
125− value: PropTypes.string,
126− submitted: PropTypes.bool,
127− };
128−
129− AdvancedInputHOC.defaultProps = {
130− className: '',
131− style: {},
132− value: '',
133− submitted: false,
134− };
135−
136− return AdvancedInputHOC;
137− // END advancedInput()
138−};
139−
140−const styleSelector = (pass, fail) => {
141− if (fail === true)
142− return 'br-yellow outline-yellow f-br-yellow bg-yellow-light';
143− if (pass === true) return 'br-green outline-green f-br-green';
144− return 'br-gray-50 f-br-blue outline-blue';
145−};
146−
147−export default advancedInput;
src/lib/constants.js+1−1
@@ -23,7 +23,7 @@ const GAS_LIMITS = {
2323 SPAWN: 250000,
2424 TRANSFER: 550000,
2525 CONFIGURE_KEYS: 100000,
26− SET_PROXY: 120000,
26+ SET_PROXY: 130000,
2727 //
2828 ESCAPE: 115000, //NOTE low sample size
2929 ADOPT: 100000, //NOTE low sample size
src/lib/useEthereumTransaction.js+2−1
@@ -82,7 +82,8 @@ export default function useEthereumTransaction(
8282 const canSign = !initializing && constructed && isDefaultState;
8383
8484 const construct = useCallback(
85− (...args) => setUnsignedTransaction(transactionBuilder(...args)),
85+ async (...args) =>
86+ setUnsignedTransaction(await transactionBuilder(...args)),
8687 [transactionBuilder]
8788 );
8889
src/lib/usePermissionsForPoint.js+10−3
@@ -47,9 +47,12 @@ export default function usePermissionsForPoint(address, point) {
4747 const isPlanet = pointSize === azimuth.PointSize.Planet;
4848 const isStar = pointSize === azimuth.PointSize.Star;
4949 const isGalaxy = pointSize === azimuth.PointSize.Galaxy;
50+ const isParent = isStar || isGalaxy;
51+
52+ const isActive = details.active;
5053
5154 const isOwner = eqAddr(address, details.owner);
52− const isActiveOwner = isOwner && details.active;
55+ const isActiveOwner = isOwner && isActive;
5356 const isManagementProxy = eqAddr(address, details.managementProxy);
5457 const isSpawnProxy = eqAddr(address, details.spawnProxy);
5558 const isVotingProxy = eqAddr(address, details.votingProxy);
@@ -62,8 +65,9 @@ export default function usePermissionsForPoint(address, point) {
6265
6366 const canManage = isOwner || isManagementProxy;
6467 const canTransfer = isOwner || isTransferProxy;
65− const canSpawn = (isStar || isGalaxy) && (isOwner || isSpawnProxy);
66− const canVote = isGalaxy && (isOwner || isVotingProxy);
68+ const canSpawn =
69+ isParent && (isOwner || isSpawnProxy) && details.keyRevisionNumber > 0;
70+ const canVote = isGalaxy && isActive && (isOwner || isVotingProxy);
6771
6872 const spawnIsDelegatedSending = eqAddr(
6973 _contracts.delegatedSending.address,
@@ -74,6 +78,9 @@ export default function usePermissionsForPoint(address, point) {
7478 isPlanet,
7579 isStar,
7680 isGalaxy,
81+ isParent,
82+ //
83+ isActive,
7784 //
7885 isOwner,
7986 isActiveOwner,
src/views/GenKeyfile.jsdeleted−142
@@ -1,142 +0,0 @@
1−import React from 'react';
2−import * as need from '../lib/need';
3−
4−import { Button } from '../components/old/Base';
5−import { H1, P } from '../components/old/Base';
6−
7−import * as ob from 'urbit-ob';
8−import * as kg from 'urbit-key-generation/dist';
9−import saveAs from 'file-saver';
10−
11−import { attemptNetworkSeedDerivation, genKey } from '../lib/keys';
12−import { addHexPrefix } from '../lib/wallet';
13−import { compose } from '../lib/lib';
14−import { withWallet } from '../store/wallet';
15−import { withPointCursor } from '../store/pointCursor';
16−import { withPointCache } from '../store/pointCache';
17−import View from 'components/View';
18−
19−class GenKeyfile extends React.Component {
20− constructor(props) {
21− super(props);
22−
23− this.state = {
24− keyfile: '',
25− loaded: false,
26− };
27− }
28−
29− getPointDetails() {
30− const point = need.point(this.props.pointCursor);
31− const pointDetails = need.fromPointCache(this.props.pointCache, point);
32−
33− // in case we did SetKeys earlier this session, make sure to generate the
34− // newer keyfile, rather than the one that will expire soon
35− const revision = this.props.networkRevision.matchWith({
36− Nothing: () => parseInt(pointDetails.keyRevisionNumber, 10),
37− Just: p => p.value,
38− });
39−
40− return {
41− point,
42− pointDetails,
43− revision,
44− };
45− }
46−
47− async componentDidMount() {
48− const { point, pointDetails, revision } = this.getPointDetails();
49− let keyfile = '';
50−
51− const hexRegExp = /[0-9A-Fa-f]{64}/g;
52− const networkSeed = await this.deriveSeed();
53−
54− const keysmatch = this.checkKeysMatch(networkSeed, pointDetails);
55− const seedValid = hexRegExp.test(networkSeed);
56−
57− if (keysmatch && seedValid) {
58− keyfile = genKey(networkSeed, point, revision);
59− }
60−
61− this.setState({
62− keyfile: keyfile,
63− loaded: true,
64− });
65− }
66−
67− checkKeysMatch(networkSeed, pointDetails) {
68− const crypub = pointDetails.encryptionKey;
69− const sgnpub = pointDetails.authenticationKey;
70−
71− const { crypt, auth } = kg.deriveNetworkKeys(networkSeed);
72−
73− const keysmatch =
74− crypub === addHexPrefix(crypt.public) &&
75− sgnpub === addHexPrefix(auth.public);
76−
77− return keysmatch;
78− }
79−
80− async deriveSeed() {
81− const next = false;
82−
83− const seed = await attemptNetworkSeedDerivation(next, this.props);
84−
85− // either return the derived seed, the cached seed, or empty string
86− return seed.matchWith({
87− Nothing: () => this.props.networkSeed.getOrElse(''),
88− Just: p => p.value,
89− });
90− }
91−
92− render() {
93− const { point, revision } = this.getPointDetails();
94− const { keyfile, loaded } = this.state;
95−
96− return (
97− <View>
98− <H1>{'Generate keyfile'}</H1>
99−
100− <P>{'Download a private key file for booting this point in Arvo.'}</P>
101−
102− {keyfile === '' && !loaded && <P>{'Generating keyfile...'}</P>}
103−
104− {keyfile === '' && loaded && (
105− <React.Fragment>
106− <P>
107− <b>Warning: </b>
108− {`No valid network seed detected. To generate a keyfile, you
109− must reset your networking keys, or try logging in with your
110− master ticket or management mnemonic.`}
111− </P>
112−
113− <P>
114− {`If you've just reset your networking keys, you may need to wait for the transaction to go through. Check back shortly.`}
115− </P>
116− </React.Fragment>
117− )}
118−
119− {keyfile !== '' && (
120− <React.Fragment>
121− <div className="pb-5 text-code keyfile">{keyfile}</div>
122− <Button
123− onClick={() => {
124− let blob = new Blob([keyfile], {
125− type: 'text/plain;charset=utf-8',
126− });
127− saveAs(blob, `${ob.patp(point).slice(1)}-${revision}.key`);
128− }}>
129− Download →
130− </Button>
131− </React.Fragment>
132− )}
133− </View>
134− );
135− }
136−}
137−
138−export default compose(
139− withWallet,
140− withPointCursor,
141− withPointCache
142−)(GenKeyfile);
src/views/Point.js+12−3
@@ -23,7 +23,12 @@ export default function Point() {
2323
2424 const point = need.point(pointCursor);
2525
26− const { isActiveOwner, canManage, canSpawn } = useCurrentPermissions();
26+ const {
27+ isParent,
28+ isActiveOwner,
29+ canManage,
30+ canSpawn,
31+ } = useCurrentPermissions();
2732
2833 // fetch the invites for the current cursor
2934 const { availableInvites } = useInvites(point);
@@ -81,9 +86,13 @@ export default function Point() {
8186 Admin
8287 </Grid.Item>
8388 <Grid.Divider />
84− {canSpawn && (
89+ {isParent && (
8590 <>
86− <Grid.Item full as={ForwardButton} onClick={goIssuePoint}>
91+ <Grid.Item
92+ full
93+ as={ForwardButton}
94+ disabled={!canSpawn}
95+ onClick={goIssuePoint}>
8796 Issue Point
8897 </Grid.Item>
8998 <Grid.Divider />
src/views/Point/Actions.jsdeleted−188
@@ -1,188 +0,0 @@
1−import React from 'react';
2−import { azimuth } from 'azimuth-js';
3−import * as need from '../../lib/need';
4−
5−import { isZeroAddress, eqAddr } from '../../lib/wallet';
6−import { H2, P } from '../../components/old/Base';
7−import { Button } from '../../components/old/Base';
8−import { ROUTE_NAMES } from '../../lib/routeNames';
9−import { useHistory } from '../../store/history';
10−import { useWallet } from '../../store/wallet';
11−import { Grid } from 'indigo-react';
12−import { usePointCursor } from 'store/pointCursor';
13−import { usePointCache } from 'store/pointCache';
14−import { CURVE_ZERO_ADDR } from 'lib/keys';
15−
16−const isPlanet = point =>
17− azimuth.getPointSize(point) === azimuth.PointSize.Planet;
18−
19−function Actions() {
20− const history = useHistory();
21− const { wallet } = useWallet();
22− const { pointCursor } = usePointCursor();
23− const point = need.point(pointCursor);
24− const { getDetails } = usePointCache();
25− const pointDetails = getDetails(point);
26−
27− const addr = need.addressFromWallet(wallet);
28−
29− const planet = isPlanet(point);
30−
31− const isOwner = pointDetails.matchWith({
32− Nothing: _ => false,
33− Just: details => eqAddr(details.value.owner, addr),
34− });
35− const isActive = pointDetails.matchWith({
36− Nothing: _ => false,
37− Just: details => details.value.active,
38− });
39− const isActiveOwner = isOwner && isActive;
40− const canSetSpawnProxy = isActiveOwner && !planet;
41− const canSetManagementProxy = isActiveOwner;
42−
43− const canManage =
44− isOwner ||
45− pointDetails.matchWith({
46− Nothing: _ => false,
47− Just: details => eqAddr(details.value.managementProxy, addr),
48− });
49− const canConfigureKeys = canManage && isActive;
50−
51− const canIssueChild = pointDetails.matchWith({
52− Nothing: () => false,
53− Just: details => {
54− const hasPermission = isOwner || eqAddr(details.value.spawnProxy, addr);
55−
56− const isBooted = details.value.keyRevisionNumber > 0;
57−
58− const isNotPlanet = !isPlanet(point);
59−
60− return hasPermission && isBooted && isNotPlanet;
61− },
62− });
63−
64− const canTransfer = pointDetails.matchWith({
65− Nothing: () => false,
66− Just: deets =>
67− eqAddr(deets.value.transferProxy, addr) ||
68− eqAddr(deets.value.owner, addr),
69− });
70−
71− const canAcceptTransfer = pointDetails.matchWith({
72− Nothing: () => false,
73− Just: deets => eqAddr(deets.value.transferProxy, addr),
74− });
75−
76− const canCancelTransfer = pointDetails.matchWith({
77− Nothing: () => false,
78− Just: deets =>
79− eqAddr(deets.value.owner, addr) &&
80− !isZeroAddress(deets.value.transferProxy),
81− });
82−
83− const displayReminder = pointDetails.matchWith({
84− Nothing: () => false,
85− Just: deets => {
86− return (
87− deets.value.encryptionKey === CURVE_ZERO_ADDR &&
88− deets.value.authenticationKey === CURVE_ZERO_ADDR
89− );
90− },
91− });
92−
93− return (
94− <div>
95− <H2>{'Actions'}</H2>
96− {displayReminder ? (
97− <P>{`Before you can issue child points or generate your Arvo
98− keyfile, you need to set your public keys.`}</P>
99− ) : (
100− ''
101− )}
102− <Grid>
103− <Grid.Item third={1}>
104− <Button
105− prop-size={'sm'}
106− prop-type={'link'}
107− disabled={planet && !canIssueChild}
108− onClick={() => {
109− history.push(ROUTE_NAMES.ISSUE_CHILD);
110− }}>
111− {'Issue child'}
112− </Button>
113−
114− <Button
115− prop-size={'sm'}
116− prop-type={'link'}
117− disabled={!canAcceptTransfer}
118− onClick={() => {
119− history.push(ROUTE_NAMES.ACCEPT_TRANSFER);
120− }}>
121− {'Accept incoming transfer'}
122− </Button>
123−
124− <Button
125− prop-size={'sm'}
126− prop-type={'link'}
127− disabled={!canCancelTransfer}
128− onClick={() => {
129− history.push(ROUTE_NAMES.CANCEL_TRANSFER);
130− }}>
131− {'Cancel outgoing transfer'}
132− </Button>
133− </Grid.Item>
134− <Grid.Item third={2}>
135− <Button
136− disabled={!canSetSpawnProxy}
137− prop-size={'sm'}
138− prop-type={'link'}
139− onClick={() => {
140− history.push(ROUTE_NAMES.SET_SPAWN_PROXY);
141− }}>
142− {'Change spawn proxy'}
143− </Button>
144−
145− <Button
146− disabled={!canSetManagementProxy}
147− prop-size={'sm'}
148− prop-type={'link'}
149− onClick={() => {
150− history.push(ROUTE_NAMES.SET_MANAGEMENT_PROXY);
151− }}>
152− {'Change management proxy'}
153− </Button>
154−
155− <Button
156− disabled={!canConfigureKeys}
157− prop-size={'sm'}
158− prop-type={'link'}
159− onClick={() => {
160− history.push(ROUTE_NAMES.SET_KEYS);
161− }}>
162− {'Set network keys'}
163− </Button>
164−
165− <Button
166− disabled={!canTransfer}
167− prop-size={'sm'}
168− prop-type={'link'}
169− onClick={() => {
170− history.push(ROUTE_NAMES.TRANSFER);
171− }}>
172− {'Transfer'}
173− </Button>
174− <Button
175− prop-size={'sm'}
176− prop-type={'link'}
177− onClick={() => {
178− history.push(ROUTE_NAMES.INVITES_MANAGE);
179− }}>
180− {'Invite'}
181− </Button>
182− </Grid.Item>
183− </Grid>
184− </div>
185− );
186−}
187−
188−export default Actions;
src/views/Point/KeysAndMetadata.jsdeleted−151
@@ -1,151 +0,0 @@
1−import React from 'react';
2−import { H2, H4 } from '../../components/old/Base';
3−
4−import { isZeroAddress } from '../../lib/wallet';
5−import { Grid } from 'indigo-react';
6−import { CURVE_ZERO_ADDR } from 'lib/keys';
7−
8−const renderAddress = addr =>
9− isZeroAddress(addr) ? (
10− <div>{'(not set)'}</div>
11− ) : (
12− <div>
13− <div>
14− <code>{addr.slice(0, 14)}</code>
15− </div>
16− <div>
17− <code>{addr.slice(14, 28)}</code>
18− </div>
19− <div>
20− <code>{addr.slice(28)}</code>
21− </div>
22− </div>
23− );
24−
25−const renderNetworkKey = hex => {
26− const sl = i => hex.slice(i, i + 4);
27− const rowFrom = i => `${sl(i)}.${sl(i + 4)}.${sl(i + 8)}.${sl(i + 12)}`;
28− return hex === CURVE_ZERO_ADDR ? (
29− <div>{'(not set)'}</div>
30− ) : (
31− <div>
32− <div>
33− <code>{hex.slice(0, 2)}</code>
34− </div>
35− <div>
36− <code>{rowFrom(2)}</code>
37− </div>
38− <div>
39− <code>{rowFrom(18)}</code>
40− </div>
41− <div>
42− <code>{rowFrom(34)}</code>
43− </div>
44− <div>
45− <code>{rowFrom(50)}</code>
46− </div>
47− </div>
48− );
49−};
50−
51−const KeysAndMetadata = props => {
52− const { pointDetails } = props;
53−
54− return (
55− <Grid>
56− <Grid.Item full>
57− <H2>{'Ownership and Proxy Addresses'}</H2>
58− </Grid.Item>
59− <Grid.Item fourth={1}>
60− <H4>{'Owner'}</H4>
61− {pointDetails.matchWith({
62− Nothing: () => <div />,
63− Just: deets => renderAddress(deets.value.owner),
64− })}
65− </Grid.Item>
66− <Grid.Item fourth={2}>
67− <H4>{'Transfer Proxy'}</H4>
68− {pointDetails.matchWith({
69− Nothing: () => <div />,
70− Just: deets => renderAddress(deets.value.transferProxy),
71− })}
72− </Grid.Item>
73− <Grid.Item fourth={3}>
74− <H4>{'Spawn Proxy'}</H4>
75− {pointDetails.matchWith({
76− Nothing: () => <div />,
77− Just: deets => renderAddress(deets.value.spawnProxy),
78− })}
79− </Grid.Item>
80− <Grid.Item fourth={4}>
81− <H4>{'Mgmt Proxy'}</H4>
82− {pointDetails.matchWith({
83− Nothing: () => <div />,
84− Just: deets => renderAddress(deets.value.managementProxy),
85− })}
86− </Grid.Item>
87− <Grid.Item full>
88− <UrbitNetworking pointDetails={pointDetails} />
89− </Grid.Item>
90− </Grid>
91− );
92−};
93−
94−const UrbitNetworking = props => {
95− const { pointDetails } = props;
96−
97− const booted = pointDetails.matchWith({
98− Nothing: _ => false,
99− Just: details => details.value.keyRevisionNumber > 0,
100− });
101−
102− const body = !booted ? (
103− <div>{'(not set)'}</div>
104− ) : (
105− <Grid>
106− <Grid.Item third={1}>
107− <H4>{'Authentication'}</H4>
108− {pointDetails.matchWith({
109− Nothing: () => <div />,
110− Just: deets => renderNetworkKey(deets.value.authenticationKey),
111− })}
112− </Grid.Item>
113− <Grid.Item third={2}>
114− <H4>{'Encryption'}</H4>
115− {pointDetails.matchWith({
116− Nothing: () => <div />,
117− Just: deets => renderNetworkKey(deets.value.encryptionKey),
118− })}
119− </Grid.Item>
120− <Grid.Item third={3}>
121− <H4>{'Revision'}</H4>
122− {pointDetails.matchWith({
123− Nothing: () => '-',
124− Just: deets => deets.value.keyRevisionNumber,
125− })}
126−
127− <H4>{'Continuity era'}</H4>
128− {pointDetails.matchWith({
129− Nothing: () => '-',
130− Just: deets => deets.value.continuityNumber,
131− })}
132−
133− <H4>{'Crypto suite version'}</H4>
134− {pointDetails.matchWith({
135− Nothing: () => '-',
136− Just: deets => deets.value.cryptoSuiteVersion,
137− })}
138− </Grid.Item>
139− </Grid>
140− );
141−
142− return (
143− <div>
144− <H2>{'Public Keys'}</H2>
145−
146− {body}
147− </div>
148− );
149−};
150−
151−export default KeysAndMetadata;
src/views/Points.js+27−2
@@ -1,5 +1,5 @@
11import React from 'react';
2−import { Nothing } from 'folktale/maybe';
2+import { Just, Nothing } from 'folktale/maybe';
33import { H1, H2, P, Grid } from 'indigo-react';
44
55import { ROUTE_NAMES } from 'lib/routeNames';
@@ -11,11 +11,36 @@ import { useHistory } from 'store/history';
1111import { useWallet } from 'store/wallet';
1212import { usePointCache } from 'store/pointCache';
1313
14−import PointList from 'components/old/PointList';
1514import View from 'components/View';
1615import { ForwardButton } from 'components/Buttons';
1716import useLifecycle from 'lib/useLifecycle';
1817
18+//TODO new component
19+import { usePointCursor } from 'store/pointCursor';
20+import * as ob from 'urbit-ob';
21+const PointList = function(props) {
22+ const { setPointCursor } = usePointCursor();
23+ const history = useHistory();
24+ const { points, loading } = props;
25+
26+ return points.length === 0 ? (
27+ <p>{loading ? 'Loading...' : 'No points to display'}</p>
28+ ) : (
29+ <>
30+ {points.map(point => (
31+ <P
32+ key={point}
33+ onClick={() => {
34+ setPointCursor(Just(point));
35+ history.push(ROUTE_NAMES.POINT);
36+ }}>
37+ {ob.patp(point)}
38+ </P>
39+ ))}
40+ </>
41+ );
42+};
43+
1944const matchArray = obj =>
2045 obj.matchWith({ Nothing: () => [], Just: p => p.value });
2146
src/views/ViewPoint.js+1−3
@@ -1,8 +1,6 @@
11import React, { useCallback } from 'react';
22import { Just } from 'folktale/maybe';
3−import { Input } from 'indigo-react';
4−
5−import { H1, P } from '../components/old/Base';
3+import { Input, H1, P } from 'indigo-react';
64
75import { useHistory } from 'store/history';
86import { usePointCursor } from 'store/pointCursor';