2018-11-13 08:07:09 -08:00
|
|
|
import React from 'react';
|
|
|
|
import { connect } from 'react-redux';
|
2018-11-13 14:51:02 -08:00
|
|
|
import { Link } from 'react-router-dom';
|
2019-01-28 16:51:10 -08:00
|
|
|
import { Button, Divider, List, message, Popconfirm, Spin } from 'antd';
|
2018-11-15 08:02:16 -08:00
|
|
|
import Placeholder from 'components/Placeholder';
|
2019-01-28 16:51:10 -08:00
|
|
|
import { getIsVerified } from 'modules/auth/selectors';
|
2019-01-23 07:15:59 -08:00
|
|
|
import Loader from 'components/Loader';
|
2019-01-09 10:23:08 -08:00
|
|
|
import { ProposalDraft, STATUS } from 'types';
|
2019-02-01 11:13:30 -08:00
|
|
|
import {
|
|
|
|
createDraft,
|
|
|
|
deleteDraft,
|
|
|
|
fetchDrafts,
|
|
|
|
fetchAndCreateDrafts,
|
|
|
|
} from 'modules/create/actions';
|
2018-11-13 14:51:02 -08:00
|
|
|
import { AppState } from 'store/reducers';
|
|
|
|
import './style.less';
|
2018-11-13 08:07:09 -08:00
|
|
|
|
2018-11-13 14:51:02 -08:00
|
|
|
interface StateProps {
|
|
|
|
drafts: AppState['create']['drafts'];
|
|
|
|
isFetchingDrafts: AppState['create']['isFetchingDrafts'];
|
|
|
|
fetchDraftsError: AppState['create']['fetchDraftsError'];
|
|
|
|
isCreatingDraft: AppState['create']['isCreatingDraft'];
|
|
|
|
createDraftError: AppState['create']['createDraftError'];
|
2018-11-15 08:02:16 -08:00
|
|
|
isDeletingDraft: AppState['create']['isDeletingDraft'];
|
|
|
|
deleteDraftError: AppState['create']['deleteDraftError'];
|
2019-01-28 16:51:10 -08:00
|
|
|
isVerified: ReturnType<typeof getIsVerified>;
|
2018-11-13 14:51:02 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
interface DispatchProps {
|
|
|
|
fetchDrafts: typeof fetchDrafts;
|
|
|
|
createDraft: typeof createDraft;
|
2018-11-15 08:02:16 -08:00
|
|
|
deleteDraft: typeof deleteDraft;
|
2019-02-01 11:13:30 -08:00
|
|
|
fetchAndCreateDrafts: typeof fetchAndCreateDrafts;
|
2018-11-13 14:51:02 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
interface OwnProps {
|
|
|
|
createIfNone?: boolean;
|
2019-02-01 11:13:30 -08:00
|
|
|
createWithRfpId?: number;
|
2018-11-13 14:51:02 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
type Props = StateProps & DispatchProps & OwnProps;
|
|
|
|
|
2018-11-15 08:02:16 -08:00
|
|
|
interface State {
|
|
|
|
deletingId: number | null;
|
|
|
|
}
|
|
|
|
|
2019-11-24 07:07:03 -08:00
|
|
|
const EMAIL_VERIFIED_RELOAD_TIMEOUT = 10000;
|
|
|
|
|
2018-11-15 08:02:16 -08:00
|
|
|
class DraftList extends React.Component<Props, State> {
|
|
|
|
state: State = {
|
|
|
|
deletingId: null,
|
|
|
|
};
|
|
|
|
|
2019-11-24 07:07:03 -08:00
|
|
|
private reloadTimeout: number | null = null;
|
|
|
|
|
2019-02-01 11:13:30 -08:00
|
|
|
componentDidMount() {
|
2019-11-24 07:07:03 -08:00
|
|
|
const { createIfNone, createWithRfpId, isVerified } = this.props;
|
2019-02-01 11:13:30 -08:00
|
|
|
if (createIfNone || createWithRfpId) {
|
|
|
|
this.props.fetchAndCreateDrafts({
|
|
|
|
rfpId: createWithRfpId,
|
|
|
|
redirect: true,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.props.fetchDrafts();
|
|
|
|
}
|
2019-11-24 07:07:03 -08:00
|
|
|
|
|
|
|
if (!isVerified) {
|
|
|
|
this.reloadTimeout = window.setTimeout(() => {
|
|
|
|
window.location.reload();
|
|
|
|
}, EMAIL_VERIFIED_RELOAD_TIMEOUT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
if (this.reloadTimeout !== null) {
|
|
|
|
window.clearTimeout(this.reloadTimeout);
|
|
|
|
}
|
2018-11-13 14:51:02 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
componentDidUpdate(prevProps: Props) {
|
2019-02-01 11:13:30 -08:00
|
|
|
const { isDeletingDraft, deleteDraftError, createDraftError } = this.props;
|
2018-11-15 08:02:16 -08:00
|
|
|
if (prevProps.isDeletingDraft && !isDeletingDraft) {
|
|
|
|
this.setState({ deletingId: null });
|
|
|
|
}
|
|
|
|
if (deleteDraftError && prevProps.deleteDraftError !== deleteDraftError) {
|
2019-03-12 20:35:38 -07:00
|
|
|
message.error(deleteDraftError, 3);
|
2018-11-15 08:02:16 -08:00
|
|
|
}
|
|
|
|
if (createDraftError && prevProps.createDraftError !== createDraftError) {
|
2019-03-12 20:35:38 -07:00
|
|
|
message.error(createDraftError, 3);
|
2018-11-15 08:02:16 -08:00
|
|
|
}
|
2018-11-13 14:51:02 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
2019-02-01 11:13:30 -08:00
|
|
|
const { drafts, isCreatingDraft, isFetchingDrafts, isVerified } = this.props;
|
2018-11-15 08:02:16 -08:00
|
|
|
const { deletingId } = this.state;
|
2018-11-13 14:51:02 -08:00
|
|
|
|
2019-01-28 16:51:10 -08:00
|
|
|
if (!isVerified) {
|
|
|
|
return (
|
|
|
|
<div className="DraftList">
|
|
|
|
<Placeholder
|
|
|
|
title="Your email is not verified"
|
|
|
|
subtitle="Please confirm your email before making a proposal."
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-11-15 08:02:16 -08:00
|
|
|
if (!drafts || isCreatingDraft) {
|
2019-01-23 08:35:03 -08:00
|
|
|
return <Loader size="large" />;
|
2018-11-13 14:51:02 -08:00
|
|
|
}
|
|
|
|
|
2018-11-15 08:02:16 -08:00
|
|
|
let draftsEl;
|
|
|
|
if (drafts.length) {
|
|
|
|
draftsEl = (
|
2018-11-13 14:51:02 -08:00
|
|
|
<List
|
|
|
|
itemLayout="horizontal"
|
|
|
|
dataSource={drafts}
|
2019-02-01 11:13:30 -08:00
|
|
|
loading={isFetchingDrafts}
|
2018-11-13 14:51:02 -08:00
|
|
|
renderItem={(d: ProposalDraft) => {
|
|
|
|
const actions = [
|
|
|
|
<Link key="edit" to={`/proposals/${d.proposalId}/edit`}>
|
|
|
|
Edit
|
|
|
|
</Link>,
|
2018-11-15 08:02:16 -08:00
|
|
|
<Popconfirm
|
|
|
|
key="delete"
|
|
|
|
title="Are you sure?"
|
|
|
|
onConfirm={() => this.deleteDraft(d.proposalId)}
|
|
|
|
>
|
|
|
|
<a>Delete</a>
|
|
|
|
</Popconfirm>,
|
2018-11-13 14:51:02 -08:00
|
|
|
];
|
|
|
|
return (
|
2019-01-23 08:35:03 -08:00
|
|
|
<Spin tip="deleting..." spinning={deletingId === d.proposalId}>
|
|
|
|
<List.Item actions={actions}>
|
|
|
|
<List.Item.Meta
|
|
|
|
title={
|
|
|
|
<>
|
CCRs (#86)
* CCRs API / Models boilerplate
* start on frontend
* backendy things
* Create CCR redux module, integrate API endpoints, create types
* Fix/Cleanup API
* Wire up CreateRequestDraftList
* bounty->target
* Add 'Create Request Flow' MVP
* cleanup
* Tweak filenames
* Simplify migrations
* fix migrations
* CCR Staking MVP
* tslint
* Get Pending Requests into Profile
* Remove staking requirement
* more staking related removals
* MVP Admin integration
* Make RFP when CCR is accepted
* Add pagination to CCRs in Admin
Improve styles for Proposals
* Hookup notifications
Adjust copy
* Simplify ccr->rfp relationship
Add admin approval email
Fixup copy
* Show Message on RFP Detail
Make Header CTAs change based on draft status
Adjust proposal card style
* Bugfix: Show header for non signed in users
* Add 'create a request' to intro
* Profile Created CCRs
RFP CCR attribution
* ignore
* CCR Price in USD (#85)
* init profile tipjar backend
* init profile tipjar frontend
* fix lint
* implement tip jar block
* fix wrapping, hide tip block on self
* init backend proposal tipjar
* init frontend proposal tipjar
* add hide title, fix bug
* uncomment rate limit
* rename vars, use null check
* allow address and view key to be unset
* add api tests
* fix tsc errors
* fix lint
* fix CopyInput styling
* fix migrations
* hide tipping in proposal if address not set
* add tip address to create flow
* redesign campaign block
* fix typo
* init backend changes
* init admin changes
* init frontend changes
* fix backend tests
* update campaign block
* be - init rfp usd changes
* admin - init rfp usd changes
* fe - fully adapt api util functions to usd
* fe - init rfp usd changes
* adapt profile created to usd
* misc usd changes
* add tip jar to dedicated card
* fix tipjar bug
* use zf light logo
* switch to zf grants logo
* hide profile tip jar if address not set
* add comment, run prettier
* conditionally add info icon and tooltip to funding line
* admin - disallow decimals in RFPs
* fe - cover usd string edge case
* add Usd as rfp bounty type
* fix migration order
* fix email bug
* adapt CCRs to USD
* implement CCR preview
* fix tsc
* Copy Updates and UX Tweaks (#87)
* Add default structure to proposal content
* Landing page copy
* Hide contributors tab for v2 proposals
* Minor UX tweaks for Liking/Following/Tipping
* Copy for Tipping Tooltip, proposal explainer for review, and milestone day estimate notice.
* Fix header styles bug and remove commented out styles.
* Revert "like" / "unfollow" hyphenication
* Comment out unused tests related to staking
Increase PROPOSAL_TARGET_MAX in .env.example
* Comment out ccr approval email send until ready
* Adjust styles, copy.
* fix proposal prune test (#88)
* fix USD display in preview, fix non-unique key (#90)
* Pre-stepper explainer for CCRs.
* Tweak styles
* Default content for CCRs
* fix tsc
* CCR approval and rejection emails
* add back admin_approval_ccr email templates
* Link ccr author name to profile in RFPs
* copy tweaks
* copy tweak
* hookup mangle user command
* Fix/add endif in jinja
* fix tests
* review
* fix review
2019-12-05 17:01:02 -08:00
|
|
|
{d.title || <em>Untitled Proposal</em>}
|
2019-11-20 13:37:58 -08:00
|
|
|
{d.status === STATUS.REJECTED && <em> (changes requested)</em>}
|
2019-01-23 08:35:03 -08:00
|
|
|
</>
|
|
|
|
}
|
|
|
|
description={d.brief || <em>No description</em>}
|
|
|
|
/>
|
|
|
|
</List.Item>
|
|
|
|
</Spin>
|
2018-11-13 14:51:02 -08:00
|
|
|
);
|
|
|
|
}}
|
|
|
|
/>
|
2018-11-15 08:02:16 -08:00
|
|
|
);
|
|
|
|
} else {
|
|
|
|
draftsEl = (
|
|
|
|
<Placeholder
|
|
|
|
title="You have no drafts"
|
|
|
|
subtitle="Why not make one now? Click below to start."
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="DraftList">
|
CCRs (#86)
* CCRs API / Models boilerplate
* start on frontend
* backendy things
* Create CCR redux module, integrate API endpoints, create types
* Fix/Cleanup API
* Wire up CreateRequestDraftList
* bounty->target
* Add 'Create Request Flow' MVP
* cleanup
* Tweak filenames
* Simplify migrations
* fix migrations
* CCR Staking MVP
* tslint
* Get Pending Requests into Profile
* Remove staking requirement
* more staking related removals
* MVP Admin integration
* Make RFP when CCR is accepted
* Add pagination to CCRs in Admin
Improve styles for Proposals
* Hookup notifications
Adjust copy
* Simplify ccr->rfp relationship
Add admin approval email
Fixup copy
* Show Message on RFP Detail
Make Header CTAs change based on draft status
Adjust proposal card style
* Bugfix: Show header for non signed in users
* Add 'create a request' to intro
* Profile Created CCRs
RFP CCR attribution
* ignore
* CCR Price in USD (#85)
* init profile tipjar backend
* init profile tipjar frontend
* fix lint
* implement tip jar block
* fix wrapping, hide tip block on self
* init backend proposal tipjar
* init frontend proposal tipjar
* add hide title, fix bug
* uncomment rate limit
* rename vars, use null check
* allow address and view key to be unset
* add api tests
* fix tsc errors
* fix lint
* fix CopyInput styling
* fix migrations
* hide tipping in proposal if address not set
* add tip address to create flow
* redesign campaign block
* fix typo
* init backend changes
* init admin changes
* init frontend changes
* fix backend tests
* update campaign block
* be - init rfp usd changes
* admin - init rfp usd changes
* fe - fully adapt api util functions to usd
* fe - init rfp usd changes
* adapt profile created to usd
* misc usd changes
* add tip jar to dedicated card
* fix tipjar bug
* use zf light logo
* switch to zf grants logo
* hide profile tip jar if address not set
* add comment, run prettier
* conditionally add info icon and tooltip to funding line
* admin - disallow decimals in RFPs
* fe - cover usd string edge case
* add Usd as rfp bounty type
* fix migration order
* fix email bug
* adapt CCRs to USD
* implement CCR preview
* fix tsc
* Copy Updates and UX Tweaks (#87)
* Add default structure to proposal content
* Landing page copy
* Hide contributors tab for v2 proposals
* Minor UX tweaks for Liking/Following/Tipping
* Copy for Tipping Tooltip, proposal explainer for review, and milestone day estimate notice.
* Fix header styles bug and remove commented out styles.
* Revert "like" / "unfollow" hyphenication
* Comment out unused tests related to staking
Increase PROPOSAL_TARGET_MAX in .env.example
* Comment out ccr approval email send until ready
* Adjust styles, copy.
* fix proposal prune test (#88)
* fix USD display in preview, fix non-unique key (#90)
* Pre-stepper explainer for CCRs.
* Tweak styles
* Default content for CCRs
* fix tsc
* CCR approval and rejection emails
* add back admin_approval_ccr email templates
* Link ccr author name to profile in RFPs
* copy tweaks
* copy tweak
* hookup mangle user command
* Fix/add endif in jinja
* fix tests
* review
* fix review
2019-12-05 17:01:02 -08:00
|
|
|
<h2 className="DraftList-title">Your Proposal Drafts</h2>
|
2018-11-15 08:02:16 -08:00
|
|
|
{draftsEl}
|
2018-11-13 14:51:02 -08:00
|
|
|
<Divider>or</Divider>
|
|
|
|
<Button
|
|
|
|
className="DraftList-create"
|
|
|
|
type="primary"
|
|
|
|
size="large"
|
|
|
|
block
|
2019-02-01 11:13:30 -08:00
|
|
|
onClick={() => this.createDraft()}
|
2018-11-13 14:51:02 -08:00
|
|
|
loading={isCreatingDraft}
|
|
|
|
>
|
|
|
|
Create a new Proposal
|
|
|
|
</Button>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-02-01 11:13:30 -08:00
|
|
|
private createDraft = (rfpId?: number) => {
|
|
|
|
this.props.createDraft({ rfpId, redirect: true });
|
2018-11-13 14:51:02 -08:00
|
|
|
};
|
2018-11-15 08:02:16 -08:00
|
|
|
|
|
|
|
private deleteDraft = (proposalId: number) => {
|
|
|
|
this.props.deleteDraft(proposalId);
|
|
|
|
this.setState({ deletingId: proposalId });
|
|
|
|
};
|
2018-11-13 14:51:02 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
export default connect<StateProps, DispatchProps, OwnProps, AppState>(
|
|
|
|
state => ({
|
|
|
|
drafts: state.create.drafts,
|
|
|
|
isFetchingDrafts: state.create.isFetchingDrafts,
|
|
|
|
fetchDraftsError: state.create.fetchDraftsError,
|
|
|
|
isCreatingDraft: state.create.isCreatingDraft,
|
|
|
|
createDraftError: state.create.createDraftError,
|
2018-11-15 08:02:16 -08:00
|
|
|
isDeletingDraft: state.create.isDeletingDraft,
|
|
|
|
deleteDraftError: state.create.deleteDraftError,
|
2019-01-28 16:51:10 -08:00
|
|
|
isVerified: getIsVerified(state),
|
2018-11-13 14:51:02 -08:00
|
|
|
}),
|
|
|
|
{
|
|
|
|
fetchDrafts,
|
|
|
|
createDraft,
|
2018-11-15 08:02:16 -08:00
|
|
|
deleteDraft,
|
2019-02-01 11:13:30 -08:00
|
|
|
fetchAndCreateDrafts,
|
2018-11-13 14:51:02 -08:00
|
|
|
},
|
|
|
|
)(DraftList);
|