Organise elements in fieldboxes

This commit is contained in:
Franck Royer 2021-06-29 15:32:29 +10:00
parent 5661c7d1ec
commit 31d0efc8d2
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
8 changed files with 232 additions and 129 deletions

View File

@ -8,6 +8,7 @@
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@material-ui/core": "^4.11.4", "@material-ui/core": "^4.11.4",
"@material-ui/icons": "^4.11.2",
"@testing-library/jest-dom": "^5.11.4", "@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0", "@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10", "@testing-library/user-event": "^12.1.10",
@ -3451,6 +3452,28 @@
} }
} }
}, },
"node_modules/@material-ui/icons": {
"version": "4.11.2",
"resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.2.tgz",
"integrity": "sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ==",
"dependencies": {
"@babel/runtime": "^7.4.4"
},
"engines": {
"node": ">=8.0.0"
},
"peerDependencies": {
"@material-ui/core": "^4.0.0",
"@types/react": "^16.8.6 || ^17.0.0",
"react": "^16.8.0 || ^17.0.0",
"react-dom": "^16.8.0 || ^17.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@material-ui/styles": { "node_modules/@material-ui/styles": {
"version": "4.11.4", "version": "4.11.4",
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz", "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",
@ -26510,6 +26533,14 @@
"react-transition-group": "^4.4.0" "react-transition-group": "^4.4.0"
} }
}, },
"@material-ui/icons": {
"version": "4.11.2",
"resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.2.tgz",
"integrity": "sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ==",
"requires": {
"@babel/runtime": "^7.4.4"
}
},
"@material-ui/styles": { "@material-ui/styles": {
"version": "4.11.4", "version": "4.11.4",
"resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz", "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz",

View File

@ -5,6 +5,7 @@
"homepage": "/js-waku/eth-dm", "homepage": "/js-waku/eth-dm",
"dependencies": { "dependencies": {
"@material-ui/core": "^4.11.4", "@material-ui/core": "^4.11.4",
"@material-ui/icons": "^4.11.2",
"@testing-library/jest-dom": "^5.11.4", "@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0", "@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10", "@testing-library/user-event": "^12.1.10",

View File

@ -9,16 +9,61 @@ import { createPublicKeyMessage, KeyPair } from './crypto';
import { encode, PublicKeyMessage } from './messages'; import { encode, PublicKeyMessage } from './messages';
import Messages, { Message } from './Messages'; import Messages, { Message } from './Messages';
import 'fontsource-roboto'; import 'fontsource-roboto';
import { Button } from '@material-ui/core'; import {
AppBar,
Button,
IconButton,
Toolbar,
Typography,
} from '@material-ui/core';
import SendMessage from './SendMessage'; import SendMessage from './SendMessage';
import KeyPairHandling from './key_pair_handling/KeyPairHandling'; import KeyPairHandling from './key_pair_handling/KeyPairHandling';
import InitWaku from './InitWaku'; import InitWaku from './InitWaku';
import {
createMuiTheme,
ThemeProvider,
makeStyles,
} from '@material-ui/core/styles';
import { teal, purple, green } from '@material-ui/core/colors';
import WifiIcon from '@material-ui/icons/Wifi';
export const PublicKeyContentTopic = '/eth-dm/1/public-key/json'; export const PublicKeyContentTopic = '/eth-dm/1/public-key/json';
export const DirectMessageContentTopic = '/eth-dm/1/direct-message/json'; export const DirectMessageContentTopic = '/eth-dm/1/direct-message/json';
declare let window: any; declare let window: any;
const theme = createMuiTheme({
palette: {
primary: {
main: purple[500],
},
secondary: {
main: teal[600],
},
},
});
const useStyles = makeStyles({
root: {
textAlign: 'center',
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
},
appBar: {
// height: '200p',
},
container: {
display: 'flex',
flex: 1,
},
main: {
flex: 1,
margin: '10px',
},
wakuStatus: {},
});
function App() { function App() {
const [waku, setWaku] = useState<Waku>(); const [waku, setWaku] = useState<Waku>();
const [provider, setProvider] = useState<Web3Provider>(); const [provider, setProvider] = useState<Web3Provider>();
@ -28,6 +73,8 @@ function App() {
const [messages, setMessages] = useState<Message[]>([]); const [messages, setMessages] = useState<Message[]>([]);
const [address, setAddress] = useState<string>(); const [address, setAddress] = useState<string>();
const classes = useStyles();
useEffect(() => { useEffect(() => {
if (provider) return; if (provider) return;
try { try {
@ -72,34 +119,58 @@ function App() {
}; };
return ( return (
<div className="App"> <ThemeProvider theme={theme}>
<header className="App-header"> <div className={classes.root}>
<InitWaku <AppBar className={classes.appBar} position="static">
ethDmKeyPair={ethDmKeyPair} <Toolbar>
setMessages={setMessages} <Typography>Ethereum Direct Message</Typography>
setPublicKeys={setPublicKeys} <IconButton
setWaku={setWaku} edge="end"
waku={waku} className={classes.wakuStatus}
address={address} aria-label="waku-status"
/> >
<KeyPairHandling <WifiIcon
ethDmKeyPair={ethDmKeyPair} color={waku ? undefined : 'disabled'}
setEthDmKeyPair={(keyPair) => setEthDmKeyPair(keyPair)} style={waku ? { color: green[500] } : {}}
/> />
<div> </IconButton>
<Button </Toolbar>
variant="contained" </AppBar>
color="primary"
onClick={broadcastPublicKey} <div className={classes.container}>
disabled={!ethDmKeyPair || !waku} <main className={classes.main}>
> <InitWaku
Broadcast Eth-DM Public Key ethDmKeyPair={ethDmKeyPair}
</Button> setMessages={setMessages}
setPublicKeys={setPublicKeys}
setWaku={setWaku}
waku={waku}
address={address}
/>
<fieldset>
<legend>Eth-DM Key Pair</legend>
<KeyPairHandling
ethDmKeyPair={ethDmKeyPair}
setEthDmKeyPair={(keyPair) => setEthDmKeyPair(keyPair)}
/>
<Button
variant="contained"
color="primary"
onClick={broadcastPublicKey}
disabled={!ethDmKeyPair || !waku}
>
Broadcast Eth-DM Public Key
</Button>
</fieldset>
<fieldset>
<legend>Messaging</legend>
<SendMessage recipients={publicKeys} waku={waku} />
<Messages messages={messages} />
</fieldset>
</main>
</div> </div>
<SendMessage recipients={publicKeys} waku={waku} /> </div>
<Messages messages={messages} /> </ThemeProvider>
</header>
</div>
); );
} }

View File

@ -79,7 +79,7 @@ export default function InitWaku({
}; };
}); });
return <p>{!!waku ? 'Waku is ready' : 'Waku is loading'}</p>; return <div />;
} }
async function initWaku(): Promise<Waku> { async function initWaku(): Promise<Waku> {

View File

@ -1,8 +1,32 @@
import { Button } from '@material-ui/core'; import { Button } from '@material-ui/core';
import { LoadKeyPair } from './LoadKeyPair'; import { LoadKeyPair } from './LoadKeyPair';
import { SaveKeyPair } from './SaveKeyPair'; import { SaveKeyPair } from './SaveKeyPair';
import React from 'react'; import React, { useState } from 'react';
import { generateEthDmKeyPair, KeyPair } from '../crypto'; import { generateEthDmKeyPair, KeyPair } from '../crypto';
import { makeStyles } from '@material-ui/core/styles';
import PasswordInput from './PasswordInput';
const useStyles = makeStyles({
root: {
textAlign: 'center',
display: 'flex',
alignItems: 'center',
flexDirection: 'column',
margin: '5px',
},
generate: { margin: '5px' },
storage: {
margin: '5px',
},
loadSave: {
display: 'flex',
flexDirection: 'row',
margin: '5px',
},
loadSaveButton: {
margin: '5px',
},
});
export interface Props { export interface Props {
ethDmKeyPair: KeyPair | undefined; ethDmKeyPair: KeyPair | undefined;
@ -13,6 +37,10 @@ export default function KeyPairHandling({
ethDmKeyPair, ethDmKeyPair,
setEthDmKeyPair, setEthDmKeyPair,
}: Props) { }: Props) {
const classes = useStyles();
const [password, setPassword] = useState<string>();
const generateKeyPair = () => { const generateKeyPair = () => {
if (ethDmKeyPair) return; if (ethDmKeyPair) return;
@ -26,43 +54,33 @@ export default function KeyPairHandling({
}; };
return ( return (
<div> <div className={classes.root}>
<div <Button
style={{ className={classes.generate}
display: 'flex', variant="contained"
alignItems: 'center', color="primary"
flexWrap: 'wrap', onClick={generateKeyPair}
}} disabled={!!ethDmKeyPair}
> >
<Button Generate Eth-DM Key Pair
variant="contained" </Button>
color="primary" <div className={classes.storage}>
onClick={generateKeyPair} <PasswordInput
disabled={!!ethDmKeyPair} password={password}
> setPassword={(p) => setPassword(p)}
Generate Eth-DM Key Pair
</Button>
</div>
<div
style={{
display: 'flex',
alignItems: 'center',
flexWrap: 'wrap',
}}
>
<LoadKeyPair
setEthDmKeyPair={(keyPair) => setEthDmKeyPair(keyPair)}
disabled={!!ethDmKeyPair}
/> />
</div> <div className={classes.loadSave}>
<div <div className={classes.loadSaveButton}>
style={{ <LoadKeyPair
display: 'flex', setEthDmKeyPair={(keyPair) => setEthDmKeyPair(keyPair)}
alignItems: 'center', disabled={!!ethDmKeyPair}
flexWrap: 'wrap', password={password}
}} />
> </div>
<SaveKeyPair ethDmKeyPair={ethDmKeyPair} /> <div className={classes.loadSaveButton}>
<SaveKeyPair ethDmKeyPair={ethDmKeyPair} password={password} />
</div>
</div>
</div> </div>
</div> </div>
); );

View File

@ -1,20 +1,15 @@
import { Button, TextField } from '@material-ui/core'; import { Button } from '@material-ui/core';
import React, { ChangeEvent, useState } from 'react'; import React from 'react';
import { loadKeyPairFromStorage } from './key_pair_storage'; import { loadKeyPairFromStorage } from './key_pair_storage';
import { KeyPair } from '../crypto'; import { KeyPair } from '../crypto';
export interface Props { export interface Props {
setEthDmKeyPair: (keyPair: KeyPair) => void; setEthDmKeyPair: (keyPair: KeyPair) => void;
disabled: boolean; disabled: boolean;
password: string | undefined;
} }
export function LoadKeyPair({ disabled, setEthDmKeyPair }: Props) { export function LoadKeyPair({ password, disabled, setEthDmKeyPair }: Props) {
const [password, setPassword] = useState<string>();
const handlePasswordChange = (event: ChangeEvent<HTMLInputElement>) => {
setPassword(event.target.value);
};
const loadKeyPair = () => { const loadKeyPair = () => {
if (disabled) return; if (disabled) return;
if (!password) return; if (!password) return;
@ -26,29 +21,13 @@ export function LoadKeyPair({ disabled, setEthDmKeyPair }: Props) {
}; };
return ( return (
<div <Button
style={{ variant="contained"
display: 'flex', color="primary"
alignItems: 'center', onClick={loadKeyPair}
flexWrap: 'wrap', disabled={!password || disabled}
}}
> >
<TextField Load Eth-DM Key Pair from storage
id="password-input" </Button>
label="Password"
variant="filled"
type="password"
onChange={handlePasswordChange}
value={password}
/>
<Button
variant="contained"
color="primary"
onClick={loadKeyPair}
disabled={!password || disabled}
>
Load Eth-DM Key Pair from storage
</Button>
</div>
); );
} }

View File

@ -0,0 +1,24 @@
import { TextField } from '@material-ui/core';
import React, { ChangeEvent } from 'react';
interface Props {
password: string | undefined;
setPassword: (password: string) => void;
}
export default function PasswordInput({ password, setPassword }: Props) {
const handlePasswordChange = (event: ChangeEvent<HTMLInputElement>) => {
setPassword(event.target.value);
};
return (
<TextField
id="password-input"
label="Password"
variant="filled"
type="password"
onChange={handlePasswordChange}
value={password}
/>
);
}

View File

@ -1,19 +1,14 @@
import { Button, TextField } from '@material-ui/core'; import { Button } from '@material-ui/core';
import React, { ChangeEvent, useState } from 'react'; import React from 'react';
import { KeyPair } from '../crypto'; import { KeyPair } from '../crypto';
import { saveKeyPairToStorage } from './key_pair_storage'; import { saveKeyPairToStorage } from './key_pair_storage';
export interface Props { export interface Props {
ethDmKeyPair: KeyPair | undefined; ethDmKeyPair: KeyPair | undefined;
password: string | undefined;
} }
export function SaveKeyPair({ ethDmKeyPair }: Props) { export function SaveKeyPair({ password, ethDmKeyPair }: Props) {
const [password, setPassword] = useState<string>();
const handlePasswordChange = (event: ChangeEvent<HTMLInputElement>) => {
setPassword(event.target.value);
};
const saveKeyPair = () => { const saveKeyPair = () => {
if (!ethDmKeyPair) return; if (!ethDmKeyPair) return;
if (!password) return; if (!password) return;
@ -23,29 +18,13 @@ export function SaveKeyPair({ ethDmKeyPair }: Props) {
}; };
return ( return (
<div <Button
style={{ variant="contained"
display: 'flex', color="primary"
alignItems: 'center', onClick={saveKeyPair}
flexWrap: 'wrap', disabled={!password || !ethDmKeyPair}
}}
> >
<TextField Save Eth-DM Key Pair to storage
id="password-input" </Button>
label="Password"
variant="filled"
type="password"
onChange={handlePasswordChange}
value={password}
/>
<Button
variant="contained"
color="primary"
onClick={saveKeyPair}
disabled={!password || !ethDmKeyPair}
>
Save Eth-DM Key Pair to storage
</Button>
</div>
); );
} }