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

Upgrade app structure #41

Merged
merged 29 commits into from
Feb 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0095d4e
chore(packages): Update aragon packages
Feb 25, 2020
3fd66de
feat(proposals): Migrate proposals data view to another comp
Feb 25, 2020
8809133
feat(logic): Separate app login in another file
Feb 25, 2020
8d9b722
feat: App now uses appLogic and accepts darkmode
Feb 25, 2020
b6839f3
feat(proposals): Add no proposals component
Feb 25, 2020
f9d43bb
feat(detail): Add proposal detail page
Feb 25, 2020
8078c4b
feat(app): Update app logic to render new components
Feb 25, 2020
ba7c801
feat(selected): selectedProposal func formats id type to number
Feb 25, 2020
45ecbff
feat(logic): All app logic is separated in another file, app-logic
Feb 27, 2020
c9796dc
feat(addProposal): Add description field and submit validation
Feb 27, 2020
92641cb
feat(filter): Add filter hooks
Feb 27, 2020
2e1ab2d
feat: Move web3-utils to a single file
Feb 27, 2020
3ea7ab9
feat(selectedProposal): Move useSelectedProposal to it's own hook file
Feb 27, 2020
718b7e8
feat(proposals): Add filter, update UI and make all components functi…
Feb 27, 2020
b42dc97
feat(detail): Add more info and fix UI according to figma
Feb 27, 2020
ef5c33e
feat(app): Comp only passes state/logic as props
Feb 27, 2020
d9d33cf
fix(packages): Update libraries in correct package.json
Feb 27, 2020
f8b1e22
fix(addProposal): Remove description field so new proposal is added t…
Feb 27, 2020
44805e9
feat: Change expression support -> vote
Feb 27, 2020
01cb48e
feat(detail): Add 'vote for this proposal' btn in ProposalDetail
Feb 27, 2020
7ce2950
feat(proposals): Add description to dataview and fix layout details
Feb 27, 2020
4366822
feat(share): Add share btn to proposal detail page
Feb 27, 2020
5146cca
feat(detail): Fixes proposal detail page layout
Feb 27, 2020
cfb975f
fix(description): Remove description field from everywhere
Feb 27, 2020
2388b02
feat(data view): Add proposals title and fix filter name
Feb 27, 2020
5023a4c
feat(detail): Add conviction bar to proposal detail page
Feb 27, 2020
d71e184
feat(balance): Update balance token layout
Feb 27, 2020
2d0098c
feat(new proposal): Side panel appears even without proposals
Feb 27, 2020
7504b8d
feat(no proposal): Remove NoProposal screen and stay with default fro…
Feb 27, 2020
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
6 changes: 3 additions & 3 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
"version": "1.0.0",
"main": "src/index.js",
"dependencies": {
"@aragon/api": "^2.0.0-beta.7",
"@aragon/api-react": "^2.0.0-beta.6",
"@aragon/ui": "^1.0.0-alpha.26",
"@aragon/api": "^2.0.0-beta.9",
"@aragon/api-react": "^2.0.0-beta.9",
"@aragon/ui": "^1.3.1",
"core-js": "^3.1.4",
"react": "^16.8.6",
"react-dom": "^16.8.6",
Expand Down
226 changes: 83 additions & 143 deletions app/src/App.js
Original file line number Diff line number Diff line change
@@ -1,164 +1,104 @@
import React, { useState } from 'react'
import { useAragonApi } from '@aragon/api-react'
import React, { useCallback } from 'react'
import { useGuiStyle, useAppState } from '@aragon/api-react'
import {
Main,
Button,
SidePanel,
Box,
DataView,
useTheme,
Text,
Tag,
SyncIndicator,
IconPlus,
Header,
GU,
useLayout,
} from '@aragon/ui'
import styled from 'styled-components'
import AppHeader from './components/AppHeader'
import Balance from './components/Balance'
import ProposalDetail from './components/ProposalDetail'

import ProposalDetail from './screens/ProposalDetail'
import Proposals from './screens/Proposals'
import AddProposalPanel from './components/AddProposalPanel'
import { ConvictionBar, ConvictionTrend } from './components/ConvictionVisuals'
import { toDecimals } from './lib/math-utils'
import { toHex } from 'web3-utils'
// import ProposalDetail from './components/ProposalDetail'

function App() {
const { api, appState, connectedAccount } = useAragonApi()
const { proposals, convictionStakes, requestToken } = appState
const activeProposals = proposals.filter(({ executed }) => !executed)
import useAppLogic from './app-logic'
import useFilterProposals from './hooks/useFilterProposals'
import useSelectedProposal from './hooks/useSelectedProposal'

const [proposalPanel, setProposalPanel] = useState(false)
const onProposalSubmit = ({ title, link, amount, beneficiary }) => {
const decimals = parseInt(requestToken.decimals)
const decimalAmount = toDecimals(amount.trim(), decimals).toString()
api.addProposal(title, toHex(link), decimalAmount, beneficiary).toPromise()
setProposalPanel(false)
}
const Layout = styled.div`
display: flex;
justify-content: center;
margin-top: ${2.5 * GU}px;
`

const myStakes =
(convictionStakes &&
convictionStakes.filter(({ entity }) => entity === connectedAccount)) ||
[]
const App = React.memo(function App() {
const { setProposalPanel, proposalPanel, onProposalSubmit } = useAppLogic()

const myLastStake = [...myStakes].pop() || {}
const { proposals = [], isSyncing, requestToken } = useAppState()

return (
<Main assetsUrl="./aragon-ui">
<>
<AppHeader
heading="Conviction Voting"
action1={
<Button
mode="strong"
label="New proposal"
onClick={() => setProposalPanel(true)}
>
New proposal
</Button>
}
/>
<Wrapper>
<div css="width: 25%; margin-right: 1rem;">
<Box heading="Vault balance">
<Balance {...requestToken} />
</Box>
{myLastStake.tokensStaked > 0 && (
<Box heading="My staked proposal" key={myLastStake.proposal}>
<ProposalInfo
proposal={
proposals.filter(({ id }) => id === myLastStake.proposal)[0]
}
stake={myLastStake}
/>
</Box>
)}
</div>
<div css="width: 75%">
<DataView
fields={[
{ label: 'Proposal', priority: 1 },
{ label: 'Requested', priority: 4 },
{ label: 'Conviction progress', priority: 2 },
{ label: 'Trend', priority: 5 },
]}
entries={activeProposals}
renderEntry={proposal => [
<IdAndTitle {...proposal} />,
<Amount {...proposal} />,
<ConvictionBar proposal={proposal} />,
<ConvictionTrend proposal={proposal} />,
]}
renderEntryExpansion={proposal => (
<ProposalDetail
proposal={proposal}
onStake={() =>
api.stakeAllToProposal(proposal.id).toPromise()
}
onWithdraw={() =>
api.withdrawAllFromProposal(proposal.id).toPromise()
}
onExecute={() =>
api.executeProposal(proposal.id, true).toPromise()
}
/>
)}
/>
</div>
</Wrapper>
<SidePanel
title="New proposal"
opened={proposalPanel}
onClose={() => setProposalPanel(false)}
>
<AddProposalPanel onSubmit={onProposalSubmit} />
</SidePanel>
</>
</Main>
)
}
const { layoutName } = useLayout()
const compactMode = layoutName === 'small'

const IdAndTitle = ({ id, name }) => {
const theme = useTheme()
return (
<div>
<Text color={theme.surfaceContent.toString()}>#{id}</Text>{' '}
<Text color={theme.surfaceContentSecondary.toString()}>{name}</Text>
</div>
)
}
const [selectedProposal, selectProposal] = useSelectedProposal(proposals)
const handleBack = useCallback(() => selectProposal(-1), [selectProposal])

const Amount = ({ requestedAmount = 0 }) => {
const {
appState: {
requestToken: { symbol, decimals, verified },
},
} = useAragonApi()
filteredProposals,
proposalStatusFilter,
handleProposalStatusFilterChange,
} = useFilterProposals(proposals)

return (
<div>
<Balance
amount={requestedAmount}
decimals={decimals}
symbol={symbol}
verified={verified}
/>
</div>
<Layout size={layoutName}>
<div
css={`
width: ${layoutName !== 'small' ? '75%' : '100%'};
`}
>
<SyncIndicator visible={isSyncing} />
<Header
primary="Conviction Voting"
secondary={
!selectedProposal && (
<Button
mode="strong"
onClick={() => setProposalPanel(true)}
label="New proposal"
icon={<IconPlus />}
display={compactMode ? 'icon' : 'label'}
/>
)
}
/>
{selectedProposal ? (
<ProposalDetail
proposal={selectedProposal}
onBack={handleBack}
requestToken={requestToken}
/>
) : (
<Proposals
proposals={proposals}
selectProposal={selectProposal}
filteredProposals={filteredProposals}
proposalStatusFilter={proposalStatusFilter}
handleProposalStatusFilterChange={handleProposalStatusFilterChange}
requestToken={requestToken}
/>
)}
</div>
<SidePanel
title="New proposal"
opened={proposalPanel}
onClose={() => setProposalPanel(false)}
>
<AddProposalPanel onSubmit={onProposalSubmit} />
</SidePanel>
</Layout>
)
}
})

const ProposalInfo = ({ proposal, stake }) => {
const {
appState: {
stakeToken: { tokenSymbol },
},
} = useAragonApi()
export default () => {
const { appearance } = useGuiStyle()
return (
<div>
<IdAndTitle {...proposal} />
<Tag>{`✓ Supported with ${stake.tokensStaked} ${tokenSymbol}`}</Tag>
<ConvictionBar proposal={proposal} />
</div>
<Main layout={false} theme={appearance} assetsUrl="./aragon-ui">
<App />
</Main>
)
}

const Wrapper = styled.div`
display: flex;
`

export default App
57 changes: 57 additions & 0 deletions app/src/app-logic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { useState } from 'react'
import { useAragonApi, useAppState } from '@aragon/api-react'
// import usePanelState from './hooks/usePanelState'
// import { noop } from './utils'
import { toDecimals } from './lib/math-utils'
import { toHex } from 'web3-utils'

// // Create a new proposal
// export function useCreateProposalAction(onDone = noop) {
// const api = useApi()
// return useCallback(
// title => {
// if (api) {
// // Don't care about response
// api['newProposal(string)'](title).toPromise()
// onDone()
// }
// },
// [api, onDone]
// )
// }

// Handles the main logic of the app.
export default function useAppLogic() {
const { api, connectedAccount } = useAragonApi()
const { requestToken, convictionStakes } = useAppState()

const [proposalPanel, setProposalPanel] = useState(false)

const onProposalSubmit = ({ title, link, amount, beneficiary }) => {
const decimals = parseInt(requestToken.decimals)
const decimalAmount = toDecimals(amount.trim(), decimals).toString()
api.addProposal(title, toHex(link), decimalAmount, beneficiary).toPromise()
setProposalPanel(false)
}

const myStakes =
(convictionStakes &&
convictionStakes.filter(({ entity }) => entity === connectedAccount)) ||
[]

const myLastStake = [...myStakes].pop() || []
// const newProposalPanel = usePanelState()

// const actions = {
// createProposal: useCreateProposalAction(newProposalPanel.requestClose),
// }

return {
// actions,
// newProposalPanel,
onProposalSubmit,
proposalPanel,
setProposalPanel,
myLastStake,
}
}
Binary file added app/src/assets/no-proposals.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading