Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add The Ability To Create Prospective Ulog-communities #295

Merged
merged 6 commits into from
May 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
.save
*.css.map
*.css
*.DS_Store

# Created by .ignore support plugin (hsz.mobi)
### Node template
Expand Down
3 changes: 3 additions & 0 deletions src/client/Wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ export default class Wrapper extends React.PureComponent {
case 'grow':
this.props.history.push('/grow');
break;
case 'create-community':
this.props.history.push('/create-community');
break;
case 'news':
this.props.history.push('/trending');
break;
Expand Down
6 changes: 0 additions & 6 deletions src/client/app/Sidebar/RightSidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,6 @@ export default class RightSidebar extends React.Component {
}
}
const isWitnessVoted = checkVote();
const { category } = match.params;
const displayUlogCaption =
category &&
category.match(
/^(ulog-quotes|ulog-howto|ulog-diy|ulog-surpassinggoogle|teardrops|untalented|ulog-ned|ulography|ulog-gratefulvibes|ulog-resolutions|ulog-memes|ulog-blocktrades|ulog-showerthoughts|ulog-snookmademedoit|ulog-utopian|ulog-thejohalfiles|ulogifs|ulog-surfyogi|ulog-bobbylee|ulog-stellabelle|ulog-sweetsssj|ulog-dimimp|ulog-teamsteem|ulog-kusknee|ulog-papapepper|ulog-steemjet)$/,
);

return (
<div>
Expand Down
272 changes: 272 additions & 0 deletions src/client/community/CreateCommunity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
import React from 'react';
import { connect } from 'react-redux';
import { injectIntl } from 'react-intl';
import _ from 'lodash';
import PropTypes from 'prop-types';
import { message, Collapse, Button, List, Form, Input } from 'antd';
import ReactMarkdown from 'react-markdown';
import steemAPI from '../steemAPI';
import { getAuthenticatedUser, getIsEditorLoading, getUpvoteSetting } from '../reducers';
import Action from '../components/Button/Action';
import { notify } from '../app/Notification/notificationActions';
import { createPost } from '../post/Write/editorActions';
import * as community from '../helpers/community';

const version = require('../../../package.json').version;

@injectIntl
@connect(
state => ({
user: getAuthenticatedUser(state),
postCreationLoading: getIsEditorLoading(state),
upvote: getUpvoteSetting(state),
}),
{
notify,
createPost,
},
)
@Form.create()
class CreateCommunity extends React.Component {
static propTypes = {
postCreationLoading: PropTypes.bool.isRequired,
upvote: PropTypes.bool.isRequired,
user: PropTypes.shape().isRequired,
intl: PropTypes.shape().isRequired,
community: PropTypes.string,
form: PropTypes.shape().isRequired,
notify: PropTypes.func.isRequired,
createPost: PropTypes.func.isRequired,
};

static defaultProps = {
community: '',
currentInputValue: '',
visible: false,
};

static minAccountLength = 3;
static maxAccountLength = 16;

constructor(props) {
super(props);
// bind the component's methods so that it can be called within render() using this.method()
this.validateCommunity = this.validateCommunity.bind(this);
this.handleCreatePost = this.handleCreatePost.bind(this);
}

/*
* Validate inputted community name
*/
validateCommunity = (rule, value, callback) => {
const { intl } = this.props;

if (!value) {
callback();
return;
}

// prefix the community name with 'ulog-'
const ulogSubTag = 'ulog-' + value;

// if subtag is less than min length
if (ulogSubTag.length < CreateCommunity.minAccountLength) {
callback([
new Error(
intl.formatMessage(
{
id: 'subtag_too_short',
defaultMessage: 'Ulog subtag {subtag} is too short.',
},
{
subtag: ulogSubTag,
},
),
),
]);
return;
}

// if subtag is more than max length
if (ulogSubTag.length > CreateCommunity.maxAccountLength) {
callback([
new Error(
intl.formatMessage(
{
id: 'subtag_too_long',
defaultMessage: 'Ulog subtag {subtag} is too long.',
},
{
subtag: ulogSubTag,
},
),
),
]);
return;
}

// check if subtag already exists by using get_discussions API
steemAPI.sendAsync('get_discussions_by_created', [{ tag: ulogSubTag, limit: 1 }]).then(result => {
// if no posts already exists, return without error
if (result.length === 0) {
callback();
} else {
callback([
new Error(
intl.formatMessage(
{
id: 'community_error_found_tag',
defaultMessage: "Ulog community {subtag} already exists. Please try another one.",
},
{
subtag: ulogSubTag,
},
),
),
]);
}
});
};

/*
* Helper function to generate post data
*/
getQuickPostData = () => {
const { form } = this.props;
const postBody = "";
const community = form.getFieldValue('community');
const ulogSubTag = "ulog-" + community;
const postTitle = `A New Ulog Community - ${ulogSubTag} - Has Been Created!`;
const tags = [ulogSubTag];
const data = {
body: postBody,
title: postTitle,
reward: '50',
author: this.props.user.name,
parentAuthor: '',
lastUpdated: Date.now(),
upvote: this.props.upvote,
};

const metaData = {
community: 'ulogs',
app: `ulogs/${version}`,
format: 'markdown',
tags,
};

data.parentPermlink = ulogSubTag;
data.permlink = _.kebabCase(postTitle);
data.jsonMetadata = metaData;

return data;
};

/*
* Post creation handler when "Create Community" is clicked
*/
handleCreatePost = (e) => {
e.preventDefault();

const { form } = this.props;
// validate form fields
form.validateFieldsAndScroll((err, values) => {
// If no error, continue to submit community creation (create a post)
if (!err) {
const community = values.community;
const ulogSubTag = "ulog-" + community;

if (_.isEmpty(ulogSubTag)) {
this.props.notify(
this.props.intl.formatMessage({
id: 'community_error_empty_name',
defaultMessage: 'Community name cannot be empty.',
}),
'error',
);
return;
}
const data = this.getQuickPostData();
this.props.createPost(data);
}
});
};

render() {
const { intl, postCreationLoading } = this.props;
const { getFieldDecorator } = this.props.form;

// Style for the 'About' description
const customPanelStyle = {
marginBottom: 5,
overflow: 'hidden',
};

// Style for the sections
const customCardStyle = {
marginBottom: '10px',
marginTop: '10px',
};

return (
<div className="shifted">
<div className="container">
<div className="center" style={{ marginBottom: '50px' }}>
<h2 style={{ color: 'purple', textAlign: 'center' }}>Create A Ulog-Community</h2>
<Collapse defaultActiveKey={['1']}>
<Collapse.Panel header="About Communities" key="1" style={customPanelStyle}>
<ReactMarkdown source={community.aboutCommunities} />
</Collapse.Panel>
</Collapse>

<Collapse defaultActiveKey={['1']}>
<Collapse.Panel showArrow={false} key="1" disabled>
<List itemLayout="vertical" size="large">
<List.Item
key="Create A Ulog-Community"
>
<h3>Create A Ulog-Community</h3>
<div style={customCardStyle}>
<ReactMarkdown source={community.createCommunity} />
</div>
<Form onSubmit={this.handleCreatePost}>
<Form.Item>
{getFieldDecorator('community', {
rules: [
{
required: true,
message: intl.formatMessage({
id: 'community_error_empty',
defaultMessage: 'Community is required.',
}),
},
{ validator: this.validateCommunity },
],
})(
<Input
type="text"
placeholder="Names should be a maximum of 19 characters, only alphabets, no special characters."
/>
)}
</Form.Item>
<Action
primary
type="submit"
loading={postCreationLoading}
disabled={postCreationLoading}
>
{postCreationLoading ? "Creating Community..." : "Create Now"}
</Action>
</Form>
</List.Item>
</List>
</Collapse.Panel>
</Collapse>
</div>
</div>
</div>
);
}
}

export default CreateCommunity;
3 changes: 3 additions & 0 deletions src/client/components/Navigation/Topnav.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,9 @@ class Topnav extends React.Component {
<PopoverMenuItem key="grow">
<FormattedMessage id="grow" defaultMessage="Grow"/>
</PopoverMenuItem>
<PopoverMenuItem key="create-community">
<FormattedMessage id="create-community" defaultMessage="Create Community"/>
</PopoverMenuItem>
<PopoverMenuItem key="get-certified">
<FormattedMessage id="get_certified" defaultMessage='Get "Certified"'/>
</PopoverMenuItem>
Expand Down
3 changes: 3 additions & 0 deletions src/client/components/Sidebar/FeedSidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import CryptoTrendingCharts from './CryptoTrendingCharts';
import ChatBar from '../../components/Sidebar/ChatBar';
import UlogGamesExchanges from '../../components/Sidebar/UlogGamesExchanges';
import UlogCaption from '../../feed/UlogCaption';
import UlogGenericCaption from '../../feed/UlogGenericCaption';

@connect(
state => ({
Expand Down Expand Up @@ -52,11 +53,13 @@ class FeedSidebar extends React.Component {
tag.match(
/^(ulog-quotes|ulog-howto|ulog-diy|ulog-surpassinggoogle|teardrops|untalented|ulog-ned|ulography|ulog-gratefulvibes|ulog-resolutions|ulog-memes|ulog-blocktrades|ulog-showerthoughts|ulog-snookmademedoit|ulog-utopian|ulog-thejohalfiles|ulogifs|ulog-surfyogi|ulog-bobbylee|ulog-stellabelle|ulog-sweetsssj|ulog-dimimp|ulog-teamsteem|ulog-kusknee|ulog-papapepper|ulog-steemjet)$/,
);
const isStartsWithUlog = tag && tag.startsWith('ulog-');
return (
<div>
{!_.isEmpty(currentCrypto) && <CryptoTrendingCharts cryptos={[currentTag]} />}
<React.Fragment>
{displayUlogCaption && <UlogCaption category={tag} />}
{(!displayUlogCaption && isStartsWithUlog) && <UlogGenericCaption category={tag} />}
<OverseeingUloggers authenticatedUser={authenticatedUser} />
<UlogGamesExchanges isFetchingFollowingList={false} />
<ChatBar isFetchingFollowingList={false} authenticated={authenticated} />
Expand Down
4 changes: 2 additions & 2 deletions src/client/feed/Page.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ class Page extends React.Component {
) : (
<HeroBannerContainer />
)}
{displayUlogCaption && <UlogsBanner category={category} />}
{(!displayUlogCaption && isStartsWithUlog) && <UlogsBanner category={category} />}
{(authenticated && displayUlogCaption) && <UlogsBanner category={category} />}
{(authenticated && !displayUlogCaption && isStartsWithUlog) && <UlogsBanner category={category} />}
<MainMenu />
<div className="shifted">
<div className="feed-layout container">
Expand Down
52 changes: 52 additions & 0 deletions src/client/feed/UlogGenericCaption.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* eslint-disable react/no-unescaped-entities */

import React from 'react';
import PropTypes from 'prop-types';
import { Collapse, Button, Icon } from 'antd';
import { injectIntl, FormattedMessage } from 'react-intl';
import ReactMarkdown from 'react-markdown';
import { generic } from '../helpers/ulogCaptions';

@injectIntl
class UlogGenericCaption extends React.Component {
static propTypes = {
category: PropTypes.string.isRequired,
};

constructor(props) {
super(props);
}

render() {
const category = this.props.category;
const about = `About #${category}`;

return (
<div className="ulog-quotes">
<Collapse defaultActiveKey={['1']}>
<Collapse.Panel header={about} key="1">
<ReactMarkdown source={generic} />
<div
style={{
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginTop: '10px',
}}
>
<Button
type={'primary'}
href='/main-editor'
>
<FormattedMessage id="post_now" defaultMessage="Post now" />
</Button>
</div>
</Collapse.Panel>
</Collapse>
</div>
);
}
}

export default UlogGenericCaption;
Loading