Moar bugs (#379)
* #376 fix milestone passed to milestone_paid email * #374 fix admin contribution PUT/POST status validation * #373 fix updates & contributors tabs of Proposal
This commit is contained in:
parent
0e979dc77c
commit
1d07997a7a
|
@ -37,6 +37,7 @@ class FakeUpdate(object):
|
||||||
|
|
||||||
user = FakeUser()
|
user = FakeUser()
|
||||||
proposal = FakeProposal()
|
proposal = FakeProposal()
|
||||||
|
milestone = FakeMilestone()
|
||||||
contribution = FakeContribution()
|
contribution = FakeContribution()
|
||||||
update = FakeUpdate()
|
update = FakeUpdate()
|
||||||
|
|
||||||
|
@ -160,6 +161,7 @@ example_email_args = {
|
||||||
},
|
},
|
||||||
'milestone_paid': {
|
'milestone_paid': {
|
||||||
'proposal': proposal,
|
'proposal': proposal,
|
||||||
|
'milestone': milestone,
|
||||||
'amount': '33',
|
'amount': '33',
|
||||||
'tx_explorer_url': 'http://someblockexplorer.com/tx/271857129857192579125',
|
'tx_explorer_url': 'http://someblockexplorer.com/tx/271857129857192579125',
|
||||||
'proposal_milestones_url': 'http://zfnd.org/proposals/999-my-proposal?tab=milestones',
|
'proposal_milestones_url': 'http://zfnd.org/proposals/999-my-proposal?tab=milestones',
|
||||||
|
|
|
@ -432,6 +432,7 @@ def paid_milestone_payout_request(id, mid, tx_id):
|
||||||
for member in proposal.team:
|
for member in proposal.team:
|
||||||
send_email(member.email_address, 'milestone_paid', {
|
send_email(member.email_address, 'milestone_paid', {
|
||||||
'proposal': proposal,
|
'proposal': proposal,
|
||||||
|
'milestone': ms,
|
||||||
'amount': amount,
|
'amount': amount,
|
||||||
'tx_explorer_url': f'{EXPLORER_URL}transactions/{tx_id}',
|
'tx_explorer_url': f'{EXPLORER_URL}transactions/{tx_id}',
|
||||||
'proposal_milestones_url': make_url(f'/proposals/{proposal.id}?tab=milestones'),
|
'proposal_milestones_url': make_url(f'/proposals/{proposal.id}?tab=milestones'),
|
||||||
|
@ -568,7 +569,7 @@ def get_contributions(page, filters, search, sort):
|
||||||
@body({
|
@body({
|
||||||
"proposalId": fields.Int(required=True),
|
"proposalId": fields.Int(required=True),
|
||||||
"userId": fields.Int(required=True),
|
"userId": fields.Int(required=True),
|
||||||
"status": fields.Str(required=True, validate=validate.OneOf(choices=RFPStatus.list())),
|
"status": fields.Str(required=True, validate=validate.OneOf(choices=ContributionStatus.list())),
|
||||||
"amount": fields.Str(required=True),
|
"amount": fields.Str(required=True),
|
||||||
"txId": fields.Str(required=False, missing=None)
|
"txId": fields.Str(required=False, missing=None)
|
||||||
})
|
})
|
||||||
|
@ -607,7 +608,7 @@ def get_contribution(contribution_id):
|
||||||
@body({
|
@body({
|
||||||
"proposalId": fields.Int(required=False, missing=None),
|
"proposalId": fields.Int(required=False, missing=None),
|
||||||
"userId": fields.Int(required=False, missing=None),
|
"userId": fields.Int(required=False, missing=None),
|
||||||
"status": fields.Str(required=True, validate=validate.OneOf(choices=RFPStatus.list())),
|
"status": fields.Str(required=True, validate=validate.OneOf(choices=ContributionStatus.list())),
|
||||||
"amount": fields.Str(required=False, missing=None),
|
"amount": fields.Str(required=False, missing=None),
|
||||||
"txId": fields.Str(required=False, missing=None),
|
"txId": fields.Str(required=False, missing=None),
|
||||||
"refundTxId": fields.Str(required=False, allow_none=True, missing=None),
|
"refundTxId": fields.Str(required=False, allow_none=True, missing=None),
|
||||||
|
|
|
@ -269,7 +269,7 @@ def milestone_accept(email_args):
|
||||||
def milestone_paid(email_args):
|
def milestone_paid(email_args):
|
||||||
p = email_args['proposal']
|
p = email_args['proposal']
|
||||||
a = email_args['amount']
|
a = email_args['amount']
|
||||||
ms = p.current_milestone
|
ms = email_args['milestone']
|
||||||
return {
|
return {
|
||||||
'subject': f'{p.title} - {ms.title} has been paid!',
|
'subject': f'{p.title} - {ms.title} has been paid!',
|
||||||
'title': f'Milestone paid',
|
'title': f'Milestone paid',
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<p style="margin: 0 0 20px;">
|
<p style="margin: 0 0 20px;">
|
||||||
Hooray! <b>{{ args.amount }} ZEC</b> has been paid out for
|
Hooray! <b>{{ args.amount }} ZEC</b> has been paid out for
|
||||||
<a href="{{ args.proposal_milestones_url }}" target="_blank">
|
<a href="{{ args.proposal_milestones_url }}" target="_blank">
|
||||||
{{ args.proposal.title }} - {{ args.proposal.current_milestone.title }}</a
|
{{ args.proposal.title }} - {{ args.milestone.title }}</a
|
||||||
>! You can view the transaction below:
|
>! You can view the transaction below:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Hooray! {{args.amount}} ZEC has been paid out for "{{ args.proposal.title }} - {{args.proposal.current_milestone.title }}"!
|
Hooray! {{args.amount}} ZEC has been paid out for "{{ args.proposal.title }} - {{args.milestone.title }}"!
|
||||||
You can view the transaction below:
|
You can view the transaction below:
|
||||||
|
|
||||||
{{ args.tx_explorer_url }}
|
{{ args.tx_explorer_url }}
|
||||||
|
|
|
@ -10,7 +10,7 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const Placeholder: React.SFC<Props> = ({ style = {}, title, subtitle, loading }) => (
|
const Placeholder: React.SFC<Props> = ({ style = {}, title, subtitle, loading }) => (
|
||||||
<div className={`Placeholder ${!!loading && 'is-loading'}`} style={style}>
|
<div className={`Placeholder${(!!loading && ' is-loading') || ''}`} style={style}>
|
||||||
{(loading && <Loader inline={true} size="small" />) || (
|
{(loading && <Loader inline={true} size="small" />) || (
|
||||||
<>
|
<>
|
||||||
{title && <h3 className="Placeholder-title">{title}</h3>}
|
{title && <h3 className="Placeholder-title">{title}</h3>}
|
||||||
|
|
|
@ -2,23 +2,27 @@
|
||||||
|
|
||||||
.ProposalContributors {
|
.ProposalContributors {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
max-width: 880px;
|
||||||
|
|
||||||
@media @mobile-query {
|
@media @mobile-query {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Placeholder {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
&-block {
|
&-block {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
margin: 1rem;
|
margin: 1rem;
|
||||||
background: #FFF;
|
background: #fff;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1),
|
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(0, 0, 0, 0.1);
|
||||||
0 1px 1px rgba(0, 0, 0, 0.1);
|
|
||||||
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { connect } from 'react-redux';
|
||||||
import UserRow from 'components/UserRow';
|
import UserRow from 'components/UserRow';
|
||||||
import Placeholder from 'components/Placeholder';
|
import Placeholder from 'components/Placeholder';
|
||||||
import UnitDisplay from 'components/UnitDisplay';
|
import UnitDisplay from 'components/UnitDisplay';
|
||||||
import Loader from 'components/Loader';
|
|
||||||
import { toZat } from 'utils/units';
|
import { toZat } from 'utils/units';
|
||||||
import { fetchProposalContributions } from 'modules/proposals/actions';
|
import { fetchProposalContributions } from 'modules/proposals/actions';
|
||||||
import {
|
import {
|
||||||
|
@ -54,20 +53,26 @@ class ProposalContributors extends React.Component<Props> {
|
||||||
<div className="ProposalContributors-block-contributor" key={c.id}>
|
<div className="ProposalContributors-block-contributor" key={c.id}>
|
||||||
<UserRow
|
<UserRow
|
||||||
user={c.user}
|
user={c.user}
|
||||||
extra={<>+<UnitDisplay value={toZat(c.amount)} symbol="ZEC" /></>}
|
extra={
|
||||||
|
<>
|
||||||
|
+<UnitDisplay value={toZat(c.amount)} symbol="ZEC" />
|
||||||
|
</>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
content = <>
|
content = (
|
||||||
<div className="ProposalContributors-block">
|
<>
|
||||||
<h3 className="ProposalContributors-block-title">Latest contributors</h3>
|
<div className="ProposalContributors-block">
|
||||||
{contributions.latest.map(makeContributionRow)}
|
<h3 className="ProposalContributors-block-title">Latest contributors</h3>
|
||||||
</div>
|
{contributions.latest.map(makeContributionRow)}
|
||||||
<div className="ProposalContributors-block">
|
</div>
|
||||||
<h3 className="ProposalContributors-block-title">Top contributors</h3>
|
<div className="ProposalContributors-block">
|
||||||
{contributions.top.map(makeContributionRow)}
|
<h3 className="ProposalContributors-block-title">Top contributors</h3>
|
||||||
</div>
|
{contributions.top.map(makeContributionRow)}
|
||||||
</>;
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
content = (
|
content = (
|
||||||
<Placeholder
|
<Placeholder
|
||||||
|
@ -81,18 +86,16 @@ class ProposalContributors extends React.Component<Props> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (fetchContributionsError) {
|
} else if (fetchContributionsError) {
|
||||||
content = <Placeholder title="Something went wrong" subtitle={fetchContributionsError} />;
|
content = (
|
||||||
|
<Placeholder title="Something went wrong" subtitle={fetchContributionsError} />
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
content = <Loader />;
|
content = <Placeholder loading={true} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return <div className="ProposalContributors">{content}</div>;
|
||||||
<div className="ProposalContributors">
|
|
||||||
{content}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
(state: AppState, ownProps: OwnProps) => ({
|
(state: AppState, ownProps: OwnProps) => ({
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import Loader from 'components/Loader';
|
|
||||||
import Markdown from 'components/Markdown';
|
import Markdown from 'components/Markdown';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import Placeholder from 'components/Placeholder';
|
import Placeholder from 'components/Placeholder';
|
||||||
|
@ -58,7 +57,7 @@ class ProposalUpdates extends React.Component<Props, State> {
|
||||||
let content = null;
|
let content = null;
|
||||||
|
|
||||||
if (isFetchingUpdates) {
|
if (isFetchingUpdates) {
|
||||||
content = <Loader />;
|
content = <Placeholder loading={true} />;
|
||||||
} else if (updatesError) {
|
} else if (updatesError) {
|
||||||
content = <Placeholder title="Something went wrong" subtitle={updatesError} />;
|
content = <Placeholder title="Something went wrong" subtitle={updatesError} />;
|
||||||
} else if (updates) {
|
} else if (updates) {
|
||||||
|
|
Loading…
Reference in New Issue