Skip to content

Commit

Permalink
add HelpContent component (steemit#494)
Browse files Browse the repository at this point in the history
* add HelpContent component

* update shrinkwrap file

* add faq page

* add 'show beginner's guide' link in blog's empty state section

* update copy and comments
  • Loading branch information
Valentine Zavgorodnev authored Oct 17, 2016
1 parent c8ae7fc commit 64f4995
Show file tree
Hide file tree
Showing 14 changed files with 355 additions and 10 deletions.
3 changes: 3 additions & 0 deletions app/ResolveRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ export default function resolveRoute(path)
if (path === '/about.html') {
return {page: 'About'};
}
if (path === '/faq.html') {
return {page: 'Faq'};
}
if (path === '/login.html') {
return {page: 'Login'};
}
Expand Down
4 changes: 4 additions & 0 deletions app/RootRoute.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ export default {
//require.ensure([], (require) => {
cb(null, [require('app/components/pages/About')]);
//});
} else if (route.page === 'Faq') {
//require.ensure([], (require) => {
cb(null, [require('app/components/pages/Faq')]);
//});
} else if (route.page === 'Login') {
//require.ensure([], (require) => {
cb(null, [require('app/components/pages/Login')]);
Expand Down
5 changes: 5 additions & 0 deletions app/components/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ class App extends React.Component {
{translate("whitepaper")}
</a>
</li>
<li>
<a href="/faq.html" onClick={this.navigate}>
FAQ
</a>
</li>
<li>
<a onClick={() => depositSteem()}>
{translate("buy_steem")}
Expand Down
4 changes: 2 additions & 2 deletions app/components/cards/PostsList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class PostsList extends React.Component {
loading: PropTypes.bool.isRequired,
category: PropTypes.string,
loadMore: PropTypes.func,
emptyText: PropTypes.string,
emptyText: PropTypes.object,
showSpam: PropTypes.bool,
fetchState: PropTypes.func.isRequired,
pathname: PropTypes.string,
Expand Down Expand Up @@ -157,7 +157,7 @@ class PostsList extends React.Component {
const {account} = this.props
const {thumbSize, showPost} = this.state
if (!loading && !posts.length && emptyText) {
return <Callout body={emptyText} type="success" />;
return <Callout>{emptyText}</Callout>;
}
const renderSummary = items => items.map(({item, ignore, netVoteSign, authorRepLog10}) => <li key={item}>
<PostSummary account={account} post={item} currentCategory={category} thumbSize={thumbSize}
Expand Down
6 changes: 3 additions & 3 deletions app/components/elements/Callout.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';

export default ({title, body, type = 'alert'}) => {
export default ({title, children, type}) => {
return <div className="row">
<div className="column">
<div className={'callout ' + type}>
<div className={'callout' + (type ? ` ${type}` : '')}>
<h4>{title}</h4>
<p>{body}</p>
<div>{children}</div>
</div>
</div>
</div>
Expand Down
110 changes: 110 additions & 0 deletions app/components/elements/HelpContent.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import React from "react";
import MarkdownViewer from 'app/components/cards/MarkdownViewer';

if (!process.env.BROWSER) {
// please note we don't need to define require.context for client side rendering because it's defined by webpack
const path = require('path');
const fs = require('fs');
function getFolderContents(folder, recursive) {
return fs.readdirSync(folder).reduce(function (list, file) {
var name = path.resolve(folder, file);
var isDir = fs.statSync(name).isDirectory();
return list.concat((isDir && recursive) ? getFolderContents(name, recursive) : [name]);
}, []);
}
function requireContext(folder, recursive, pattern) {
var normalizedFolder = path.resolve(path.dirname(module.filename), folder);
var folderContents = getFolderContents(normalizedFolder, recursive)
.filter(function (item) {
if (item === module.filename) return false;
return pattern.test(item);
});

var keys = function () {
return folderContents;
};
var returnContext = function returnContext(item) {
return fs.readFileSync(item, 'utf8');//require(item);
};
returnContext.keys = keys;
return returnContext;
}
require.context = requireContext;
}

let req = require.context("../../help", true, /\.md/);
let HelpData = {};

function split_into_sections(str) {
let sections = str.split(/\[#\s?(.+?)\s?\]/);
if (sections.length === 1) return sections[0];
if (sections[0].length < 4) sections.splice(0, 1);
sections = sections.reduce((result, n) => {
let last = result.length > 0 ? result[result.length-1] : null;
if (!last || last.length === 2) { last = [n]; result.push(last); }
else last.push(n);
return result;
}, []);
return sections.reduce((result, n) => {
result[n[0]] = n[1];
return result;
}, {});
}

export default class HelpContent extends React.Component {

static propTypes = {
path: React.PropTypes.string.isRequired,
section: React.PropTypes.string
};

constructor(props) {
super(props);
this.locale = 'en';
}

componentWillMount() {
const md_file_path_regexp = new RegExp(`\/${this.locale}\/(.+)\.md$`)
req.keys().filter(a => {
return a.indexOf(`/${this.locale}/`) !== -1;
}).forEach(filename => {
var res = filename.match(md_file_path_regexp);
let key = res[1];
let help_locale = HelpData[this.locale];
if (!help_locale) HelpData[this.locale] = help_locale = {};
let content = req(filename);
help_locale[key] = split_into_sections(content);
});
}

setVars(str) {
return str.replace(/(\{.+?\})/gi, (match, text) => {
let key = text.substr(1, text.length - 2);
let value = this.props[key] !== undefined ? this.props[key] : text;
return value;
});
}

render() {
if (!HelpData[this.locale]) {
console.error(`missing locale '${this.locale}' help files`);
return null;
}
let value = HelpData[this.locale][this.props.path];
if (!value && this.locale !== "en") {
console.warn(`missing path '${this.props.path}' for locale '${this.locale}' help files, rolling back to 'en'`);
value = HelpData['en'][this.props.path];
}
if (!value) {
console.error(`help file not found '${this.props.path}' for locale '${this.locale}'`);
return null;
}
if (this.props.section) value = value[this.props.section];
if (!value) {
console.error(`help section not found ${this.props.path}#${this.props.section}`);
return null;
}
value = this.setVars(value);
return <MarkdownViewer className="HelpContent" text={value} />;
}
}
19 changes: 19 additions & 0 deletions app/components/pages/Faq.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import HelpContent from 'app/components/elements/HelpContent';

class Faq extends React.Component {
render() {
return (
<div className="row">
<div className="column large-8 medium-10 small-12">
<HelpContent path="faq"/>
</div>
</div>
);
}
}

module.exports = {
path: 'faq.html',
component: Faq
};
2 changes: 1 addition & 1 deletion app/components/pages/RecoverAccountStep2.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class RecoverAccountStep2 extends React.Component {
}
const {account_to_recover} = this.props;
if (!account_to_recover) {
return <Callout body="Account recovery request is not confirmed yes, please get back later, thank you for your patience." />;
return <Callout body="Account recovery request is not confirmed yes, please try back later, thank you for your patience." type="alert" />;
}
const {oldPassword, valid, error, progress_status, name_error, success} = this.state;
const submit_btn_class = 'button action' + (!valid || !oldPassword ? ' disabled' : '');
Expand Down
8 changes: 7 additions & 1 deletion app/components/pages/UserProfile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,14 @@ export default class UserProfile extends React.Component {
}
} else if(!section || section === 'blog') {
if (account.blog) {
const emptyText = isMyAccount ? <div>
Looks like you haven't posted anything yet.<br />
<Link to="/submit.html">Submit a Story</Link><br />
<Link to="/steemit/@thecryptofiend/the-missing-faq-a-beginners-guide-to-using-steemit">Read The Beginner's Guide</Link>
</div>:
<div>Looks like {account.name} hasn't started blogging yet!</div>;
tab_content = <PostsList
emptyText={`Looks like ${account.name} hasn't started blogging yet!`}
emptyText={emptyText}
account={account.name}
posts={account.blog}
loading={fetching}
Expand Down
Loading

0 comments on commit 64f4995

Please sign in to comment.