zcash-grant-system/frontend/client/components/DraftList/index.tsx

206 lines
5.7 KiB
TypeScript
Raw Normal View History

2018-11-13 08:07:09 -08:00
import React from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { Button, Divider, List, message, Popconfirm, Spin } from 'antd';
2018-11-15 08:02:16 -08:00
import Placeholder from 'components/Placeholder';
import { getIsVerified } from 'modules/auth/selectors';
2019-01-23 07:15:59 -08:00
import Loader from 'components/Loader';
import { ProposalDraft, STATUS } from 'types';
import {
createDraft,
deleteDraft,
fetchDrafts,
fetchAndCreateDrafts,
} from 'modules/create/actions';
import { AppState } from 'store/reducers';
import './style.less';
2018-11-13 08:07:09 -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'];
isVerified: ReturnType<typeof getIsVerified>;
}
interface DispatchProps {
fetchDrafts: typeof fetchDrafts;
createDraft: typeof createDraft;
2018-11-15 08:02:16 -08:00
deleteDraft: typeof deleteDraft;
fetchAndCreateDrafts: typeof fetchAndCreateDrafts;
}
interface OwnProps {
createIfNone?: boolean;
createWithRfpId?: number;
}
type Props = StateProps & DispatchProps & OwnProps;
2018-11-15 08:02:16 -08:00
interface State {
deletingId: number | null;
}
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,
};
private reloadTimeout: number | null = null;
componentDidMount() {
const { createIfNone, createWithRfpId, isVerified } = this.props;
if (createIfNone || createWithRfpId) {
this.props.fetchAndCreateDrafts({
rfpId: createWithRfpId,
redirect: true,
});
} else {
this.props.fetchDrafts();
}
if (!isVerified) {
this.reloadTimeout = window.setTimeout(() => {
window.location.reload();
}, EMAIL_VERIFIED_RELOAD_TIMEOUT);
}
}
componentWillUnmount() {
if (this.reloadTimeout !== null) {
window.clearTimeout(this.reloadTimeout);
}
}
componentDidUpdate(prevProps: Props) {
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) {
message.error(deleteDraftError, 3);
2018-11-15 08:02:16 -08:00
}
if (createDraftError && prevProps.createDraftError !== createDraftError) {
message.error(createDraftError, 3);
2018-11-15 08:02:16 -08:00
}
}
render() {
const { drafts, isCreatingDraft, isFetchingDrafts, isVerified } = this.props;
2018-11-15 08:02:16 -08:00
const { deletingId } = this.state;
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-15 08:02:16 -08:00
let draftsEl;
if (drafts.length) {
draftsEl = (
<List
itemLayout="horizontal"
dataSource={drafts}
loading={isFetchingDrafts}
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>,
];
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>}
{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-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}
<Divider>or</Divider>
<Button
className="DraftList-create"
type="primary"
size="large"
block
onClick={() => this.createDraft()}
loading={isCreatingDraft}
>
Create a new Proposal
</Button>
</div>
);
}
private createDraft = (rfpId?: number) => {
this.props.createDraft({ rfpId, redirect: true });
};
2018-11-15 08:02:16 -08:00
private deleteDraft = (proposalId: number) => {
this.props.deleteDraft(proposalId);
this.setState({ deletingId: proposalId });
};
}
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,
isVerified: getIsVerified(state),
}),
{
fetchDrafts,
createDraft,
2018-11-15 08:02:16 -08:00
deleteDraft,
fetchAndCreateDrafts,
},
)(DraftList);