Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Developer UI: Safe page #136

Merged
merged 88 commits into from
Apr 24, 2021
Merged
Show file tree
Hide file tree
Changes from 87 commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
97edeb8
signer wip
mmv08 Feb 10, 2021
4d3a267
signer wip
mmv08 Feb 10, 2021
049b696
signer wip
mmv08 Feb 10, 2021
a17b80f
wip
mmv08 Feb 11, 2021
267341e
da mvp
mmv08 Feb 11, 2021
fdcd83c
dep bump
mmv08 Feb 12, 2021
10b15ef
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Feb 15, 2021
64a64f8
Signer wip
mmv08 Feb 15, 2021
80cd04d
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Feb 16, 2021
893b792
ethers signer
mmv08 Feb 16, 2021
231b769
remove yalc from signer
mmv08 Feb 16, 2021
58ae5d8
remove console.logs
mmv08 Feb 16, 2021
01510e3
change ethersprovider version
mmv08 Feb 16, 2021
7bc2323
add docs
mmv08 Feb 16, 2021
fc28d95
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Feb 17, 2021
a804dde
type fixes
mmv08 Feb 17, 2021
f4f3fcd
utils/poll: remove double increment
mmv08 Feb 17, 2021
8fe85e2
dep updatE
mmv08 Feb 17, 2021
d46985f
doc fix
mmv08 Feb 17, 2021
6fce81b
remove jsonrpc error check logic in checkError
mmv08 Feb 17, 2021
ef5fd35
ui: hello world
mmv08 Feb 25, 2021
22033b4
safe dev ui: hello world
mmv08 Feb 25, 2021
4b0fea4
pin jest version to the one required by react-scripts
mmv08 Feb 25, 2021
d382f58
test script fix
mmv08 Feb 25, 2021
ca851ac
dep bump
mmv08 Mar 1, 2021
a327276
use jest 26.6.0
mmv08 Mar 1, 2021
c223968
bootstrapping
mmv08 Mar 1, 2021
787cb46
wip
mmv08 Mar 1, 2021
a010adb
wip
mmv08 Mar 1, 2021
bafe43f
wip
mmv08 Mar 2, 2021
d8728b1
dep bump
mmv08 Mar 3, 2021
bb7b222
wip
mmv08 Mar 3, 2021
0b6fa02
trying to make header work
mmv08 Mar 3, 2021
9399b91
got this thing to render
mmv08 Mar 4, 2021
9e679a3
logo alignment
mmv08 Mar 4, 2021
ea25d98
a battle with changing default font family in mui
mmv08 Mar 4, 2021
b7b7a31
a battle with font scaling
mmv08 Mar 4, 2021
61c4a55
header
mmv08 Mar 5, 2021
b2232d8
header battle continues
mmv08 Mar 5, 2021
ef3ee32
material ui warning fixes
mmv08 Mar 9, 2021
5667c70
Fix web3modal
mmv08 Mar 9, 2021
b3f81cf
provider store wip
mmv08 Mar 9, 2021
e51e18f
provider store wip
mmv08 Mar 9, 2021
87b531d
provider details wip
mmv08 Mar 9, 2021
3e3cd42
provider details wip
mmv08 Mar 9, 2021
884dc57
Merge branch 'feature/dev-ui' of github.com:gnosis/safe-apps-sdk into…
mmv08 Mar 9, 2021
b8b1fd9
wip:
mmv08 Mar 10, 2021
3368b3c
connected account details
mmv08 Mar 10, 2021
59bd4f9
connect/disconnect provider
mmv08 Mar 10, 2021
b5839db
welcome page layout
mmv08 Mar 11, 2021
9fbf9f3
welcome page layout
mmv08 Mar 11, 2021
cd043af
welcome page layout wip
mmv08 Mar 12, 2021
16c0bfe
welcome page layout done
mmv08 Mar 12, 2021
f0f86b1
welcome page connect provider
mmv08 Mar 12, 2021
4e12f58
deploy contracts wip
mmv08 Mar 12, 2021
8fa6b16
save contract addresses to state
mmv08 Mar 15, 2021
1b65f75
save contract addresses to localstorage
mmv08 Mar 15, 2021
f84f824
deploying safe wip
mmv08 Mar 15, 2021
d0b5692
deploy safe function
mmv08 Mar 16, 2021
b9bc7c9
dep bump
mmv08 Mar 23, 2021
c4d2a27
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Mar 23, 2021
76d301e
dep bump
mmv08 Mar 23, 2021
bb7ae9b
update package json
mmv08 Mar 23, 2021
1eec182
deploy safe and redirect to safe page
mmv08 Mar 23, 2021
d3c6e15
disable btn
mmv08 Mar 23, 2021
f7330fa
safe page wip
mmv08 Mar 23, 2021
aeb56fc
type fixes
mmv08 Mar 24, 2021
d92f95c
cache provider
mmv08 Mar 24, 2021
93b07d0
sidebar wip
mmv08 Mar 24, 2021
daf89f4
sidebar wip
mmv08 Mar 24, 2021
45060a1
mui theme fixes, sidebar wip
mmv08 Mar 25, 2021
20ecf86
sidebar wip
mmv08 Mar 25, 2021
52db5a8
redirects and stuff
mmv08 Mar 25, 2021
934d663
use borderbox box sizing
mmv08 Mar 25, 2021
c874477
loading app
mmv08 Mar 26, 2021
b6faf2d
dep bump
mmv08 Mar 29, 2021
dd44e49
wip
mmv08 Mar 29, 2021
199d3fa
display safe app in an iframe
mmv08 Mar 29, 2021
48c6cd9
safe app connector
mmv08 Mar 29, 2021
1e1a71a
connector wip
mmv08 Mar 29, 2021
636ba1e
getSafeInfo handler
mmv08 Mar 30, 2021
0b3a450
Handle rpc calls
mmv08 Mar 30, 2021
9319b20
Merge branch 'development' of github.com:gnosis/safe-apps-sdk into fe…
mmv08 Apr 23, 2021
9ab28b6
fix eslint errors
mmv08 Apr 23, 2021
1e7e42a
regen yarn lock
mmv08 Apr 23, 2021
01a32c1
fix tsts
mmv08 Apr 23, 2021
7646460
fix tsts
mmv08 Apr 23, 2021
7e13096
feedback fixes
mmv08 Apr 24, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.17.0",
"@typescript-eslint/parser": "^4.17.0",
"eslint": "7.21.0",
"eslint": "7.23.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-prettier": "^3.3.1",
"jest": "26.6.0",
Expand Down
14 changes: 7 additions & 7 deletions packages/safe-apps-developer-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@gnosis.pm/safe-apps-react-sdk": "2.1.0",
"@gnosis.pm/safe-apps-sdk": "^2.2.0",
"@gnosis.pm/safe-contracts": "1.1.1-dev.2",
"@material-ui/core": "^4.11.3",
"@material-ui/icons": "^4.11.2",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/jest-dom": "^5.11.10",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.8.3",
"@testing-library/user-event": "^13.0.16",
"@types/styled-components": "^5.1.9",
"@walletconnect/web3-provider": "^1.4.0",
"clsx": "^1.1.1",
Expand Down Expand Up @@ -43,17 +43,17 @@
]
},
"devDependencies": {
"@types/jest": "^26.0.21",
"@types/node": "^14.14.35",
"@types/jest": "^26.0.22",
"@types/node": "^14.14.37",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.3",
"@types/react-router": "^5.1.12",
"@types/react-router": "^5.1.13",
"@types/react-router-dom": "^5.1.7",
"eslint-config-react-app": "^6.0.0",
"eslint-plugin-flowtype": "^5.4.0",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-jsx-a11y": "^6.3.1",
"eslint-plugin-react": "^7.23.0",
"eslint-plugin-react": "^7.23.1",
"eslint-plugin-react-hooks": "^4.2.0",
"web-vitals": "^1.1.1"
}
Expand Down
6 changes: 5 additions & 1 deletion packages/safe-apps-developer-ui/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom';
import Header from 'src/components/Header';
import { WelcomePage } from './pages/Welcome';
import { SafePage } from './pages/safes';

function App(): React.ReactElement {
return (
<Router>
<Header />
<Switch>
<Route path="/">
<Route exact path="/">
<WelcomePage />
</Route>
<Route path="/safes/:safeAddress">
<SafePage />
</Route>
<Redirect to="/" />
</Switch>
</Router>
Expand Down
3 changes: 1 addition & 2 deletions packages/safe-apps-developer-ui/src/api/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,11 @@ const providerOptions: IProviderOptions = {
},
};

const web3Modal = new Web3Modal({ network: 'rinkeby', providerOptions });
const web3Modal = new Web3Modal({ network: 'rinkeby', providerOptions, cacheProvider: true });

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const connectToProvider = async (): Promise<any> => {
const provider = await web3Modal.connect();
console.log({ provider });
return provider;
};

Expand Down
16 changes: 12 additions & 4 deletions packages/safe-apps-developer-ui/src/components/ConnectButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@ import Button from '@material-ui/core/Button';

import { connectToProvider } from '../api/provider';
import { useProviderStore } from 'src/stores/provider';
import { getFromLocalStorage } from 'src/utils/localStorage';

const SButton = styled(Button)`
min-width: 140px;
`;

const ConnectButton = ({ className }: { className?: string }): React.ReactElement => {
const [disabled, setDisabled] = React.useState(false);
const [fetchAndSetProvider, updateProvider, disconnect] = useProviderStore((state) => [
const [fetchAndSetProvider, updateProvider, disconnect, account] = useProviderStore((state) => [
state.fetchAndSetProvider,
state.updateProvider,
state.disconnect,
state.account,
]);

const handleClick = async () => {
const handleProviderConnect = React.useCallback(async () => {
setDisabled(true);

try {
Expand All @@ -36,13 +38,19 @@ const ConnectButton = ({ className }: { className?: string }): React.ReactElemen
} finally {
setDisabled(false);
}
};
}, [fetchAndSetProvider, setDisabled, disconnect, updateProvider]);

React.useEffect(() => {
if (getFromLocalStorage('WEB3_CONNECT_CACHED_PROVIDER') && !account) {
handleProviderConnect();
}
}, [handleProviderConnect, account]);

return (
<SButton
color="primary"
type="button"
onClick={handleClick}
onClick={handleProviderConnect}
variant="contained"
disabled={disabled}
className={className}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { makeStyles } from '@material-ui/core/styles';
import * as React from 'react';
import { Link } from 'react-router-dom';

import Provider from './Provider';
import { Provider } from './Provider';

import { Img } from 'src/components/Layout/Img';
import { border, headerHeight, sm, md } from 'src/styles/variables';
Expand All @@ -16,7 +16,7 @@ import SafeLogo from '../assets/gnosis-safe-multisig-logo.svg';
import { Spacer } from 'src/components/Layout/Spacer';

const useStyles = makeStyles({
root: {
dropdownContainer: {
backgroundColor: 'white',
borderRadius: sm,
boxShadow: '0 0 10px 0 rgba(33, 48, 77, 0.1)',
Expand All @@ -25,7 +25,7 @@ const useStyles = makeStyles({
minHeight: '244px',
padding: 0,
},
summary: {
container: {
backgroundColor: 'white',
borderBottom: `solid 2px ${border}`,
boxShadow: '0 2px 4px 0 rgba(212, 212, 211, 0.59)',
Expand All @@ -52,7 +52,7 @@ const Layout = ({ dropdownContent, providerInfo }: Props): React.ReactElement =>
const { close, open, toggle } = useOpenHandler();

return (
<Grid component="header" container className={classes.summary}>
<Grid component="header" container className={classes.container}>
<Grid item xs={2}>
<Link className={classes.link} to="/">
<Img alt="Gnosis Safe Multisig Logo" height={36} src={SafeLogo} />
Expand All @@ -64,7 +64,7 @@ const Layout = ({ dropdownContent, providerInfo }: Props): React.ReactElement =>
info={providerInfo}
open={open}
toggle={toggle}
render={(providerRef: React.MutableRefObject<HTMLElement | null>) => (
render={(providerRef: React.MutableRefObject<HTMLDivElement | null>) => (
<Popper
anchorEl={providerRef.current}
className={classes.popper}
Expand All @@ -81,7 +81,7 @@ const Layout = ({ dropdownContent, providerInfo }: Props): React.ReactElement =>
direction="column"
alignItems="center"
justify="space-between"
className={classes.root}
className={classes.dropdownContainer}
>
{dropdownContent}
</Grid>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { createStyles, makeStyles } from '@material-ui/core/styles';
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import ExpandLess from '@material-ui/icons/ExpandLess';
import ExpandMore from '@material-ui/icons/ExpandMore';
import IconButton from '@material-ui/core/IconButton';
import * as React from 'react';

import { Divider } from 'src/components/Layout/Divider';
import { screenSm, sm } from 'src/styles/variables';

const styles = createStyles({
const useStyles = makeStyles({
root: {
alignItems: 'center',
display: 'flex',
Expand Down Expand Up @@ -35,22 +35,20 @@ const styles = createStyles({
},
});

const useStyles = makeStyles(styles);

type ProviderProps = {
toggle: () => void;
type Props = {
info: React.ReactNode;
open: boolean;
info: React.ReactElement;
render: (ref: React.MutableRefObject<HTMLElement | null>) => React.ReactElement;
toggle: () => void;
render: (ref: React.MutableRefObject<HTMLDivElement | null>) => React.ReactNode;
};

const Provider = ({ render, info, open, toggle }: ProviderProps): React.ReactElement => {
const Provider = ({ render, info, open, toggle }: Props): React.ReactElement => {
const classes = useStyles();
const providerRef = React.useRef<HTMLDivElement>(null);
const containerRef = React.useRef<HTMLDivElement | null>(null);

return (
<>
<div className={classes.root} ref={providerRef}>
<div className={classes.root} ref={containerRef}>
<Divider />
<div className={classes.provider} onClick={toggle}>
{info}
Expand All @@ -60,9 +58,9 @@ const Provider = ({ render, info, open, toggle }: ProviderProps): React.ReactEle
</div>
<Divider />
</div>
{render(providerRef)}
{render(containerRef)}
</>
);
};

export default Provider;
export { Provider };
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const styles = createStyles({
padding: `${md} 12px`,
},
identicon: {
padding: `${md} 0`,
margin: `${md} 0`,
},
user: {
borderRadius: '3px',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import styled from 'styled-components';
import { Identicon } from 'src/components/Identicon';
import { textShortener } from 'src/utils/strings';

type Props = {
network: string;
safeAddress: string;
};

const Container = styled.div`
display: flex;
align-items: center;
flex-direction: column;
`;

const SafeHeader = ({ network, safeAddress }: Props): React.ReactElement => {
return (
<Container>
<p>{network}</p>
<Identicon size={40} address={safeAddress} />
<p>{textShortener(safeAddress, 6, 4)}</p>
</Container>
);
};

export { SafeHeader };
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 82 additions & 0 deletions packages/safe-apps-developer-ui/src/components/Sidebar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import React from 'react';
import { useParams, NavLink, NavLinkProps, useRouteMatch } from 'react-router-dom';
import styled from 'styled-components';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import { ETHEREUM_NETWORK_TO_ID } from 'src/api/provider';
import { useProviderStore } from 'src/stores/provider';
import { upperFirst } from 'src/utils/strings';
import { connected, headerHeight, sm } from 'src/styles/variables';
import { SafeHeader } from './SafeHeader';
import ÅppsIcon from './apps.svg';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Å


const SidebarContainer = styled.aside`
width: 200px;
height: calc(100vh - ${headerHeight});
background-color: white;
border-right: ${(props) => `2px solid ${props.theme.colors.separator}`};
padding: ${sm};

display: flex;
flex-direction: column;
`;

const Line = styled.hr`
width: 100%;
background-color: ${(props) => props.theme.colors.separator};
height: 2px;
border: none;
`;

interface ListItemLinkProps {
icon?: React.ReactElement;
primary: string;
to: string;
}

// https://material-ui.com/ru/guides/composition/#list
const ListItemLink = (props: ListItemLinkProps): React.ReactElement => {
const { icon, primary, to } = props;

const renderLink = React.useMemo(
() =>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
React.forwardRef<any, Omit<NavLinkProps, 'to'>>((itemProps, ref) => (
<NavLink activeStyle={{ color: connected }} to={to} ref={ref} {...itemProps} />
)),
[to],
);

return (
<li>
<ListItem button component={renderLink}>
{icon ? <ListItemIcon>{icon}</ListItemIcon> : null}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case you feel like changing it
{icon && <ListItemIcon>{icon}</ListItemIcon>}

<ListItemText primary={primary} />
</ListItem>
</li>
);
};

const Sidebar = (): React.ReactElement => {
const networkId = useProviderStore((state) => state.networkId);
const params = useParams<{ safeAddress: string }>();
const { url } = useRouteMatch();

return (
<SidebarContainer>
<SafeHeader network={upperFirst(ETHEREUM_NETWORK_TO_ID[networkId])} safeAddress={params.safeAddress} />
<Line />
<List component="nav" aria-label="main safe features navigation">
<ListItemLink
to={`${url}/apps`}
primary="Apps"
icon={<img src={ÅppsIcon} alt="Apps Icon" style={{ width: 24, fill: '#5D7274' }} />}
/>
</List>
</SidebarContainer>
);
};

export { Sidebar };
Loading