Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into add-current-account
Browse files Browse the repository at this point in the history
* origin/master:
  App Center (#625)
  • Loading branch information
2color committed Apr 15, 2019
2 parents a0a4d28 + 533c308 commit a18a993
Show file tree
Hide file tree
Showing 62 changed files with 1,892 additions and 407 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -26,7 +26,7 @@
"dependencies": {
"@aragon/templates-tokens": "^1.1.1",
"@aragon/ui": "^0.33.0",
"@aragon/wrapper": "^4.0.0",
"@aragon/wrapper": "^5.0.0-beta.1",
"@babel/polyfill": "^7.0.0",
"bn.js": "4.11.6",
"date-fns": "2.0.0-alpha.22",
Expand Down
62 changes: 46 additions & 16 deletions src/App.js
Expand Up @@ -28,15 +28,23 @@ import {
DAO_CREATION_STATUS_ERROR,
} from './symbols'

const INITIAL_DAO_STATE = {
apps: [],
appIdentifiers: {},
appsStatus: APPS_STATUS_LOADING,
daoAddress: { address: '', domain: '' },
permissions: {},
permissionsLoading: true,
repos: [],
}

class App extends React.Component {
state = {
...INITIAL_DAO_STATE,
account: '',
apps: [],
appsStatus: APPS_STATUS_LOADING,
balance: getUnknownBalance(),
buildData: null, // data returned by aragon.js when a DAO is created
connected: false,
daoAddress: { address: '', domain: '' },
// daoCreationStatus is one of:
// - DAO_CREATION_STATUS_NONE
// - DAO_CREATION_STATUS_SUCCESS
Expand All @@ -45,8 +53,6 @@ class App extends React.Component {
fatalError: null,
identityIntent: null,
locator: {},
permissions: {},
permissionsLoading: true,
prevLocator: null,
selectorNetworks: [
['main', 'Ethereum Mainnet', 'https://mainnet.aragon.org/'],
Expand Down Expand Up @@ -193,19 +199,20 @@ class App extends React.Component {

updateDao(dao = null) {
// Cancel the subscriptions / unload the wrapper
if (dao === null && this.state.wrapper) {
if (this.state.wrapper) {
this.state.wrapper.cancel()
this.setState({ wrapper: null })
return
}

// Reset the DAO state
this.setState({
appsStatus: APPS_STATUS_LOADING,
apps: [],
daoAddress: { address: '', domain: '' },
...INITIAL_DAO_STATE,
})

if (dao === null) {
return
}

log('Init DAO', dao)
initWrapper(dao, contractAddresses.ensRegistry, {
provider: web3Providers.default,
Expand Down Expand Up @@ -239,6 +246,14 @@ class App extends React.Component {
onForwarders: forwarders => {
log('forwarders', forwarders)
},
onAppIdentifiers: appIdentifiers => {
log('app identifiers', appIdentifiers)
this.setState({ appIdentifiers })
},
onInstalledRepos: repos => {
log('installed repos', repos)
this.setState({ repos })
},
onTransaction: transactionBag => {
log('transaction bag', transactionBag)
this.setState({ transactionBag })
Expand Down Expand Up @@ -325,6 +340,7 @@ class App extends React.Component {
const {
account,
apps,
appIdentifiers,
appsStatus,
balance,
connected,
Expand All @@ -335,6 +351,7 @@ class App extends React.Component {
locator,
permissions,
permissionsLoading,
repos,
selectorNetworks,
showDeprecatedBanner,
transactionBag,
Expand All @@ -345,18 +362,30 @@ class App extends React.Component {
} = this.state

const { mode, dao } = locator
if (!mode) return null
const { address: intentAddress = null, label: intentLabel = '' } =
identityIntent || {}

if (!mode) {
return null
}
if (mode === 'invalid') {
throw new Error(
`URL contained invalid organization name or address (${dao}).\nPlease modify it to be a valid ENS name or address.`
)
}

if (fatalError !== null) {
throw fatalError
}
const { address: intentAddress = null, label: intentLabel = '' } =
identityIntent || {}

const appsWithIdentifiers = apps.map(app => {
const identifier = appIdentifiers[app.proxyAddress]
return identifier
? {
identifier,
...app,
}
: app
})

return (
<IdentityProvider onResolve={this.handleIdentityResolve}>
Expand All @@ -374,12 +403,12 @@ class App extends React.Component {
<FavoriteDaosProvider>
<PermissionsProvider
wrapper={wrapper}
apps={apps}
apps={appsWithIdentifiers}
permissions={permissions}
>
<Wrapper
account={account}
apps={apps}
apps={appsWithIdentifiers}
appsStatus={appsStatus}
banner={
showDeprecatedBanner && <DeprecatedBanner dao={dao} />
Expand All @@ -393,6 +422,7 @@ class App extends React.Component {
onRequestAppsReload={this.handleRequestAppsReload}
onRequestEnable={this.handleRequestEnable}
permissionsLoading={permissionsLoading}
repos={repos}
transactionBag={transactionBag}
walletNetwork={walletNetwork}
walletWeb3={walletWeb3}
Expand Down
118 changes: 69 additions & 49 deletions src/Wrapper.js
@@ -1,8 +1,9 @@
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import memoize from 'lodash.memoize'
import { Viewport } from '@aragon/ui'
import { Apps, Permissions, Settings } from './apps'
import { AppCenter, Permissions, Settings } from './apps'
import AppIFrame from './components/App/AppIFrame'
import App404 from './components/App404/App404'
import Home from './components/Home/Home'
Expand All @@ -18,9 +19,9 @@ import {
AragonType,
DaoAddressType,
EthereumAddressType,
RepoType,
} from './prop-types'
import { getAppPath } from './routing'
import { staticApps } from './static-apps'
import { APPS_STATUS_LOADING } from './symbols'
import { addressesEqual } from './web3-utils'
import ethereumLoadingAnimation from './assets/ethereum-loading.svg'
Expand All @@ -30,6 +31,7 @@ class Wrapper extends React.PureComponent {
account: EthereumAddressType,
apps: PropTypes.arrayOf(AppType).isRequired,
appsStatus: AppsStatusType.isRequired,
autoClosingPanel: PropTypes.bool.isRequired,
banner: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.shape({
Expand All @@ -44,7 +46,7 @@ class Wrapper extends React.PureComponent {
onRequestAppsReload: PropTypes.func.isRequired,
onRequestEnable: PropTypes.func.isRequired,
permissionsLoading: PropTypes.bool.isRequired,
autoClosingPanel: PropTypes.bool.isRequired,
repos: PropTypes.arrayOf(RepoType).isRequired,
transactionBag: PropTypes.object,
walletNetwork: PropTypes.string,
walletProviderId: PropTypes.string,
Expand All @@ -63,7 +65,6 @@ class Wrapper extends React.PureComponent {
}

state = {
appInstance: {},
menuPanelOpened: !this.props.autoClosingPanel,
preferencesOpened: false,
notificationOpen: false,
Expand Down Expand Up @@ -113,11 +114,16 @@ class Wrapper extends React.PureComponent {
wrapper,
locator: { instanceId },
} = this.props
if (
!wrapper ||
!apps.find(app => addressesEqual(app.proxyAddress, instanceId))
) {
console.error('The app cannot be connected to aragon.js')
if (!wrapper) {
console.error(
`Attempted to connect app (${instanceId}) before aragonAPI was ready`
)
return
}
if (!apps.find(app => addressesEqual(app.proxyAddress, instanceId))) {
console.error(
`The requested app (${instanceId}) could not be found in the installed apps`
)
return
}

Expand Down Expand Up @@ -176,13 +182,44 @@ class Wrapper extends React.PureComponent {
}
}

isAppInstalled(instanceId) {
const { apps } = this.props
return (
staticApps.has(instanceId) &&
!!apps.find(app => addressesEqual(app.proxyAddress, instanceId))
)
}
getAppInstancesGroups = memoize(apps =>
apps.reduce((groups, app) => {
const group = groups.find(({ appId }) => appId === app.appId)

const {
// This is not technically fully true, but let's assume that only these
// aspects be different between multiple instances of the same app
codeAddress: instanceCodeAddress,
identifier: instanceIdentifier,
proxyAddress: instanceProxyAddress,
...sharedAppInfo
} = app

const instance = {
codeAddress: instanceCodeAddress,
identifier: instanceIdentifier,
instanceId: instanceProxyAddress,
proxyAddress: instanceProxyAddress,
}

// Append the instance to the existing app group
if (group) {
group.instances.push(instance)
return groups
}

return groups.concat([
{
app: sharedAppInfo,
appId: app.appId,
name: app.name,
instances: [instance],
hasWebApp: app.hasWebApp,
repoName: app.appName,
},
])
}, [])
)

render() {
const {
Expand Down Expand Up @@ -212,7 +249,7 @@ class Wrapper extends React.PureComponent {
return (
<Main>
<Preferences
locator={locator}
dao={locator.dao}
opened={preferencesOpened}
onClose={this.handleClosePreferences}
wrapper={wrapper}
Expand All @@ -229,6 +266,7 @@ class Wrapper extends React.PureComponent {
<MenuPanel
account={account}
apps={apps.filter(app => app.hasWebApp)}
appInstanceGroups={this.getAppInstancesGroups(apps)}
appsStatus={appsStatus}
activeInstanceId={locator.instanceId}
connected={connected}
Expand Down Expand Up @@ -258,41 +296,12 @@ class Wrapper extends React.PureComponent {
<SignerPanel
account={account}
apps={apps}
locator={locator}
dao={locator.dao}
onRequestEnable={onRequestEnable}
transactionBag={transactionBag}
walletNetwork={walletNetwork}
walletProviderId={walletProviderId}
walletWeb3={walletWeb3}
onTransactionSuccess={({ data, name, description, identifier }) =>
this.setState(state => ({
queuedNotifications: [
{
id: data,
type: 'transaction',
title: `${name} ${identifier}`,
content: description,
},
...state.queuedNotifications,
],
}))
}
onClose={() => {
if (this.state.queuedNotifications.length) {
// Wait a little, then update notifications
setTimeout(
() =>
this.setState(state => ({
queuedNotifications: [],
notifications: [
...state.queuedNotifications,
...state.notifications,
],
})),
250
)
}
}}
/>
</Main>
)
Expand All @@ -306,20 +315,22 @@ class Wrapper extends React.PureComponent {
daoAddress,
locator,
permissionsLoading,
repos,
walletNetwork,
walletWeb3,
wrapper,
} = this.props

const appsLoading = appsStatus === APPS_STATUS_LOADING
const reposLoading = appsLoading || (apps.length && !repos.length)

if (instanceId === 'home') {
return (
<Home
apps={apps}
appsLoading={appsLoading}
connected={connected}
locator={locator}
dao={locator.dao}
onMessage={this.handleAppMessage}
onOpenApp={this.openApp}
/>
Expand All @@ -340,7 +351,16 @@ class Wrapper extends React.PureComponent {
}

if (instanceId === 'apps') {
return <Apps onMessage={this.handleAppMessage} />
return (
<AppCenter
appInstanceGroups={this.getAppInstancesGroups(apps)}
params={params}
repos={repos}
reposLoading={reposLoading}
onMessage={this.handleAppMessage}
onParamsRequest={this.handleParamsRequest}
/>
)
}

if (instanceId === 'settings') {
Expand Down

0 comments on commit a18a993

Please sign in to comment.