Merge pull request #443 from ZcashFoundation/develop

Release 1.3.2
This commit is contained in:
Daniel Ternyak 2019-05-28 16:34:32 -06:00 committed by GitHub
commit b34ee977d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 49 additions and 28 deletions

View File

@ -32,7 +32,7 @@ class Home extends React.Component {
<div>
<Icon type="exclamation-circle" /> There are <b>{proposalNoArbiterCount}</b>{' '}
live proposals <b>without an arbiter</b>.{' '}
<Link to="/proposals?filters[]=STATUS_LIVE&filters[]=ARBITER_MISSING">
<Link to="/proposals?filters[]=STATUS_LIVE&filters[]=ARBITER_MISSING&filters[]=STAGE_NOT_CANCELED">
Click here
</Link>{' '}
to view them.
@ -42,14 +42,16 @@ class Home extends React.Component {
<div>
<Icon type="exclamation-circle" /> There are{' '}
<b>{proposalMilestonePayoutsCount}</b> proposals <b>with approved payouts</b>.{' '}
<Link to="/proposals?filters[]=MILESTONE_ACCEPTED">Click here</Link> to view
them.
<Link to="/proposals?filters[]=MILESTONE_ACCEPTED&filters[]=STAGE_NOT_CANCELED">
Click here
</Link>{' '}
to view them.
</div>
),
!!contributionRefundableCount && (
<div>
<Icon type="exclamation-circle" /> There are <b>{contributionRefundableCount}</b>{' '}
contributions <b>ready to be refunded</b>.{' '}
<Icon type="exclamation-circle" /> There are{' '}
<b>{contributionRefundableCount}</b> contributions <b>ready to be refunded</b>.{' '}
<Link to="/contributions?filters[]=REFUNDABLE">Click here</Link> to view them.
</div>
),

View File

@ -12,6 +12,7 @@ import {
Popconfirm,
Input,
Switch,
Tag,
message,
} from 'antd';
import TextArea from 'antd/lib/input/TextArea';
@ -64,19 +65,6 @@ class ProposalDetailNaked extends React.Component<Props, State> {
return m.datePaid ? prev - parseFloat(m.payoutPercent) : prev;
}, 100);
const renderDeleteControl = () => (
<Popconfirm
onConfirm={this.handleDelete}
title="Delete proposal?"
okText="delete"
cancelText="cancel"
>
<Button icon="delete" className="ProposalDetail-controls-control" block>
Delete
</Button>
</Popconfirm>
);
const renderCancelControl = () => {
const disabled = this.getCancelAndRefundDisabled();
@ -392,7 +380,8 @@ class ProposalDetailNaked extends React.Component<Props, State> {
{renderNominatedArbiter()}
{renderMilestoneAccepted()}
{renderFailed()}
<Collapse defaultActiveKey={['brief', 'content']}>
<Collapse defaultActiveKey={['brief', 'content', 'milestones']}>
<Collapse.Panel key="brief" header="brief">
{p.brief}
</Collapse.Panel>
@ -401,6 +390,27 @@ class ProposalDetailNaked extends React.Component<Props, State> {
<Markdown source={p.content} />
</Collapse.Panel>
<Collapse.Panel key="milestones" header="milestones">
{
p.milestones.map((milestone, i) =>
<Card title={
<>
{milestone.title + ' '}
{milestone.immediatePayout && <Tag color="magenta">Immediate Payout</Tag>}
</>
}
extra={`${milestone.payoutPercent}% Payout`}
key={i}
>
<p><b>Estimated Date:</b> {formatDateSeconds(milestone.dateEstimated )} </p>
<p>{milestone.content}</p>
</Card>
)
}
</Collapse.Panel>
<Collapse.Panel key="json" header="json">
<pre>{JSON.stringify(p, null, 4)}</pre>
</Collapse.Panel>
@ -411,7 +421,6 @@ class ProposalDetailNaked extends React.Component<Props, State> {
<Col span={6}>
{/* ACTIONS */}
<Card size="small" className="ProposalDetail-controls">
{renderDeleteControl()}
{renderCancelControl()}
{renderArbiterControl()}
{renderBountyControl()}
@ -507,11 +516,6 @@ class ProposalDetailNaked extends React.Component<Props, State> {
store.fetchProposalDetail(this.getIdFromQuery());
};
private handleDelete = () => {
if (!store.proposalDetail) return;
store.deleteProposal(store.proposalDetail.proposalId);
};
private handleCancelCancel = () => {
this.setState({ showCancelAndRefundPopover: false });
};

View File

@ -87,6 +87,7 @@ export enum PROPOSAL_STAGE {
COMPLETED = 'COMPLETED',
FAILED = 'FAILED',
CANCELED = 'CANCELED',
NOT_CANCELED = 'NOT_CANCELED',
}
export interface Proposal {
proposalId: number;

View File

@ -12,6 +12,7 @@ export interface StatusSoT<E> {
tagDisplay: string;
tagColor: string;
hint: string;
not?: boolean;
}
export const MILESTONE_STAGES: Array<StatusSoT<MILESTONE_STAGE>> = [
@ -131,6 +132,13 @@ export const PROPOSAL_STAGES: Array<StatusSoT<PROPOSAL_STAGE>> = [
hint:
'Proposal was canceled by an admin and is currently refunding all contributors.',
},
{
id: PROPOSAL_STAGE.NOT_CANCELED,
tagDisplay: 'NOT Canceled',
tagColor: '#eb4118',
hint: 'Proposal has NOT been canceled.',
not: true,
},
];
export const PROPOSAL_ARBITER_STATUSES: Array<StatusSoT<PROPOSAL_ARBITER_STATUS>> = [

View File

@ -18,7 +18,7 @@ module.exports = {
publicPath: '/',
chunkFilename: isDev ? '[name].chunk.js' : '[name].[chunkhash:8].chunk.js',
},
devtool: 'inline-source-map',
devtool: isDev ? 'inline-source-map' : 'source-map',
devServer: {
port: 3500,
contentBase: './build',

View File

@ -149,6 +149,7 @@ def stats():
proposal_milestone_payouts_count = db.session.query(func.count(Proposal.id)) \
.join(Proposal.milestones) \
.filter(Proposal.status == ProposalStatus.LIVE) \
.filter(Proposal.stage != ProposalStage.CANCELED) \
.filter(Milestone.stage == MilestoneStage.ACCEPTED) \
.scalar()
# Count contributions on proposals that didn't get funded for users who have specified a refund address

View File

@ -10,7 +10,9 @@ from .enums import ProposalStatus, ProposalStage, Category, ContributionStatus,
def extract_filters(sw, strings):
return [f[len(sw):] for f in strings if f.startswith(sw)]
filters = [f[len(sw):] for f in strings if f.startswith(sw)]
filters = [f for f in filters if not f.startswith('NOT_')]
return filters
class PaginationException(Exception):
@ -52,6 +54,7 @@ class ProposalPagination(Pagination):
def __init__(self):
self.FILTERS = [f'STATUS_{s}' for s in ProposalStatus.list()]
self.FILTERS.extend([f'STAGE_{s}' for s in ProposalStage.list()])
self.FILTERS.extend([f'STAGE_NOT_{s}' for s in ProposalStage.list()])
self.FILTERS.extend([f'CAT_{c}' for c in Category.list()])
self.FILTERS.extend([f'ARBITER_{c}' for c in ProposalArbiterStatus.list()])
self.FILTERS.extend([f'MILESTONE_{c}' for c in MilestoneStage.list()])
@ -80,6 +83,7 @@ class ProposalPagination(Pagination):
self.validate_filters(filters)
status_filters = extract_filters('STATUS_', filters)
stage_filters = extract_filters('STAGE_', filters)
stage_not_filters = extract_filters('STAGE_NOT_', filters, )
cat_filters = extract_filters('CAT_', filters)
arbiter_filters = extract_filters('ARBITER_', filters)
milestone_filters = extract_filters('MILESTONE_', filters)
@ -88,6 +92,8 @@ class ProposalPagination(Pagination):
query = query.filter(Proposal.status.in_(status_filters))
if stage_filters:
query = query.filter(Proposal.stage.in_(stage_filters))
if stage_not_filters:
query = query.filter(Proposal.stage.notin_(stage_not_filters))
if cat_filters:
query = query.filter(Proposal.category.in_(cat_filters))
if arbiter_filters:
@ -177,7 +183,6 @@ class ContributionPagination(Pagination):
Proposal.stage == ProposalStage.CANCELED,
))
# SORT (see self.SORT_MAP)
if sort:
self.validate_sort(sort)