setup 'FUNDING BY ZOMG'
This commit is contained in:
parent
1a38eea631
commit
7f065b4163
|
@ -0,0 +1,32 @@
|
||||||
|
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||||
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||||
|
|
||||||
|
name: Node.js CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [12.x]
|
||||||
|
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- run: cd frontend && yarn && && yarn run lint && yarn run tsc
|
|
@ -0,0 +1,32 @@
|
||||||
|
# This workflow will install Python dependencies, run tests and lint with a single version of Python
|
||||||
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||||
|
|
||||||
|
name: Python application
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up Python 3.7
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.7
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
cd backend && pip install -r requirements/dev.txt
|
||||||
|
- name: Test with flask test
|
||||||
|
run: |
|
||||||
|
cd backend && cp .env.example .env && flask test
|
|
@ -2,27 +2,11 @@ import React from 'react';
|
||||||
import BN from 'bn.js';
|
import BN from 'bn.js';
|
||||||
import { view } from 'react-easy-state';
|
import { view } from 'react-easy-state';
|
||||||
import { RouteComponentProps, withRouter } from 'react-router';
|
import { RouteComponentProps, withRouter } from 'react-router';
|
||||||
import {
|
import { Alert, Button, Card, Col, Collapse, Input, message, Popconfirm, Row, Switch, Tag } from 'antd';
|
||||||
Alert,
|
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
Col,
|
|
||||||
Collapse,
|
|
||||||
Input,
|
|
||||||
message,
|
|
||||||
Popconfirm,
|
|
||||||
Row,
|
|
||||||
Tag,
|
|
||||||
} from 'antd';
|
|
||||||
import TextArea from 'antd/lib/input/TextArea';
|
import TextArea from 'antd/lib/input/TextArea';
|
||||||
import store from 'src/store';
|
import store from 'src/store';
|
||||||
import { formatDateSeconds, formatDurationSeconds } from 'util/time';
|
import { formatDateSeconds, formatDurationSeconds } from 'util/time';
|
||||||
import {
|
import { MILESTONE_STAGE, PROPOSAL_ARBITER_STATUS, PROPOSAL_STAGE, PROPOSAL_STATUS } from 'src/types';
|
||||||
MILESTONE_STAGE,
|
|
||||||
PROPOSAL_ARBITER_STATUS,
|
|
||||||
PROPOSAL_STAGE,
|
|
||||||
PROPOSAL_STATUS,
|
|
||||||
} from 'src/types';
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import Back from 'components/Back';
|
import Back from 'components/Back';
|
||||||
import Markdown from 'components/Markdown';
|
import Markdown from 'components/Markdown';
|
||||||
|
@ -30,6 +14,7 @@ import ArbiterControl from 'components/ArbiterControl';
|
||||||
import { fromZat, toZat } from 'src/util/units';
|
import { fromZat, toZat } from 'src/util/units';
|
||||||
import FeedbackModal from '../FeedbackModal';
|
import FeedbackModal from '../FeedbackModal';
|
||||||
import { formatUsd } from 'util/formatters';
|
import { formatUsd } from 'util/formatters';
|
||||||
|
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
|
||||||
type Props = RouteComponentProps<any>;
|
type Props = RouteComponentProps<any>;
|
||||||
|
@ -58,6 +43,8 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
return 'loading proposal...';
|
return 'loading proposal...';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(p.fundedByZomg);
|
||||||
|
|
||||||
const needsArbiter =
|
const needsArbiter =
|
||||||
PROPOSAL_ARBITER_STATUS.MISSING === p.arbiter.status &&
|
PROPOSAL_ARBITER_STATUS.MISSING === p.arbiter.status &&
|
||||||
p.status === PROPOSAL_STATUS.LIVE &&
|
p.status === PROPOSAL_STATUS.LIVE &&
|
||||||
|
@ -94,9 +81,9 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
</p>
|
</p>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
placement="left"
|
placement='left'
|
||||||
cancelText="cancel"
|
cancelText='cancel'
|
||||||
okText="confirm"
|
okText='confirm'
|
||||||
visible={this.state.showCancelAndRefundPopover}
|
visible={this.state.showCancelAndRefundPopover}
|
||||||
okButtonProps={{
|
okButtonProps={{
|
||||||
loading: store.proposalDetailCanceling,
|
loading: store.proposalDetailCanceling,
|
||||||
|
@ -105,8 +92,8 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
onConfirm={this.handleConfirmCancel}
|
onConfirm={this.handleConfirmCancel}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
icon="close-circle"
|
icon='close-circle'
|
||||||
className="ProposalDetail-controls-control"
|
className='ProposalDetail-controls-control'
|
||||||
loading={store.proposalDetailCanceling}
|
loading={store.proposalDetailCanceling}
|
||||||
onClick={this.handleCancelAndRefundClick}
|
onClick={this.handleCancelAndRefundClick}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
@ -128,9 +115,9 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
with funding? This cannot be undone.
|
with funding? This cannot be undone.
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
placement="left"
|
placement='left'
|
||||||
cancelText="cancel"
|
cancelText='cancel'
|
||||||
okText="confirm"
|
okText='confirm'
|
||||||
visible={this.state.showChangeToAcceptedWithFundingPopover}
|
visible={this.state.showChangeToAcceptedWithFundingPopover}
|
||||||
okButtonProps={{
|
okButtonProps={{
|
||||||
loading: store.proposalDetailCanceling,
|
loading: store.proposalDetailCanceling,
|
||||||
|
@ -139,8 +126,8 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
onConfirm={this.handleChangeToAcceptWithFundingConfirm}
|
onConfirm={this.handleChangeToAcceptWithFundingConfirm}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
icon="close-circle"
|
icon='close-circle'
|
||||||
className="ProposalDetail-controls-control"
|
className='ProposalDetail-controls-control'
|
||||||
loading={store.proposalDetailChangingToAcceptedWithFunding}
|
loading={store.proposalDetailChangingToAcceptedWithFunding}
|
||||||
onClick={this.handleChangeToAcceptedWithFunding}
|
onClick={this.handleChangeToAcceptedWithFunding}
|
||||||
block
|
block
|
||||||
|
@ -170,7 +157,7 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
p.status === PROPOSAL_STATUS.APPROVED && (
|
p.status === PROPOSAL_STATUS.APPROVED && (
|
||||||
<Alert
|
<Alert
|
||||||
showIcon
|
showIcon
|
||||||
type="success"
|
type='success'
|
||||||
message={`Approved on ${formatDateSeconds(p.dateApproved)}`}
|
message={`Approved on ${formatDateSeconds(p.dateApproved)}`}
|
||||||
description={`
|
description={`
|
||||||
This proposal has been approved and will become live when a team-member
|
This proposal has been approved and will become live when a team-member
|
||||||
|
@ -206,25 +193,25 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
<Col span={isVersionTwo ? 16 : 24}>
|
<Col span={isVersionTwo ? 16 : 24}>
|
||||||
<Alert
|
<Alert
|
||||||
showIcon
|
showIcon
|
||||||
type="warning"
|
type='warning'
|
||||||
message="Review Discussion"
|
message='Review Discussion'
|
||||||
description={
|
description={
|
||||||
<div>
|
<div>
|
||||||
<p>Please review this proposal and render your judgment.</p>
|
<p>Please review this proposal and render your judgment.</p>
|
||||||
<Button
|
<Button
|
||||||
className="ProposalDetail-review"
|
className='ProposalDetail-review'
|
||||||
loading={store.proposalDetailApprovingDiscussion}
|
loading={store.proposalDetailApprovingDiscussion}
|
||||||
icon="check"
|
icon='check'
|
||||||
type="primary"
|
type='primary'
|
||||||
onClick={() => this.handleApproveDiscussion()}
|
onClick={() => this.handleApproveDiscussion()}
|
||||||
>
|
>
|
||||||
Open for Public Review
|
Open for Public Review
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
className="ProposalDetail-review"
|
className='ProposalDetail-review'
|
||||||
loading={store.proposalDetailApprovingDiscussion}
|
loading={store.proposalDetailApprovingDiscussion}
|
||||||
icon="warning"
|
icon='warning'
|
||||||
type="default"
|
type='default'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
FeedbackModal.open({
|
FeedbackModal.open({
|
||||||
title: 'Request changes to this proposal?',
|
title: 'Request changes to this proposal?',
|
||||||
|
@ -237,10 +224,10 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
Request Changes
|
Request Changes
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
className="ProposalDetail-review"
|
className='ProposalDetail-review'
|
||||||
loading={store.proposalDetailRejectingPermanently}
|
loading={store.proposalDetailRejectingPermanently}
|
||||||
icon="close"
|
icon='close'
|
||||||
type="danger"
|
type='danger'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
FeedbackModal.open({
|
FeedbackModal.open({
|
||||||
title: 'Reject this proposal permanently?',
|
title: 'Reject this proposal permanently?',
|
||||||
|
@ -269,27 +256,27 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
<Col span={isVersionTwo ? 16 : 24}>
|
<Col span={isVersionTwo ? 16 : 24}>
|
||||||
<Alert
|
<Alert
|
||||||
showIcon
|
showIcon
|
||||||
type="warning"
|
type='warning'
|
||||||
message="Review Pending"
|
message='Review Pending'
|
||||||
description={
|
description={
|
||||||
<div>
|
<div>
|
||||||
<p>Please review this proposal and render your judgment.</p>
|
<p>Please review this proposal and render your judgment.</p>
|
||||||
|
|
||||||
<>
|
<>
|
||||||
<Button
|
<Button
|
||||||
className="ProposalDetail-review"
|
className='ProposalDetail-review'
|
||||||
loading={store.proposalDetailAcceptingProposal}
|
loading={store.proposalDetailAcceptingProposal}
|
||||||
icon="check"
|
icon='check'
|
||||||
type="primary"
|
type='primary'
|
||||||
onClick={() => this.handleAcceptProposal(true, true)}
|
onClick={() => this.handleAcceptProposal(true, true)}
|
||||||
>
|
>
|
||||||
Approve With Funding
|
Approve With Funding
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
className="ProposalDetail-review"
|
className='ProposalDetail-review'
|
||||||
loading={store.proposalDetailAcceptingProposal}
|
loading={store.proposalDetailAcceptingProposal}
|
||||||
icon="check"
|
icon='check'
|
||||||
type="default"
|
type='default'
|
||||||
onClick={() => this.handleAcceptProposal(true, false)}
|
onClick={() => this.handleAcceptProposal(true, false)}
|
||||||
>
|
>
|
||||||
Approve Without Funding
|
Approve Without Funding
|
||||||
|
@ -297,10 +284,10 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
</>
|
</>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="ProposalDetail-review"
|
className='ProposalDetail-review'
|
||||||
loading={store.proposalDetailMarkingChangesAsResolved}
|
loading={store.proposalDetailMarkingChangesAsResolved}
|
||||||
icon="close"
|
icon='close'
|
||||||
type="danger"
|
type='danger'
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
FeedbackModal.open({
|
FeedbackModal.open({
|
||||||
title: 'Request changes to this proposal?',
|
title: 'Request changes to this proposal?',
|
||||||
|
@ -325,8 +312,8 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
p.status === PROPOSAL_STATUS.REJECTED && (
|
p.status === PROPOSAL_STATUS.REJECTED && (
|
||||||
<Alert
|
<Alert
|
||||||
showIcon
|
showIcon
|
||||||
type="error"
|
type='error'
|
||||||
message="Changes requested"
|
message='Changes requested'
|
||||||
description={
|
description={
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
|
@ -346,8 +333,8 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
p.changesRequestedDiscussion && (
|
p.changesRequestedDiscussion && (
|
||||||
<Alert
|
<Alert
|
||||||
showIcon
|
showIcon
|
||||||
type="error"
|
type='error'
|
||||||
message="Changes requested"
|
message='Changes requested'
|
||||||
description={
|
description={
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
|
@ -360,10 +347,10 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
<br />
|
<br />
|
||||||
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||||
<Button
|
<Button
|
||||||
className="ProposalDetail-review"
|
className='ProposalDetail-review'
|
||||||
loading={false}
|
loading={false}
|
||||||
icon="check"
|
icon='check'
|
||||||
type="danger"
|
type='danger'
|
||||||
onClick={this.handleMarkChangesAsResolved}
|
onClick={this.handleMarkChangesAsResolved}
|
||||||
>
|
>
|
||||||
Mark Request as Resolved
|
Mark Request as Resolved
|
||||||
|
@ -381,8 +368,8 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
{!p.kycApproved ? (
|
{!p.kycApproved ? (
|
||||||
<Alert
|
<Alert
|
||||||
showIcon
|
showIcon
|
||||||
type="error"
|
type='error'
|
||||||
message="KYC approval required"
|
message='KYC approval required'
|
||||||
description={
|
description={
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
|
@ -390,10 +377,10 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
with payouts.
|
with payouts.
|
||||||
</p>
|
</p>
|
||||||
<Button
|
<Button
|
||||||
className="ProposalDetail-review"
|
className='ProposalDetail-review'
|
||||||
loading={store.proposalDetailApprovingKyc}
|
loading={store.proposalDetailApprovingKyc}
|
||||||
icon="check"
|
icon='check'
|
||||||
type="primary"
|
type='primary'
|
||||||
onClick={() => this.handleApproveKYC()}
|
onClick={() => this.handleApproveKYC()}
|
||||||
>
|
>
|
||||||
KYC Approved
|
KYC Approved
|
||||||
|
@ -404,8 +391,8 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
) : (
|
) : (
|
||||||
<Alert
|
<Alert
|
||||||
showIcon
|
showIcon
|
||||||
type="warning"
|
type='warning'
|
||||||
message="No arbiter on live proposal"
|
message='No arbiter on live proposal'
|
||||||
description={
|
description={
|
||||||
<div>
|
<div>
|
||||||
<p>An arbiter is required to review milestone payout requests.</p>
|
<p>An arbiter is required to review milestone payout requests.</p>
|
||||||
|
@ -422,8 +409,8 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
p.status === PROPOSAL_STATUS.LIVE && (
|
p.status === PROPOSAL_STATUS.LIVE && (
|
||||||
<Alert
|
<Alert
|
||||||
showIcon
|
showIcon
|
||||||
type="info"
|
type='info'
|
||||||
message="Arbiter has been nominated"
|
message='Arbiter has been nominated'
|
||||||
description={
|
description={
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p>
|
||||||
|
@ -469,9 +456,9 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Alert
|
<Alert
|
||||||
className="ProposalDetail-alert"
|
className='ProposalDetail-alert'
|
||||||
showIcon
|
showIcon
|
||||||
type="warning"
|
type='warning'
|
||||||
message={null}
|
message={null}
|
||||||
description={
|
description={
|
||||||
<div>
|
<div>
|
||||||
|
@ -487,9 +474,9 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
</p>{' '}
|
</p>{' '}
|
||||||
<pre>{p.payoutAddress}</pre>
|
<pre>{p.payoutAddress}</pre>
|
||||||
<Input.Search
|
<Input.Search
|
||||||
placeholder="please enter payment txid"
|
placeholder='please enter payment txid'
|
||||||
value={this.state.paidTxId}
|
value={this.state.paidTxId}
|
||||||
enterButton="Mark Paid"
|
enterButton='Mark Paid'
|
||||||
onChange={e => this.setState({ paidTxId: e.target.value })}
|
onChange={e => this.setState({ paidTxId: e.target.value })}
|
||||||
onSearch={this.handlePaidMilestone}
|
onSearch={this.handlePaidMilestone}
|
||||||
/>
|
/>
|
||||||
|
@ -503,7 +490,7 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
p.isFailed && (
|
p.isFailed && (
|
||||||
<Alert
|
<Alert
|
||||||
showIcon
|
showIcon
|
||||||
type="error"
|
type='error'
|
||||||
message={
|
message={
|
||||||
p.stage === PROPOSAL_STAGE.FAILED ? 'Proposal failed' : 'Proposal canceled'
|
p.stage === PROPOSAL_STAGE.FAILED ? 'Proposal failed' : 'Proposal canceled'
|
||||||
}
|
}
|
||||||
|
@ -525,17 +512,16 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderDeetItem = (name: string, val: any) => (
|
const renderDeetItem = (name: string, val: any) => (
|
||||||
<div className="ProposalDetail-deet">
|
<div className='ProposalDetail-deet'>
|
||||||
<span>{name}</span>
|
<span>{name}</span>
|
||||||
{val}
|
{val}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(p);
|
// @ts-ignore
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ProposalDetail">
|
<div className='ProposalDetail'>
|
||||||
<Back to="/proposals" text="Proposals" />
|
<Back to='/proposals' text='Proposals' />
|
||||||
<h1>{p.title}</h1>
|
<h1>{p.title}</h1>
|
||||||
<Row gutter={16}>
|
<Row gutter={16}>
|
||||||
{/* MAIN */}
|
{/* MAIN */}
|
||||||
|
@ -550,22 +536,22 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
{renderMilestoneAccepted()}
|
{renderMilestoneAccepted()}
|
||||||
{renderFailed()}
|
{renderFailed()}
|
||||||
<Collapse defaultActiveKey={['brief', 'content', 'milestones']}>
|
<Collapse defaultActiveKey={['brief', 'content', 'milestones']}>
|
||||||
<Collapse.Panel key="brief" header="brief">
|
<Collapse.Panel key='brief' header='brief'>
|
||||||
{p.brief}
|
{p.brief}
|
||||||
</Collapse.Panel>
|
</Collapse.Panel>
|
||||||
|
|
||||||
<Collapse.Panel key="content" header="content">
|
<Collapse.Panel key='content' header='content'>
|
||||||
<Markdown source={p.content} />
|
<Markdown source={p.content} />
|
||||||
</Collapse.Panel>
|
</Collapse.Panel>
|
||||||
|
|
||||||
<Collapse.Panel key="milestones" header="milestones">
|
<Collapse.Panel key='milestones' header='milestones'>
|
||||||
{p.milestones.map((milestone, i) => (
|
{p.milestones.map((milestone, i) => (
|
||||||
<Card
|
<Card
|
||||||
title={
|
title={
|
||||||
<>
|
<>
|
||||||
{milestone.title + ' '}
|
{milestone.title + ' '}
|
||||||
{milestone.immediatePayout && (
|
{milestone.immediatePayout && (
|
||||||
<Tag color="magenta">Immediate Payout</Tag>
|
<Tag color='magenta'>Immediate Payout</Tag>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
@ -590,7 +576,7 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
))}
|
))}
|
||||||
</Collapse.Panel>
|
</Collapse.Panel>
|
||||||
|
|
||||||
<Collapse.Panel key="json" header="json">
|
<Collapse.Panel key='json' header='json'>
|
||||||
<pre>{JSON.stringify(p, null, 4)}</pre>
|
<pre>{JSON.stringify(p, null, 4)}</pre>
|
||||||
</Collapse.Panel>
|
</Collapse.Panel>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
|
@ -602,23 +588,35 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
!p.acceptedWithFunding &&
|
!p.acceptedWithFunding &&
|
||||||
p.stage === PROPOSAL_STAGE.WIP && (
|
p.stage === PROPOSAL_STAGE.WIP && (
|
||||||
<Alert
|
<Alert
|
||||||
message="Accepted without funding"
|
message='Accepted without funding'
|
||||||
description="This proposal has been posted publicly, but isn't being funded by the Zcash Foundation."
|
description="This proposal has been posted publicly, but isn't being funded by the Zcash Foundation."
|
||||||
type="info"
|
type='info'
|
||||||
showIcon
|
showIcon
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ACTIONS */}
|
{/* ACTIONS */}
|
||||||
<Card size="small" className="ProposalDetail-controls">
|
<Card size='small' className='ProposalDetail-controls'>
|
||||||
{renderCancelControl()}
|
{renderCancelControl()}
|
||||||
{renderArbiterControl()}
|
{renderArbiterControl()}
|
||||||
|
|
||||||
|
{
|
||||||
|
p.acceptedWithFunding &&
|
||||||
|
<div style={{ marginTop: '10px' }}>
|
||||||
|
<Switch checkedChildren='Funded by ZOMG'
|
||||||
|
unCheckedChildren='Funded by ZF'
|
||||||
|
onChange={this.handleSwitchFunder}
|
||||||
|
loading={store.proposalDetailSwitchingFunder}
|
||||||
|
checked={p.fundedByZomg} />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
{shouldShowChangeToAcceptedWithFunding &&
|
{shouldShowChangeToAcceptedWithFunding &&
|
||||||
renderChangeToAcceptedWithFundingControl()}
|
renderChangeToAcceptedWithFundingControl()}
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* DETAILS */}
|
{/* DETAILS */}
|
||||||
<Card title="Details" size="small">
|
<Card title='Details' size='small'>
|
||||||
{renderDeetItem('id', p.proposalId)}
|
{renderDeetItem('id', p.proposalId)}
|
||||||
{renderDeetItem('created', formatDateSeconds(p.dateCreated))}
|
{renderDeetItem('created', formatDateSeconds(p.dateCreated))}
|
||||||
{renderDeetItem(
|
{renderDeetItem(
|
||||||
|
@ -669,7 +667,7 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* TEAM */}
|
{/* TEAM */}
|
||||||
<Card title="Team" size="small">
|
<Card title='Team' size='small'>
|
||||||
{p.team.map(t => (
|
{p.team.map(t => (
|
||||||
<div key={t.userid}>
|
<div key={t.userid}>
|
||||||
<Link to={`/users/${t.userid}`}>{t.displayName}</Link>
|
<Link to={`/users/${t.userid}`}>{t.displayName}</Link>
|
||||||
|
@ -783,6 +781,10 @@ class ProposalDetailNaked extends React.Component<Props, State> {
|
||||||
await store.markMilestonePaid(pid, mid, this.state.paidTxId);
|
await store.markMilestonePaid(pid, mid, this.state.paidTxId);
|
||||||
message.success('Marked milestone paid.');
|
message.success('Marked milestone paid.');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private handleSwitchFunder = async (checkValue: boolean) => {
|
||||||
|
store.switchProposalFunder(checkValue);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const ProposalDetail = withRouter(view(ProposalDetailNaked));
|
const ProposalDetail = withRouter(view(ProposalDetailNaked));
|
||||||
|
|
|
@ -142,6 +142,11 @@ async function approveDiscussion(
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function switchProposalFunder(id: number, fundedByZomg: boolean) {
|
||||||
|
const { data } = await api.put(`/admin/proposals/${id}/adjust-funder`, {fundedByZomg});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
async function approveProposalKYC(id: number) {
|
async function approveProposalKYC(id: number) {
|
||||||
const { data } = await api.put(`/admin/proposals/${id}/approve-kyc`);
|
const { data } = await api.put(`/admin/proposals/${id}/approve-kyc`);
|
||||||
return data;
|
return data;
|
||||||
|
@ -351,6 +356,7 @@ const app = store({
|
||||||
proposalDetailMarkingChangesAsResolved: false,
|
proposalDetailMarkingChangesAsResolved: false,
|
||||||
proposalDetailAcceptingProposal: false,
|
proposalDetailAcceptingProposal: false,
|
||||||
proposalDetailApprovingKyc: false,
|
proposalDetailApprovingKyc: false,
|
||||||
|
proposalDetailSwitchingFunder: false,
|
||||||
proposalDetailMarkingMilestonePaid: false,
|
proposalDetailMarkingMilestonePaid: false,
|
||||||
proposalDetailCanceling: false,
|
proposalDetailCanceling: false,
|
||||||
proposalDetailUpdating: false,
|
proposalDetailUpdating: false,
|
||||||
|
@ -695,6 +701,24 @@ const app = store({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async switchProposalFunder(fundedByZomg: boolean) {
|
||||||
|
if (!app.proposalDetail) {
|
||||||
|
const m = 'store.acceptProposal(): Expected proposalDetail to be populated!';
|
||||||
|
app.generalError.push(m);
|
||||||
|
console.error(m);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
app.proposalDetailSwitchingFunder = true;
|
||||||
|
try {
|
||||||
|
const { proposalId } = app.proposalDetail;
|
||||||
|
const res = await switchProposalFunder(proposalId, fundedByZomg);
|
||||||
|
app.updateProposalInStore(res);
|
||||||
|
} catch (e) {
|
||||||
|
handleApiError(e);
|
||||||
|
}
|
||||||
|
app.proposalDetailSwitchingFunder = false;
|
||||||
|
},
|
||||||
|
|
||||||
async approveProposalKYC() {
|
async approveProposalKYC() {
|
||||||
if (!app.proposalDetail) {
|
if (!app.proposalDetail) {
|
||||||
const m = 'store.acceptProposal(): Expected proposalDetail to be populated!';
|
const m = 'store.acceptProposal(): Expected proposalDetail to be populated!';
|
||||||
|
|
|
@ -124,6 +124,7 @@ export interface Proposal {
|
||||||
changesRequestedDiscussion: boolean | null;
|
changesRequestedDiscussion: boolean | null;
|
||||||
changesRequestedDiscussionReason: string | null;
|
changesRequestedDiscussionReason: string | null;
|
||||||
kycApproved: null | boolean;
|
kycApproved: null | boolean;
|
||||||
|
fundedByZomg: boolean;
|
||||||
}
|
}
|
||||||
export interface Comment {
|
export interface Comment {
|
||||||
id: number;
|
id: number;
|
||||||
|
|
|
@ -4,7 +4,7 @@ from functools import reduce
|
||||||
|
|
||||||
from flask import Blueprint, request
|
from flask import Blueprint, request
|
||||||
from marshmallow import fields, validate
|
from marshmallow import fields, validate
|
||||||
from sqlalchemy import func, or_, text
|
from sqlalchemy import func, text
|
||||||
|
|
||||||
import grant.utils.admin as admin
|
import grant.utils.admin as admin
|
||||||
import grant.utils.auth as auth
|
import grant.utils.auth as auth
|
||||||
|
@ -25,7 +25,7 @@ from grant.proposal.models import (
|
||||||
admin_proposal_contributions_schema,
|
admin_proposal_contributions_schema,
|
||||||
)
|
)
|
||||||
from grant.rfp.models import RFP, admin_rfp_schema, admin_rfps_schema
|
from grant.rfp.models import RFP, admin_rfp_schema, admin_rfps_schema
|
||||||
from grant.user.models import User, UserSettings, admin_users_schema, admin_user_schema
|
from grant.user.models import User, admin_users_schema, admin_user_schema
|
||||||
from grant.utils import pagination
|
from grant.utils import pagination
|
||||||
from grant.utils.enums import (
|
from grant.utils.enums import (
|
||||||
ProposalStatus,
|
ProposalStatus,
|
||||||
|
@ -390,6 +390,22 @@ def approve_proposal_kyc(id):
|
||||||
return proposal_schema.dump(proposal)
|
return proposal_schema.dump(proposal)
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route('/proposals/<id>/adjust-funder', methods=['PUT'])
|
||||||
|
@body({
|
||||||
|
"fundedByZomg": fields.Bool(required=True),
|
||||||
|
})
|
||||||
|
@admin.admin_auth_required
|
||||||
|
def adjust_funder(id, funded_by_zomg):
|
||||||
|
proposal = Proposal.query.get(id)
|
||||||
|
if not proposal:
|
||||||
|
return {"message": "No proposal found."}, 404
|
||||||
|
|
||||||
|
proposal.funded_by_zomg = funded_by_zomg
|
||||||
|
db.session.add(proposal)
|
||||||
|
db.session.commit()
|
||||||
|
return proposal_schema.dump(proposal)
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route('/proposals/<id>/accept', methods=['PUT'])
|
@blueprint.route('/proposals/<id>/accept', methods=['PUT'])
|
||||||
@body({
|
@body({
|
||||||
"isAccepted": fields.Bool(required=True),
|
"isAccepted": fields.Bool(required=True),
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
from typing import Optional
|
|
||||||
from decimal import Decimal, ROUND_DOWN
|
from decimal import Decimal, ROUND_DOWN
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from marshmallow import post_dump
|
from marshmallow import post_dump
|
||||||
from sqlalchemy import func, or_, select, ForeignKey
|
from sqlalchemy import func, or_, select, ForeignKey
|
||||||
|
@ -10,15 +10,14 @@ from sqlalchemy.ext.hybrid import hybrid_property
|
||||||
from sqlalchemy.orm import column_property
|
from sqlalchemy.orm import column_property
|
||||||
|
|
||||||
from grant.comment.models import Comment
|
from grant.comment.models import Comment
|
||||||
from grant.milestone.models import Milestone
|
|
||||||
from grant.email.send import send_email
|
from grant.email.send import send_email
|
||||||
from grant.extensions import ma, db
|
from grant.extensions import ma, db
|
||||||
|
from grant.milestone.models import Milestone
|
||||||
from grant.settings import PROPOSAL_STAKING_AMOUNT, PROPOSAL_TARGET_MAX
|
from grant.settings import PROPOSAL_STAKING_AMOUNT, PROPOSAL_TARGET_MAX
|
||||||
from grant.task.jobs import ContributionExpired
|
from grant.task.jobs import ContributionExpired
|
||||||
from grant.utils.enums import (
|
from grant.utils.enums import (
|
||||||
ProposalStatus,
|
ProposalStatus,
|
||||||
ProposalStage,
|
ProposalStage,
|
||||||
Category,
|
|
||||||
ContributionStatus,
|
ContributionStatus,
|
||||||
ProposalArbiterStatus,
|
ProposalArbiterStatus,
|
||||||
MilestoneStage,
|
MilestoneStage,
|
||||||
|
@ -332,7 +331,8 @@ class ProposalRevision(db.Model):
|
||||||
if old_proposal.title != new_proposal.title:
|
if old_proposal.title != new_proposal.title:
|
||||||
proposal_changes.append({"type": ProposalChange.PROPOSAL_EDIT_TITLE})
|
proposal_changes.append({"type": ProposalChange.PROPOSAL_EDIT_TITLE})
|
||||||
|
|
||||||
milestone_changes = ProposalRevision.calculate_milestone_changes(old_proposal.milestones, new_proposal.milestones)
|
milestone_changes = ProposalRevision.calculate_milestone_changes(old_proposal.milestones,
|
||||||
|
new_proposal.milestones)
|
||||||
|
|
||||||
return proposal_changes + milestone_changes
|
return proposal_changes + milestone_changes
|
||||||
|
|
||||||
|
@ -392,6 +392,7 @@ class Proposal(db.Model):
|
||||||
date_published = db.Column(db.DateTime)
|
date_published = db.Column(db.DateTime)
|
||||||
reject_reason = db.Column(db.String())
|
reject_reason = db.Column(db.String())
|
||||||
kyc_approved = db.Column(db.Boolean(), nullable=True, default=False)
|
kyc_approved = db.Column(db.Boolean(), nullable=True, default=False)
|
||||||
|
funded_by_zomg = db.Column(db.Boolean(), nullable=True, default=False)
|
||||||
|
|
||||||
accepted_with_funding = db.Column(db.Boolean(), nullable=True)
|
accepted_with_funding = db.Column(db.Boolean(), nullable=True)
|
||||||
changes_requested_discussion = db.Column(db.Boolean(), nullable=True)
|
changes_requested_discussion = db.Column(db.Boolean(), nullable=True)
|
||||||
|
@ -434,9 +435,11 @@ class Proposal(db.Model):
|
||||||
.correlate_except(proposal_liker)
|
.correlate_except(proposal_liker)
|
||||||
)
|
)
|
||||||
live_draft_parent_id = db.Column(db.Integer, ForeignKey('proposal.id'))
|
live_draft_parent_id = db.Column(db.Integer, ForeignKey('proposal.id'))
|
||||||
live_draft = db.relationship("Proposal", uselist=False, backref=db.backref('live_draft_parent', remote_side=[id], uselist=False))
|
live_draft = db.relationship("Proposal", uselist=False,
|
||||||
|
backref=db.backref('live_draft_parent', remote_side=[id], uselist=False))
|
||||||
|
|
||||||
revisions = db.relationship(ProposalRevision, foreign_keys=[ProposalRevision.proposal_id], lazy=True, cascade="all, delete-orphan")
|
revisions = db.relationship(ProposalRevision, foreign_keys=[ProposalRevision.proposal_id], lazy=True,
|
||||||
|
cascade="all, delete-orphan")
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
@ -535,7 +538,6 @@ class Proposal(db.Model):
|
||||||
# Then run through regular validation
|
# Then run through regular validation
|
||||||
Proposal.simple_validate(vars(self))
|
Proposal.simple_validate(vars(self))
|
||||||
|
|
||||||
|
|
||||||
def validate_milestone_days(self):
|
def validate_milestone_days(self):
|
||||||
for milestone in self.milestones:
|
for milestone in self.milestones:
|
||||||
if milestone.immediate_payout:
|
if milestone.immediate_payout:
|
||||||
|
@ -1099,7 +1101,8 @@ class ProposalSchema(ma.Schema):
|
||||||
"changes_requested_discussion",
|
"changes_requested_discussion",
|
||||||
"changes_requested_discussion_reason",
|
"changes_requested_discussion_reason",
|
||||||
"live_draft_id",
|
"live_draft_id",
|
||||||
"kyc_approved"
|
"kyc_approved",
|
||||||
|
"funded_by_zomg"
|
||||||
)
|
)
|
||||||
|
|
||||||
date_created = ma.Method("get_date_created")
|
date_created = ma.Method("get_date_created")
|
||||||
|
@ -1109,6 +1112,7 @@ class ProposalSchema(ma.Schema):
|
||||||
is_version_two = ma.Method("get_is_version_two")
|
is_version_two = ma.Method("get_is_version_two")
|
||||||
tip_jar_view_key = ma.Method("get_tip_jar_view_key")
|
tip_jar_view_key = ma.Method("get_tip_jar_view_key")
|
||||||
live_draft_id = ma.Method("get_live_draft_id")
|
live_draft_id = ma.Method("get_live_draft_id")
|
||||||
|
funded_by_zomg = ma.Method("get_funded_by_zomg")
|
||||||
|
|
||||||
updates = ma.Nested("ProposalUpdateSchema", many=True)
|
updates = ma.Nested("ProposalUpdateSchema", many=True)
|
||||||
team = ma.Nested("UserSchema", many=True)
|
team = ma.Nested("UserSchema", many=True)
|
||||||
|
@ -1118,6 +1122,14 @@ class ProposalSchema(ma.Schema):
|
||||||
rfp = ma.Nested("RFPSchema", exclude=["accepted_proposals"])
|
rfp = ma.Nested("RFPSchema", exclude=["accepted_proposals"])
|
||||||
arbiter = ma.Nested("ProposalArbiterSchema", exclude=["proposal"])
|
arbiter = ma.Nested("ProposalArbiterSchema", exclude=["proposal"])
|
||||||
|
|
||||||
|
def get_funded_by_zomg(self, obj):
|
||||||
|
if obj.funded_by_zomg is None:
|
||||||
|
return False
|
||||||
|
elif obj.funded_by_zomg is False:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
def get_proposal_id(self, obj):
|
def get_proposal_id(self, obj):
|
||||||
return obj.id
|
return obj.id
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
"""empty message
|
||||||
|
|
||||||
|
Revision ID: 91b16dc2fd74
|
||||||
|
Revises: d03c91f3038d
|
||||||
|
Create Date: 2021-02-01 17:00:23.721765
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '91b16dc2fd74'
|
||||||
|
down_revision = 'd03c91f3038d'
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column('proposal', sa.Column('funded_by_zomg', sa.Boolean(), nullable=True))
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_column('proposal', 'funded_by_zomg')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -86,11 +86,11 @@ export const STAGE_UI: { [key in PROPOSAL_FILTERS]: StageUI } = {
|
||||||
color: '#8e44ad',
|
color: '#8e44ad',
|
||||||
},
|
},
|
||||||
ACCEPTED_WITH_FUNDING: {
|
ACCEPTED_WITH_FUNDING: {
|
||||||
label: 'Funded by ZF',
|
label: 'Funded',
|
||||||
color: '#8e44ad',
|
color: '#8e44ad',
|
||||||
},
|
},
|
||||||
ACCEPTED_WITHOUT_FUNDING: {
|
ACCEPTED_WITHOUT_FUNDING: {
|
||||||
label: 'Not Funded by ZF',
|
label: 'Not Funded',
|
||||||
color: '#8e44ad',
|
color: '#8e44ad',
|
||||||
},
|
},
|
||||||
WIP: {
|
WIP: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { UserProposal, STATUS } from 'types';
|
import { STATUS, UserProposal } from 'types';
|
||||||
import './ProfileProposal.less';
|
import './ProfileProposal.less';
|
||||||
import UserRow from 'components/UserRow';
|
import UserRow from 'components/UserRow';
|
||||||
import UnitDisplay from 'components/UnitDisplay';
|
import UnitDisplay from 'components/UnitDisplay';
|
||||||
|
@ -23,7 +23,8 @@ export default class Profile extends React.Component<OwnProps> {
|
||||||
isVersionTwo,
|
isVersionTwo,
|
||||||
acceptedWithFunding,
|
acceptedWithFunding,
|
||||||
status,
|
status,
|
||||||
changesRequestedDiscussionReason
|
changesRequestedDiscussionReason,
|
||||||
|
fundedByZomg,
|
||||||
} = this.props.proposal;
|
} = this.props.proposal;
|
||||||
|
|
||||||
// pulled from `variables.less`
|
// pulled from `variables.less`
|
||||||
|
@ -31,18 +32,24 @@ export default class Profile extends React.Component<OwnProps> {
|
||||||
const secondaryColor = '#2D2A26';
|
const secondaryColor = '#2D2A26';
|
||||||
|
|
||||||
const isOpenForDiscussion = status === STATUS.DISCUSSION;
|
const isOpenForDiscussion = status === STATUS.DISCUSSION;
|
||||||
const discussionColor = changesRequestedDiscussionReason ? 'red' : infoColor
|
const discussionColor = changesRequestedDiscussionReason ? 'red' : infoColor;
|
||||||
const discussionTag = changesRequestedDiscussionReason ? 'Changes Requested' : 'Open for Public Review'
|
const discussionTag = changesRequestedDiscussionReason
|
||||||
|
? 'Changes Requested'
|
||||||
|
: 'Open for Public Review';
|
||||||
|
|
||||||
let tagColor = infoColor
|
let tagColor = infoColor;
|
||||||
let tagMessage = 'Open for Contributions'
|
let tagMessage = 'Open for Contributions';
|
||||||
|
|
||||||
if (acceptedWithFunding) {
|
if (acceptedWithFunding) {
|
||||||
tagColor = secondaryColor
|
tagColor = secondaryColor;
|
||||||
tagMessage = 'Funded by ZF'
|
if (!fundedByZomg) {
|
||||||
|
tagMessage = 'Funded by ZF';
|
||||||
|
} else {
|
||||||
|
tagMessage = 'Funded by ZOMG';
|
||||||
|
}
|
||||||
} else if (isOpenForDiscussion) {
|
} else if (isOpenForDiscussion) {
|
||||||
tagColor = discussionColor
|
tagColor = discussionColor;
|
||||||
tagMessage = discussionTag
|
tagMessage = discussionTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { Icon, Popover, Tooltip, Alert } from 'antd';
|
import { Alert, Icon, Popover, Tooltip } from 'antd';
|
||||||
import { Proposal, STATUS } from 'types';
|
import { Proposal, STATUS } from 'types';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
@ -12,6 +12,8 @@ import Loader from 'components/Loader';
|
||||||
import { PROPOSAL_STAGE } from 'api/constants';
|
import { PROPOSAL_STAGE } from 'api/constants';
|
||||||
import { formatUsd } from 'utils/formatters';
|
import { formatUsd } from 'utils/formatters';
|
||||||
import ZFGrantsLogo from 'static/images/logo-name-light.svg';
|
import ZFGrantsLogo from 'static/images/logo-name-light.svg';
|
||||||
|
import ZomgLogo from 'static/images/zomg-logo.png';
|
||||||
|
|
||||||
import './style.less';
|
import './style.less';
|
||||||
|
|
||||||
interface OwnProps {
|
interface OwnProps {
|
||||||
|
@ -134,7 +136,11 @@ export class ProposalCampaignBlock extends React.Component<Props, State> {
|
||||||
isAcceptedWithFunding && (
|
isAcceptedWithFunding && (
|
||||||
<div className="ProposalCampaignBlock-with-funding">
|
<div className="ProposalCampaignBlock-with-funding">
|
||||||
Funded through
|
Funded through
|
||||||
|
{proposal.fundedByZomg ? (
|
||||||
|
<img src={ZomgLogo} alt={'Zomg logo'} style={{ height: '1.5rem' }} />
|
||||||
|
) : (
|
||||||
<ZFGrantsLogo style={{ height: '1.5rem' }} />
|
<ZFGrantsLogo style={{ height: '1.5rem' }} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ export class ProposalCard extends React.Component<Proposal> {
|
||||||
percentFunded,
|
percentFunded,
|
||||||
acceptedWithFunding,
|
acceptedWithFunding,
|
||||||
status,
|
status,
|
||||||
|
fundedByZomg,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
// pulled from `variables.less`
|
// pulled from `variables.less`
|
||||||
|
@ -46,7 +47,11 @@ export class ProposalCard extends React.Component<Proposal> {
|
||||||
if (isVersionTwo && status === STATUS.LIVE) {
|
if (isVersionTwo && status === STATUS.LIVE) {
|
||||||
if (acceptedWithFunding) {
|
if (acceptedWithFunding) {
|
||||||
tagColor = secondaryColor;
|
tagColor = secondaryColor;
|
||||||
|
if (!fundedByZomg) {
|
||||||
tagMessage = 'Funded by ZF';
|
tagMessage = 'Funded by ZF';
|
||||||
|
} else {
|
||||||
|
tagMessage = 'Funded by ZOMG';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tagColor = infoColor;
|
tagColor = infoColor;
|
||||||
tagMessage = 'Not Funded';
|
tagMessage = 'Not Funded';
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
|
@ -0,0 +1,64 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 1300.8 419.2" style="enable-background:new 0 0 1300.8 419.2;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{display:none;}
|
||||||
|
.st1{display:inline;fill:#100400;}
|
||||||
|
.st2{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
|
||||||
|
.st3{fill-rule:evenodd;clip-rule:evenodd;fill:#0F7000;}
|
||||||
|
.st4{fill:#FFFFFF;}
|
||||||
|
.st5{fill:#F8BB14;}
|
||||||
|
.st6{fill:none;stroke:#FFFFFF;stroke-width:24.24;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;}
|
||||||
|
.st7{font-family:'Roboto-Medium';}
|
||||||
|
.st8{font-size:304.0703px;}
|
||||||
|
</style>
|
||||||
|
<g id="Layer_2" class="st0">
|
||||||
|
<rect x="-102.5" y="-82" class="st1" width="1515.7" height="567.6"/>
|
||||||
|
</g>
|
||||||
|
<g id="Layer_1" xmlns:serif="http://www.serif.com/">
|
||||||
|
<g>
|
||||||
|
<g transform="matrix(0.347046,-4.1523e-17,-1.03807e-17,0.347046,307.53,12.3394)">
|
||||||
|
<g id="Color">
|
||||||
|
<g>
|
||||||
|
<g id="Color1" transform="matrix(1.09544,1.31066e-16,3.27664e-17,1.09544,-953.204,-33.2755)" serif:id="Color">
|
||||||
|
<g transform="matrix(1.19303,-3.26522e-48,2.90837e-48,1.06265,-101.088,-115.302)">
|
||||||
|
<rect x="572.7" y="564.3" class="st2" width="37.4" height="265.4"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1,-2.73691e-48,2.73691e-48,1,0,-21.0434)">
|
||||||
|
<path class="st3" d="M970,472.4c-7.7-25.6-24.4,55.7-167.7,79.1c-112.6,18.3-168.6,129.2-148.5,161.9
|
||||||
|
c13.1,21.4,111.2,52.7,194.7-8.3C931.7,644.3,977.7,498,970,472.4z M651.6,707c3,5.4,78.8-15.7,123.6-40.6
|
||||||
|
c52.8-29.3,108.9-79.9,104.4-85.7c-2.9-3.8-63.8,23.9-123.7,57.7C704.1,667.6,646.4,697.7,651.6,707z"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(1,-2.73691e-48,2.73691e-48,1,0,-21.0434)">
|
||||||
|
<path class="st3" d="M295.5,443.5C308,424.7,306.9,490,436.7,528c102,29.9,131.7,123.6,106.1,146.1
|
||||||
|
c-16.7,14.7-115.4,25.3-181.2-33.5C295.9,581.9,283,462.2,295.5,443.5z M544.7,672c-2.8,3.9-52.5-14.7-91.1-39
|
||||||
|
c-30-19-76.9-55.4-64.6-63.8c5.6-3.8,41.1,21,77.6,44.2C504.4,637.4,550.2,664.4,544.7,672z"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(0.927915,-1.11022e-16,-2.77556e-17,0.927915,854.005,46.6736)">
|
||||||
|
<g transform="matrix(1,0,0,1,-581.95,-44.2319)">
|
||||||
|
<path class="st4" d="M312.2,514.8c-131.2,0-238-106.8-238-238c0-131.2,106.8-238,238-238c131.2,0,238,106.8,238,238
|
||||||
|
C550.2,408,443.4,514.8,312.2,514.8z M312.2-8.3C155-8.3,27.1,119.6,27.1,276.8S155,561.9,312.2,561.9
|
||||||
|
S597.3,434,597.3,276.8S469.4-8.3,312.2-8.3z"/>
|
||||||
|
</g>
|
||||||
|
<path class="st5" d="M-269.8,7.8c-123.9,0-224.7,100.8-224.7,224.7c0,123.9,100.8,224.7,224.7,224.7S-45.1,356.4-45.1,232.5
|
||||||
|
C-45.1,108.6-145.9,7.8-269.8,7.8z M-168.1,143.7l-22,27.9l-98.6,135.7h120.6v57.6h-77.8v47.6h-5.7v0.2h-36.3v-0.2h-5.7
|
||||||
|
v-47.6h-77.8v-43.5l22-27.9l98.6-135.7h-120.6v-57.6h77.8V52.5h47.8v47.7h77.8V143.7z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Hand" transform="matrix(1.23479,1.47739e-16,3.95e-17,1.32055,-1023.9,-346.117)">
|
||||||
|
<path class="st6" d="M139.9,880c0,0,93-1.5,138.8-9.1c48.9-8.1,105.2-39.7,154.8-39.4c49.5,0.3,87.5,32.1,142.6,41.4
|
||||||
|
c59,10,156.2,9.9,180.2,27.8c19.8,14.7,5.2,49.9-32.8,64c-26,9.7-73.4,19.4-110.9,19.1c-53.6-0.5-217.9-23.2-210.9-21.8
|
||||||
|
c7,1.4,168.5,39.2,252.9,30.2c84.8-9,192.9-67.4,256.1-84.4c40-10.7,92.5-19.5,123.1-17.3c38.6,2.8,64,22.1,47.7,32.5
|
||||||
|
c-57.7,36.8-263.6,156-393.9,188.1c-86.5,21.3-273,9.5-313,4.2c-60.9-8-98.3-24.4-139.4-53.2c-23.7-16.6-95.3-45.2-95.3-45.2
|
||||||
|
V880z"/>
|
||||||
|
</g>
|
||||||
|
<g transform="matrix(121.473,1.45339e-14,3.31689e-15,110.889,-21599.6,-106761)">
|
||||||
|
<text transform="matrix(2.598518e-02 0 0 2.598510e-02 181.6097 969.9001)" class="st4 st7 st8">zomg</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
|
@ -81,6 +81,7 @@ export interface Proposal extends Omit<ProposalDraft, 'target' | 'invites'> {
|
||||||
liveDraftId: string | null;
|
liveDraftId: string | null;
|
||||||
isTeamMember?: boolean; // FE derived
|
isTeamMember?: boolean; // FE derived
|
||||||
isArbiter?: boolean; // FE derived
|
isArbiter?: boolean; // FE derived
|
||||||
|
fundedByZomg: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TeamInviteWithProposal extends TeamInvite {
|
export interface TeamInviteWithProposal extends TeamInvite {
|
||||||
|
|
Loading…
Reference in New Issue