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:
AMStrix 2019-03-14 22:26:28 -05:00 committed by Daniel Ternyak
parent 0e979dc77c
commit 1d07997a7a
9 changed files with 42 additions and 33 deletions

View File

@ -37,6 +37,7 @@ class FakeUpdate(object):
user = FakeUser()
proposal = FakeProposal()
milestone = FakeMilestone()
contribution = FakeContribution()
update = FakeUpdate()
@ -160,6 +161,7 @@ example_email_args = {
},
'milestone_paid': {
'proposal': proposal,
'milestone': milestone,
'amount': '33',
'tx_explorer_url': 'http://someblockexplorer.com/tx/271857129857192579125',
'proposal_milestones_url': 'http://zfnd.org/proposals/999-my-proposal?tab=milestones',

View File

@ -432,6 +432,7 @@ def paid_milestone_payout_request(id, mid, tx_id):
for member in proposal.team:
send_email(member.email_address, 'milestone_paid', {
'proposal': proposal,
'milestone': ms,
'amount': amount,
'tx_explorer_url': f'{EXPLORER_URL}transactions/{tx_id}',
'proposal_milestones_url': make_url(f'/proposals/{proposal.id}?tab=milestones'),
@ -568,7 +569,7 @@ def get_contributions(page, filters, search, sort):
@body({
"proposalId": 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),
"txId": fields.Str(required=False, missing=None)
})
@ -607,7 +608,7 @@ def get_contribution(contribution_id):
@body({
"proposalId": 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),
"txId": fields.Str(required=False, missing=None),
"refundTxId": fields.Str(required=False, allow_none=True, missing=None),

View File

@ -269,7 +269,7 @@ def milestone_accept(email_args):
def milestone_paid(email_args):
p = email_args['proposal']
a = email_args['amount']
ms = p.current_milestone
ms = email_args['milestone']
return {
'subject': f'{p.title} - {ms.title} has been paid!',
'title': f'Milestone paid',

View File

@ -1,7 +1,7 @@
<p style="margin: 0 0 20px;">
Hooray! <b>{{ args.amount }} ZEC</b> has been paid out for
<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:
</p>

View File

@ -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:
{{ args.tx_explorer_url }}

View File

@ -10,7 +10,7 @@ interface Props {
}
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" />) || (
<>
{title && <h3 className="Placeholder-title">{title}</h3>}

View File

@ -2,23 +2,27 @@
.ProposalContributors {
display: flex;
max-width: 880px;
@media @mobile-query {
flex-direction: column;
}
.Placeholder {
flex-grow: 1;
}
&-block {
flex: 1;
padding: 1.5rem;
margin: 1rem;
background: #FFF;
background: #fff;
border-radius: 4px;
border: 1px solid #ddd;
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1),
0 1px 1px 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);
&:first-child {
margin-left: 0;
margin-left: 0;
}
&:last-child {
margin-right: 0;

View File

@ -3,7 +3,6 @@ import { connect } from 'react-redux';
import UserRow from 'components/UserRow';
import Placeholder from 'components/Placeholder';
import UnitDisplay from 'components/UnitDisplay';
import Loader from 'components/Loader';
import { toZat } from 'utils/units';
import { fetchProposalContributions } from 'modules/proposals/actions';
import {
@ -54,20 +53,26 @@ class ProposalContributors extends React.Component<Props> {
<div className="ProposalContributors-block-contributor" key={c.id}>
<UserRow
user={c.user}
extra={<>+<UnitDisplay value={toZat(c.amount)} symbol="ZEC" /></>}
extra={
<>
+<UnitDisplay value={toZat(c.amount)} symbol="ZEC" />
</>
}
/>
</div>
)
content = <>
<div className="ProposalContributors-block">
<h3 className="ProposalContributors-block-title">Latest contributors</h3>
{contributions.latest.map(makeContributionRow)}
</div>
<div className="ProposalContributors-block">
<h3 className="ProposalContributors-block-title">Top contributors</h3>
{contributions.top.map(makeContributionRow)}
</div>
</>;
);
content = (
<>
<div className="ProposalContributors-block">
<h3 className="ProposalContributors-block-title">Latest contributors</h3>
{contributions.latest.map(makeContributionRow)}
</div>
<div className="ProposalContributors-block">
<h3 className="ProposalContributors-block-title">Top contributors</h3>
{contributions.top.map(makeContributionRow)}
</div>
</>
);
} else {
content = (
<Placeholder
@ -81,18 +86,16 @@ class ProposalContributors extends React.Component<Props> {
);
}
} else if (fetchContributionsError) {
content = <Placeholder title="Something went wrong" subtitle={fetchContributionsError} />;
content = (
<Placeholder title="Something went wrong" subtitle={fetchContributionsError} />
);
} else {
content = <Loader />;
content = <Placeholder loading={true} />;
}
return (
<div className="ProposalContributors">
{content}
</div>
);
return <div className="ProposalContributors">{content}</div>;
}
};
}
export default connect(
(state: AppState, ownProps: OwnProps) => ({

View File

@ -1,6 +1,5 @@
import React from 'react';
import { connect } from 'react-redux';
import Loader from 'components/Loader';
import Markdown from 'components/Markdown';
import moment from 'moment';
import Placeholder from 'components/Placeholder';
@ -58,7 +57,7 @@ class ProposalUpdates extends React.Component<Props, State> {
let content = null;
if (isFetchingUpdates) {
content = <Loader />;
content = <Placeholder loading={true} />;
} else if (updatesError) {
content = <Placeholder title="Something went wrong" subtitle={updatesError} />;
} else if (updates) {