Unverified Commit 09e5463e authored by roadscape's avatar roadscape Committed by GitHub
Browse files

Merge pull request #107 from steemit/106-community-create-UI-tweaks

106 community create ui tweaks
parents ffd08186 aace1cf4
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
@import './elements/SanitizedLink/styles'; @import './elements/SanitizedLink/styles';
@import './elements/HelpTip/styles'; @import './elements/HelpTip/styles';
@import './elements/Dropdown'; @import './elements/Dropdown';
@import './elements/CreateCommunity';
// modules // modules
@import './modules/Header/styles'; @import './modules/Header/styles';
......
...@@ -4,6 +4,8 @@ import { connect } from 'react-redux'; ...@@ -4,6 +4,8 @@ import { connect } from 'react-redux';
import * as communityActions from 'app/redux/CommunityReducer'; import * as communityActions from 'app/redux/CommunityReducer';
import tt from 'counterpart'; import tt from 'counterpart';
import { key_utils } from '@steemit/steem-js/lib/auth/ecc'; import { key_utils } from '@steemit/steem-js/lib/auth/ecc';
import LoadingIndicator from 'app/components/elements/LoadingIndicator';
import Unicode from 'app/utils/Unicode';
class CreateCommunity extends React.Component { class CreateCommunity extends React.Component {
constructor() { constructor() {
...@@ -23,19 +25,24 @@ class CreateCommunity extends React.Component { ...@@ -23,19 +25,24 @@ class CreateCommunity extends React.Component {
communityCreateSuccess, communityCreateSuccess,
createCommunity, createCommunity,
communityDescription, communityDescription,
communityNSFW,
communityOwnerWifPassword, communityOwnerWifPassword,
communityOwnerName, communityOwnerName,
communityTitle, communityTitle,
updateCommunityTitle, updateCommunityTitle,
updateCommunityDescription, updateCommunityDescription,
updateCommunityNSFW,
updateCommunityOwnerAccountName, updateCommunityOwnerAccountName,
updateCommunityOwnerWifPassword, updateCommunityOwnerWifPassword,
broadcastOps, broadcastOps,
communityCreationPending,
socialUrl,
} = this.props; } = this.props;
const handleAccountCreateError = () => { const handleAccountCreateError = error => {
// If the user cancels the account creation do not show an error.
if (error === undefined) {
communityCreationPending(false);
return;
}
this.setState({ accountError: true }); this.setState({ accountError: true });
}; };
...@@ -53,15 +60,13 @@ class CreateCommunity extends React.Component { ...@@ -53,15 +60,13 @@ class CreateCommunity extends React.Component {
} }
updateCommunityTitle(e.target.value); updateCommunityTitle(e.target.value);
}; };
const handleCommunityDescriptionInput = e => { const handleCommunityDescriptionInput = e => {
if (e.target.value.length > 120) { if (e.target.value.length > 120) {
return; return;
} }
updateCommunityDescription(e.target.value); updateCommunityDescription(e.target.value);
}; };
const handleCommunityNSFWInput = e => {
updateCommunityNSFW(e.target.checked);
};
const handleCommunitySubmit = e => { const handleCommunitySubmit = e => {
e.preventDefault(); e.preventDefault();
...@@ -69,7 +74,6 @@ class CreateCommunity extends React.Component { ...@@ -69,7 +74,6 @@ class CreateCommunity extends React.Component {
accountName, accountName,
communityTitle, communityTitle,
communityDescription, communityDescription,
communityNSFW,
communityOwnerName, communityOwnerName,
communityOwnerWifPassword, communityOwnerWifPassword,
createAccountSuccessCB: handleAccountCreateSuccess, createAccountSuccessCB: handleAccountCreateSuccess,
...@@ -101,160 +105,115 @@ class CreateCommunity extends React.Component { ...@@ -101,160 +105,115 @@ class CreateCommunity extends React.Component {
updateCommunityOwnerAccountName(ownerUsername); updateCommunityOwnerAccountName(ownerUsername);
}; };
const generateCommunityCredentials = () => { const generateCreds = () => {
generateWif(); generateWif();
generateUsername(); generateUsername();
}; };
const generateCommunityCredentialsButton = ( const generateCommunityCredentialsButton = (
<button <button type="button" className="button" onClick={generateCreds}>
type="button" Next
className="button hollow"
onClick={generateCommunityCredentials}
>
{tt('g.click_to_generate_password')}
</button> </button>
); );
const rememberCredentialsPrompt = ( const credentialsPane = (
<div>
<div>{`${tt(
'g.community_owner_name_is'
)}: ${communityOwnerName}`}</div>
<div>{`${tt(
'g.community_password_is'
)}: ${communityOwnerWifPassword}`}</div>
</div>
);
const rememberCredentialsCheckbox1 = (
<label htmlFor="box1">
<input type="checkbox" name="box1" required />
{tt('g.understand_that_APP_NAME_cannot_recover_password', {
APP_NAME,
})}.
</label>
);
const rememberCredentialsCheckbox2 = (
<label htmlFor="box2">
<input type="checkbox" name="box2" required />
{tt('g.i_saved_password')}.
</label>
);
const submitCreateCommunityFormButton = (
<input type="submit" value="Submit" />
);
const createCommunityAccountSuccessMessage = (
<div>
Community account created on the blockchain. Setting current
user to be community admin...
</div>
);
const createCommunityAccountErrorMessage = (
<div> <div>
Unable to create that community. Please ensure you used the <label>
correct key. Owner Name / Password
<code className="pwd">
{communityOwnerName}
<br />
{communityOwnerWifPassword}
</code>
</label>
<label style={{ marginTop: '0px' }}>
<input type="checkbox" name="box2" required />
I have securely saved my owner name and password.
</label>
</div> </div>
); );
const createCommunityBroadcastOpsErrorMessage = ( const submitCreateCommunityFormButton = error => (
<div> <input
The community was created but setting current user to be admin className="button"
failed. Wait a moment and try again type="submit"
</div> value="Create Community"
disabled={!!error}
/>
); );
const createCommunitySuccessMessage = ( const hasPass = communityOwnerWifPassword.length > 0;
<div>
<p>Your community was created!</p>
<a
href={`https://steemitdev.com/trending/${communityOwnerName}`}
>
{tt('g.community_visit')}
</a>
</div>
);
const createCommunityErrorMessage = (
<div>{tt('g.community_error')}</div>
);
const createCommunityLoading = <div>{tt('g.community_creating')}</div>; let formError = null;
const rx = new RegExp('^[' + Unicode.L + ']');
if (!rx.test(communityTitle) && (communityTitle || hasPass))
formError = 'Must start with a letter.';
const createCommunityForm = ( const form = (
<form onSubmit={handleCommunitySubmit}> <form className="community--form" onSubmit={handleCommunitySubmit}>
<div>{tt('g.community_create')}</div> <div>{tt('g.community_create')}</div>
<label htmlFor="community_title"> <label>
Title Title
<input <input
id="community_title" id="community_title"
name="community_title"
type="text" type="text"
minLength="4" minLength="3"
maxLength="30" maxLength="20"
onChange={handleCommunityTitleInput} onChange={handleCommunityTitleInput}
value={communityTitle} value={communityTitle}
required required
/> />
</label> </label>
<label htmlFor="community_description"> {formError && <span className="error">{formError}</span>}
<label>
{tt('g.community_description')} {tt('g.community_description')}
<input <input
id="community_description" id="community_description"
name="community_description"
type="text" type="text"
minLength="10" maxLength="120"
maxLength="140"
onChange={handleCommunityDescriptionInput} onChange={handleCommunityDescriptionInput}
value={communityDescription} value={communityDescription}
required
/>
</label>
<label id="is_nsfw" htmlFor="is_nsfw">
{tt('g.community_nsfw')}
<input
type="checkbox"
name="is_nsfw"
checked={communityNSFW}
onChange={handleCommunityNSFWInput}
/> />
</label> </label>
{communityOwnerWifPassword.length <= 0 && {!hasPass && generateCommunityCredentialsButton}
generateCommunityCredentialsButton} {hasPass && credentialsPane}
{communityOwnerWifPassword.length > 0 && {hasPass && submitCreateCommunityFormButton(formError)}
rememberCredentialsPrompt}
{communityOwnerWifPassword.length > 0 &&
rememberCredentialsCheckbox1}
{communityOwnerWifPassword.length > 0 &&
rememberCredentialsCheckbox2}
{communityOwnerWifPassword.length > 0 &&
submitCreateCommunityFormButton}
</form> </form>
); );
const accountCreated = this.state.accountCreated;
const accountError = this.state.accountError;
const settingsError = this.state.broadcastOpsError;
const errored = accountError || settingsError;
const pending = communityCreatePending && !errored;
const finished = communityCreateSuccess;
const sagaError = communityCreateError;
if (finished) {
const url = `${socialUrl}/trending/${communityOwnerName}`;
return (
<div className="row">
<div className="column large-6 small-12">
Your community was created!<br />
<strong>
<a href={url}>Get started.</a>
</strong>
</div>
</div>
);
}
const showErr = msg => <div className="community--error">{msg}</div>;
const adminMsg = `Account created. Setting @${accountName} as admin...`;
return ( return (
<div className="row"> <div className="row">
<div className="column large-6 small-12"> <div className="column large-6 small-12">
{this.state.accountError && {accountError && showErr('Account creation failed.')}
createCommunityAccountErrorMessage} {settingsError && showErr('Update settings failed.')}
{this.state.accountCreated && {sagaError && showErr('Failed. Please report this issue.')}
!communityCreateSuccess && {accountCreated && <div>{adminMsg}</div>}
createCommunityAccountSuccessMessage} {pending ? <LoadingIndicator type="circle" /> : form}
{this.state.broadcastOpsError &&
createCommunityBroadcastOpsErrorMessage}
{this.state.accountError && createCommunityForm}
{this.state.broadcastOpsError && createCommunityForm}
{!communityCreatePending &&
!communityCreateSuccess &&
createCommunityForm}
{communityCreatePending &&
!this.state.accountError &&
!this.state.broadcastOpsError &&
createCommunityLoading}
{communityCreateSuccess && createCommunitySuccessMessage}
{communityCreateError && createCommunityErrorMessage}
</div> </div>
</div> </div>
); );
...@@ -269,11 +228,13 @@ export default connect( ...@@ -269,11 +228,13 @@ export default connect(
const current = state.user.get('current'); const current = state.user.get('current');
const username = current && current.get('username'); const username = current && current.get('username');
const isMyAccount = username === accountName; const isMyAccount = username === accountName;
const socialUrl = state.app.get('socialUrl');
return { return {
...ownProps, ...ownProps,
...state.community.toJS(), ...state.community.toJS(),
isMyAccount, isMyAccount,
accountName, accountName,
socialUrl,
}; };
}, },
// mapDispatchToProps // mapDispatchToProps
...@@ -285,9 +246,6 @@ export default connect( ...@@ -285,9 +246,6 @@ export default connect(
updateCommunityDescription: description => { updateCommunityDescription: description => {
dispatch(communityActions.setCommunityDescription(description)); dispatch(communityActions.setCommunityDescription(description));
}, },
updateCommunityNSFW: isNSFW => {
dispatch(communityActions.setCommunityNSFW(isNSFW));
},
updateCommunityOwnerAccountName: accountName => { updateCommunityOwnerAccountName: accountName => {
dispatch( dispatch(
communityActions.setCommunityOwnerAccountName(accountName) communityActions.setCommunityOwnerAccountName(accountName)
...@@ -318,6 +276,13 @@ export default connect( ...@@ -318,6 +276,13 @@ export default connect(
) )
); );
}, },
communityCreationPending: createCommunityAccountPending => {
dispatch(
communityActions.createCommunityAccountPending(
createCommunityAccountPending
)
);
},
}; };
} }
)(CreateCommunity); )(CreateCommunity);
.community--form {
label {margin-top: 1rem;}
.button {margin-top: 1rem;}
.pwd {
text-transform: none;
display: block;
padding: 0.2rem 0.5rem;
color: rgb(199, 37, 78);
font-size: 1rem;
background: #fff;
word-break: break-all;
text-align: left;
}
}
.community--error {
color: rgb(199, 37, 78);
}
...@@ -29,8 +29,7 @@ ...@@ -29,8 +29,7 @@
"community_error": "community_error":
"Oops, there was an error creating the community, please try again.", "Oops, there was an error creating the community, please try again.",
"community_create": "CREATE A COMMUNITY", "community_create": "CREATE A COMMUNITY",
"community_description": "Description", "community_description": "About",
"community_nsfw": "Is Not Safe For Work",
"confirm": "Confirm", "confirm": "Confirm",
"convert": "Convert", "convert": "Convert",
"date": "Date", "date": "Date",
......
...@@ -3,7 +3,6 @@ import { fromJS } from 'immutable'; ...@@ -3,7 +3,6 @@ import { fromJS } from 'immutable';
// Action constants // Action constants
const SET_COMMUNITY_TITLE = 'community/SET_COMMUNITY_TITLE'; const SET_COMMUNITY_TITLE = 'community/SET_COMMUNITY_TITLE';
const SET_COMMUNITY_DESCRIPTION = 'community/SET_COMMUNITY_DESCRIPTION'; const SET_COMMUNITY_DESCRIPTION = 'community/SET_COMMUNITY_DESCRIPTION';
const SET_COMMUNITY_NSFW = 'community/SET_COMMUNITY_NSFW';
const SET_COMMUNITY_OWNER_ACCOUNT_NAME = const SET_COMMUNITY_OWNER_ACCOUNT_NAME =
'community/SET_COMMUNITY_OWNER_ACCOUNT_NAME'; 'community/SET_COMMUNITY_OWNER_ACCOUNT_NAME';
...@@ -28,7 +27,6 @@ const COMMUNITY_HIVEMIND_OPERATION_ERROR = ...@@ -28,7 +27,6 @@ const COMMUNITY_HIVEMIND_OPERATION_ERROR =
const defaultState = fromJS({ const defaultState = fromJS({
communityTitle: '', communityTitle: '',
communityDescription: '', communityDescription: '',
communityNSFW: false,
communityOwnerName: '', communityOwnerName: '',
communityOwnerWifPassword: '', communityOwnerWifPassword: '',
communityCreatePending: false, communityCreatePending: false,
...@@ -49,10 +47,6 @@ export default function reducer(state = defaultState, action) { ...@@ -49,10 +47,6 @@ export default function reducer(state = defaultState, action) {
const description = fromJS(payload); const description = fromJS(payload);
return state.merge({ communityDescription: description }); return state.merge({ communityDescription: description });
} }
case SET_COMMUNITY_NSFW: {
const nsfw = fromJS(payload);
return state.merge({ communityNSFW: nsfw });
}
case SET_COMMUNITY_OWNER_ACCOUNT_NAME: { case SET_COMMUNITY_OWNER_ACCOUNT_NAME: {
const name = fromJS(payload); const name = fromJS(payload);
return state.merge({ communityOwnerName: name }); return state.merge({ communityOwnerName: name });
...@@ -107,10 +101,6 @@ export const setCommunityDescription = payload => ({ ...@@ -107,10 +101,6 @@ export const setCommunityDescription = payload => ({
type: SET_COMMUNITY_DESCRIPTION, type: SET_COMMUNITY_DESCRIPTION,
payload, payload,
}); });
export const setCommunityNSFW = payload => ({
type: SET_COMMUNITY_NSFW,
payload,
});
export const setCommunityOwnerAccountName = payload => ({ export const setCommunityOwnerAccountName = payload => ({
type: SET_COMMUNITY_OWNER_ACCOUNT_NAME, type: SET_COMMUNITY_OWNER_ACCOUNT_NAME,
......
...@@ -20,7 +20,7 @@ const generateAuth = (user, pass, type) => { ...@@ -20,7 +20,7 @@ const generateAuth = (user, pass, type) => {
}; };
}; };
const generateHivemindOperation = (action, params, actor_name) => { const generateHivemindOperation = (actor_name, action, params) => {
return [ return [
'custom_json', 'custom_json',
{ {
...@@ -49,14 +49,16 @@ export function* customOps(action) { ...@@ -49,14 +49,16 @@ export function* customOps(action) {
accountName, accountName,
communityTitle, communityTitle,
communityDescription, communityDescription,
communityNSFW,
communityOwnerName, communityOwnerName,
communityOwnerWifPassword, communityOwnerWifPassword,
createAccountSuccessCB, createAccountSuccessCB,
createAccountErrorCB, createAccountErrorCB,
broadcastOpsErrorCB, broadcastOpsErrorCB,
} = action.payload; } = action.payload;
yield call(wait, 9000);
// wait 3s for account creation to settle
yield call(wait, 3000);
try { try {
const communityOwnerPosting = auth.getPrivateKeys( const communityOwnerPosting = auth.getPrivateKeys(
communityOwnerName, communityOwnerName,
...@@ -65,28 +67,33 @@ export function* customOps(action) { ...@@ -65,28 +67,33 @@ export function* customOps(action) {
); );
const setRoleOperation = generateHivemindOperation( const setRoleOperation = generateHivemindOperation(
communityOwnerName,
'setRole', 'setRole',
{ {
community: communityOwnerName, community: communityOwnerName,
account: accountName, account: accountName,
role: 'admin', role: 'admin',
}, }
communityOwnerName,
communityOwnerPosting
); );
const updatePropsOperation = generateHivemindOperation( const updatePropsOperation = generateHivemindOperation(
communityOwnerName,
'updateProps', 'updateProps',
{ {
community: communityOwnerName, community: communityOwnerName,
props: { props: {
title: communityTitle, title: communityTitle,
about: communityDescription, about: communityDescription,
is_nsfw: !!communityNSFW,
}, },
}, }
communityOwnerName, );
communityOwnerPosting
const subscribeToCommunityOperation = generateHivemindOperation(
accountName,
'subscribe',