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 = () => (
-
-
- Delete
-
-
- );
-
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)