diff --git a/admin/src/components/Home/index.tsx b/admin/src/components/Home/index.tsx index e0845089..66ebb62a 100644 --- a/admin/src/components/Home/index.tsx +++ b/admin/src/components/Home/index.tsx @@ -32,7 +32,7 @@ class Home extends React.Component {
There are {proposalNoArbiterCount}{' '} live proposals without an arbiter.{' '} - + Click here {' '} to view them. @@ -42,14 +42,16 @@ class Home extends React.Component {
There are{' '} {proposalMilestonePayoutsCount} proposals with approved payouts.{' '} - Click here to view - them. + + Click here + {' '} + to view them.
), !!contributionRefundableCount && (
- There are {contributionRefundableCount}{' '} - contributions ready to be refunded.{' '} + There are{' '} + {contributionRefundableCount} contributions ready to be refunded.{' '} Click here to view them.
), diff --git a/admin/src/components/ProposalDetail/index.tsx b/admin/src/components/ProposalDetail/index.tsx index 2067569f..977ad24b 100644 --- a/admin/src/components/ProposalDetail/index.tsx +++ b/admin/src/components/ProposalDetail/index.tsx @@ -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 { return m.datePaid ? prev - parseFloat(m.payoutPercent) : prev; }, 100); - const renderDeleteControl = () => ( - - - - ); - const renderCancelControl = () => { const disabled = this.getCancelAndRefundDisabled(); @@ -392,7 +380,8 @@ class ProposalDetailNaked extends React.Component { {renderNominatedArbiter()} {renderMilestoneAccepted()} {renderFailed()} - + + {p.brief} @@ -401,6 +390,27 @@ class ProposalDetailNaked extends React.Component { + + { + p.milestones.map((milestone, i) => + + + {milestone.title + ' '} + {milestone.immediatePayout && Immediate Payout} + + } + extra={`${milestone.payoutPercent}% Payout`} + key={i} + > +

Estimated Date: {formatDateSeconds(milestone.dateEstimated )}

+

{milestone.content}

+
+ + ) + } +
+
{JSON.stringify(p, null, 4)}
@@ -411,7 +421,6 @@ class ProposalDetailNaked extends React.Component { {/* ACTIONS */} - {renderDeleteControl()} {renderCancelControl()} {renderArbiterControl()} {renderBountyControl()} @@ -507,11 +516,6 @@ class ProposalDetailNaked extends React.Component { store.fetchProposalDetail(this.getIdFromQuery()); }; - private handleDelete = () => { - if (!store.proposalDetail) return; - store.deleteProposal(store.proposalDetail.proposalId); - }; - private handleCancelCancel = () => { this.setState({ showCancelAndRefundPopover: false }); }; diff --git a/admin/src/types.ts b/admin/src/types.ts index f7eee8af..72f75e63 100644 --- a/admin/src/types.ts +++ b/admin/src/types.ts @@ -87,6 +87,7 @@ export enum PROPOSAL_STAGE { COMPLETED = 'COMPLETED', FAILED = 'FAILED', CANCELED = 'CANCELED', + NOT_CANCELED = 'NOT_CANCELED', } export interface Proposal { proposalId: number; diff --git a/admin/src/util/statuses.ts b/admin/src/util/statuses.ts index 71cce6d7..967fffa8 100644 --- a/admin/src/util/statuses.ts +++ b/admin/src/util/statuses.ts @@ -12,6 +12,7 @@ export interface StatusSoT { tagDisplay: string; tagColor: string; hint: string; + not?: boolean; } export const MILESTONE_STAGES: Array> = [ @@ -131,6 +132,13 @@ export const PROPOSAL_STAGES: Array> = [ 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> = [ diff --git a/admin/webpack.config.js b/admin/webpack.config.js index 4e0cfc30..12dbca31 100644 --- a/admin/webpack.config.js +++ b/admin/webpack.config.js @@ -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', diff --git a/backend/grant/admin/views.py b/backend/grant/admin/views.py index a9aba16b..44ba82b8 100644 --- a/backend/grant/admin/views.py +++ b/backend/grant/admin/views.py @@ -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 diff --git a/backend/grant/utils/pagination.py b/backend/grant/utils/pagination.py index 5ce0935f..65022eda 100644 --- a/backend/grant/utils/pagination.py +++ b/backend/grant/utils/pagination.py @@ -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)