Repository: busyorg/busy
Pull request #656 (2017-08-26 19:35:26)

Add textarea autoresize, notice for boost and improve preview
- Add block notice get boost
- Add textarea autoresize for post and comment
- Add preview on comment
- Remove tabs on editor and move preview under textarea

![image](https://user-images.githubusercontent.com/16245250/29744508-5290d0c6-8ad0-11e7-92d0-2eeab1d363ae.png)



Patch:
diff --git a/src/components/Comments/CommentForm.js b/src/components/Comments/CommentForm.js
index b8905689..c08ef2b5 100644
--- a/src/components/Comments/CommentForm.js
+++ b/src/components/Comments/CommentForm.js
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
 import ReactDOM from 'react-dom';
 import { injectIntl, FormattedMessage } from 'react-intl';
 import { Input, Icon } from 'antd';
+import Body, { remarkable } from '../Story/Body';
 import Avatar from '../Avatar';
 import './CommentForm.less';
 
@@ -120,11 +121,12 @@ class CommentForm extends React.Component {
         <Avatar username={username} size={!isSmall ? 40 : 32} />
         <div className="CommentForm__text">
           <Input
-            type="textarea"
             ref={ref => this.setInput(ref)}
             value={this.state.inputValue}
+            autosize={{ minRows: 2, maxRows: 6 }}
             onChange={this.handleCommentTextChange}
             placeholder={intl.formatMessage({ id: 'comment_placeholder', defaultMessage: 'Write a comment' })}
+            type="textarea"
             disabled={isLoading}
           />
           <p className="CommentForm__imagebox">
@@ -142,6 +144,12 @@ class CommentForm extends React.Component {
             {isLoading && <Icon type="loading" />}
             {isLoading ? <FormattedMessage id="comment_send_progress" defaultMessage="Commenting" /> : <FormattedMessage id="comment_send" defaultMessage="Comment" />}
           </button>
+          {this.state.inputValue &&
+            <div className="CommentForm__preview">
+              <span className="Editor__label"><FormattedMessage id="preview" defaultMessage="Preview" /></span>
+              <Body body={remarkable.render(this.state.inputValue)} />
+            </div>
+          }
         </div>
       </div>
     );
diff --git a/src/components/Comments/CommentForm.less b/src/components/Comments/CommentForm.less
index d95abcc2..7e456c57 100644
--- a/src/components/Comments/CommentForm.less
+++ b/src/components/Comments/CommentForm.less
@@ -9,10 +9,6 @@
   &__text {
     width: 100%;
     margin-left: 12px;
-
-    textarea {
-      resize: vertical;
-    }
   }
 
   &__imagebox {
@@ -43,6 +39,10 @@
     }
   }
 
+  &__preview {
+    margin: 20px 0;
+  }
+
   &__button {
     color: @white-darker;
     margin-top: 4px;
diff --git a/src/components/Editor/Editor.js b/src/components/Editor/Editor.js
index 45e68dee..e0f145af 100644
--- a/src/components/Editor/Editor.js
+++ b/src/components/Editor/Editor.js
@@ -5,14 +5,12 @@ import { injectIntl, FormattedMessage } from 'react-intl';
 import { HotKeys } from 'react-hotkeys';
 import { throttle } from 'lodash';
 import isArray from 'lodash/isArray';
-import { Icon, Checkbox, Form, Input, Select, Tabs } from 'antd';
+import { Icon, Checkbox, Form, Input, Select } from 'antd';
 import EditorToolbar from './EditorToolbar';
 import Action from '../Button/Action';
 import Body, { remarkable } from '../Story/Body';
 import './Editor.less';
 
-const TabPane = Tabs.TabPane;
-
 @injectIntl
 class Editor extends React.Component {
   static propTypes = {
@@ -387,33 +385,32 @@ class Editor extends React.Component {
           validateStatus={this.state.noContent ? 'error' : ''}
           help={this.state.noContent && intl.formatMessage({ id: 'story_error_empty', defaultMessage: "Story content can't be empty." })}
         >
-          <Tabs defaultActiveKey="1">
-            <TabPane tab={intl.formatMessage({ id: 'editor', defaultMessage: 'Editor' })} key="1">
-              <EditorToolbar onSelect={this.insertCode} />
-              <HotKeys keyMap={Editor.hotkeys} handlers={this.handlers}>
-                <Input
-                  onChange={this.onUpdate}
-                  ref={ref => this.setInput(ref)}
-                  type="textarea"
-                  placeholder={intl.formatMessage({ id: 'story_placeholder', defaultMessage: 'Write your story...' })}
-                />
-              </HotKeys>
-              <p className="Editor__imagebox">
-                <input type="file" id="inputfile" onChange={this.handleImageChange} />
-                <label htmlFor="inputfile">
-                  {(this.state.imageUploading) ? <Icon type="loading" /> : <i className="iconfont icon-picture" />}
-                  {(this.state.imageUploading) ?
-                    <FormattedMessage id="image_uploading" defaultMessage="Uploading your image..." /> :
-                    <FormattedMessage id="select_or_past_image" defaultMessage="Select image or paste it from the clipboard." />
-                  }
-                </label>
-              </p>
-            </TabPane>
-            <TabPane tab={intl.formatMessage({ id: 'preview', defaultMessage: 'Preview' })} key="2">
-              <Body full body={this.state.contentHtml} />
-            </TabPane>
-          </Tabs>
+          <EditorToolbar onSelect={this.insertCode} />
+          <HotKeys keyMap={Editor.hotkeys} handlers={this.handlers}>
+            <Input
+              autosize={{ minRows: 6, maxRows: 12 }}
+              onChange={this.onUpdate}
+              ref={ref => this.setInput(ref)}
+              type="textarea"
+              placeholder={intl.formatMessage({ id: 'story_placeholder', defaultMessage: 'Write your story...' })}
+            />
+          </HotKeys>
+          <p className="Editor__imagebox">
+            <input type="file" id="inputfile" onChange={this.handleImageChange} />
+            <label htmlFor="inputfile">
+              {(this.state.imageUploading) ? <Icon type="loading" /> : <i className="iconfont icon-picture" />}
+              {(this.state.imageUploading) ?
+                <FormattedMessage id="image_uploading" defaultMessage="Uploading your image..." /> :
+                <FormattedMessage id="select_or_past_image" defaultMessage="Select image or paste it from the clipboard." />
+              }
+            </label>
+          </p>
         </Form.Item>
+        {this.state.contentHtml &&
+          <Form.Item label={<span className="Editor__label"><FormattedMessage id="preview" defaultMessage="Preview" /></span>}>
+            <Body full body={this.state.contentHtml} />
+          </Form.Item>
+        }
         <Form.Item label={<span className="Editor__label"><FormattedMessage id="reward" defaultMessage="Rward" /></span>}>
           {getFieldDecorator('reward', { initialValue: '50' })(
             <Select onChange={this.onUpdate}>
diff --git a/src/components/Editor/Editor.less b/src/components/Editor/Editor.less
index ed4e1cc0..3dbc9979 100644
--- a/src/components/Editor/Editor.less
+++ b/src/components/Editor/Editor.less
@@ -3,10 +3,6 @@
 .Editor {
   padding-bottom: 24px;
 
-  textarea {
-    height: 200px !important;
-  }
-
   & .ant-form-item-label {
     position: relative;
     top: 8px !important;
diff --git a/src/components/Sidebar/GetBoost.js b/src/components/Sidebar/GetBoost.js
new file mode 100644
index 00000000..6eba5f05
--- /dev/null
+++ b/src/components/Sidebar/GetBoost.js
@@ -0,0 +1,15 @@
+import React from 'react';
+import { FormattedMessage } from 'react-intl';
+import './SidebarBlock.less';
+
+const StartNow = () =>
+  (<div className="SidebarBlock">
+    <h3 className="SidebarBlock__title">
+      <FormattedMessage id="get_boost" defaultMessage="Get the Busy boost!" />
+    </h3>
+    <p>
+      <FormattedMessage id="get_boost_content" defaultMessage='Want to boost your post? Add the topic "busy" and get a like from us.' />
+    </p>
+  </div>);
+
+export default StartNow;
diff --git a/src/components/Sidebar/SignUp.less b/src/components/Sidebar/SidebarBlock.less
similarity index 86%
rename from src/components/Sidebar/SignUp.less
rename to src/components/Sidebar/SidebarBlock.less
index 4b97a053..f3e59767 100644
--- a/src/components/Sidebar/SignUp.less
+++ b/src/components/Sidebar/SidebarBlock.less
@@ -1,7 +1,7 @@
 @import "../../styles/custom.less";
 
-.SignUp {
-  padding: 30px 20%;
+.SidebarBlock {
+  padding: 30px 40px;
   border-radius: @border-radius-base;
   text-align: center;
   color: @white;
@@ -9,14 +9,14 @@
   margin-bottom: 1em;
 }
 
-.SignUp__title {
+.SidebarBlock__title {
   font-size: 18px;
   margin-bottom: 26px;
   color: @white;
   font-weight: 500;
 }
 
-.SignUp__button {
+.SidebarBlock__button {
   .btn;
   .btn-default;
   .btn-ghost;
diff --git a/src/components/Sidebar/SignUp.js b/src/components/Sidebar/SignUp.js
index da6b0a9d..7f0980cb 100644
--- a/src/components/Sidebar/SignUp.js
+++ b/src/components/Sidebar/SignUp.js
@@ -1,14 +1,14 @@
 import React from 'react';
 import { FormattedMessage } from 'react-intl';
-import './SignUp.less';
+import './SidebarBlock.less';
 
 const SignUp = () =>
-  (<div className="SignUp">
-    <h3 className="SignUp__title">
+  (<div className="SidebarBlock">
+    <h3 className="SidebarBlock__title">
       <FormattedMessage id="new_to_busy" defaultMessage="New to Busy?" />
     </h3>
     <a target="_blank" rel="noopener noreferrer" href="https://steemit.com/pick_account">
-      <button className="SignUp__button">
+      <button className="SidebarBlock__button">
         <FormattedMessage id="signup" defaultMessage="Sign up" />
       </button>
     </a>
diff --git a/src/components/Sidebar/StartNow.js b/src/components/Sidebar/StartNow.js
index e0d8ea44..218f98fc 100644
--- a/src/components/Sidebar/StartNow.js
+++ b/src/components/Sidebar/StartNow.js
@@ -1,15 +1,15 @@
 import React from 'react';
 import { FormattedMessage } from 'react-intl';
 import { Link } from 'react-router-dom';
-import './StartNow.less';
+import './SidebarBlock.less';
 
 const StartNow = () =>
-  (<div className="StartNow">
-    <h3 className="StartNow__title">
+  (<div className="SidebarBlock">
+    <h3 className="SidebarBlock__title">
       <FormattedMessage id="never_written_post" defaultMessage="Never written a post?" />
     </h3>
     <Link to="/write">
-      <button className="StartNow__button">
+      <button className="SidebarBlock__button">
         <FormattedMessage id="start_now" defaultMessage="Start now" />
       </button>
     </Link>
diff --git a/src/components/Sidebar/StartNow.less b/src/components/Sidebar/StartNow.less
deleted file mode 100644
index d9f59728..00000000
--- a/src/components/Sidebar/StartNow.less
+++ /dev/null
@@ -1,36 +0,0 @@
-@import "../../styles/custom.less";
-
-.StartNow {
-  padding: 30px 40px;
-  border-radius: @border-radius-base;
-  text-align: center;
-  color: @white;
-  background-color: @purple;
-  margin-bottom: 1em;
-}
-
-.StartNow__title {
-  font-size: 18px;
-  margin-bottom: 26px;
-  color: @white;
-  font-weight: 500;
-}
-
-.StartNow__button {
-  .btn;
-  .btn-default;
-  .btn-ghost;
-
-  height: 46px !important;
-  color: @white !important;
-  font-size: 16px !important;
-
-  &:hover,
-  &:focus,
-  &:active,
-  &.active {
-    color: @purple !important;
-    background: @white !important;
-    border: none !important;
-  }
-}
diff --git a/src/locales/en.json b/src/locales/en.json
index 6c621bb3..16b40868 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -111,6 +111,8 @@
   "quote":"Add quote",
   "link":"Add link",
   "image":"Add image",
+  "get_boost":"Get the Busy boost!",
+  "get_boost_content":"Want to boost your post? Add the topic \"busy\" and get a like from us.",
   "drafts":"Drafts",
   "drafts_empty":"You don't have any draft saved",
   "draft_untitled":"Untitled draft",
diff --git a/src/post/Write/Write.js b/src/post/Write/Write.js
index 0152cb85..51931af9 100644
--- a/src/post/Write/Write.js
+++ b/src/post/Write/Write.js
@@ -6,6 +6,7 @@ import kebabCase from 'lodash/kebabCase';
 import debounce from 'lodash/debounce';
 import isArray from 'lodash/isArray';
 import 'url-search-params-polyfill';
+import GetBoost from '../../components/Sidebar/GetBoost';
 
 import { getAuthenticatedUser, getDraftPosts, getIsEditorLoading } from '../../reducers';
 
@@ -212,7 +213,9 @@ class Write extends React.Component {
       <div className="shifted">
         <div className="post-layout container">
           <Affix className="rightContainer" stickPosition={77}>
-            <div className="right">WIP</div>
+            <div className="right">
+              <GetBoost />
+            </div>
           </Affix>
           <div className="center">
             <Editor


Test patch:
diff --git a/src/stories/__snapshots__/stories.test.js.snap b/src/stories/__snapshots__/stories.test.js.snap
index a7b8c295..a4c1775e 100644
--- a/src/stories/__snapshots__/stories.test.js.snap
+++ b/src/stories/__snapshots__/stories.test.js.snap
@@ -320,9 +320,146 @@ exports[`Storyshots Editor Editor 1`] = `
       >
         <div
           className="ant-form-item-control "
-        />
+        >
+          <div
+            className="EditorToolbar"
+          >
+            <button
+              className="ant-btn EditorToolbar__button ant-dropdown-trigger"
+              onBlur={undefined}
+              onClick={[Function]}
+              onFocus={undefined}
+              onMouseDown={undefined}
+              onMouseEnter={[Function]}
+              onMouseLeave={[Function]}
+              onTouchStart={undefined}
+              type="button"
+            >
+              <i
+                className="iconfont icon-fontsize"
+              />
+              <span>
+                 
+              </span>
+              <i
+                className="anticon anticon-down"
+              />
+            </button>
+            <button
+              className="ant-btn EditorToolbar__button"
+              onBlur={undefined}
+              onClick={[Function]}
+              onFocus={undefined}
+              onMouseDown={undefined}
+              onMouseEnter={[Function]}
+              onMouseLeave={[Function]}
+              onTouchStart={undefined}
+              type="button"
+            >
+              <i
+                className="iconfont icon-bold"
+              />
+            </button>
+            <button
+              className="ant-btn EditorToolbar__button"
+              onBlur={undefined}
+              onClick={[Function]}
+              onFocus={undefined}
+              onMouseDown={undefined}
+              onMouseEnter={[Function]}
+              onMouseLeave={[Function]}
+              onTouchStart={undefined}
+              type="button"
+            >
+              <i
+                className="iconfont icon-italic"
+              />
+            </button>
+            <button
+              className="ant-btn EditorToolbar__button"
+              onBlur={undefined}
+              onClick={[Function]}
+              onFocus={undefined}
+              onMouseDown={undefined}
+              onMouseEnter={[Function]}
+              onMouseLeave={[Function]}
+              onTouchStart={undefined}
+              type="button"
+            >
+              <i
+                className="iconfont icon-q1"
+              />
+            </button>
+            <button
+              className="ant-btn EditorToolbar__button"
+              onBlur={undefined}
+              onClick={[Function]}
+              onFocus={undefined}
+              onMouseDown={undefined}
+              onMouseEnter={[Function]}
+              onMouseLeave={[Function]}
+              onTouchStart={undefined}
+              type="button"
+            >
+              <i
+                className="iconfont icon-link"
+              />
+            </button>
+            <button
+              className="ant-btn EditorToolbar__button"
+              onBlur={undefined}
+              onClick={[Function]}
+              onFocus={undefined}
+              onMouseDown={undefined}
+              onMouseEnter={[Function]}
+              onMouseLeave={[Function]}
+              onTouchStart={undefined}
+              type="button"
+            >
+              <i
+                className="iconfont icon-picture"
+              />
+            </button>
+          </div>
+          <div
+            onBlur={[Function]}
+            onFocus={[Function]}
+            size="large"
+            tabIndex="-1"
+          >
+            <textarea
+              className="ant-input"
+              disabled={false}
+              onChange={[Function]}
+              onKeyDown={[Function]}
+              placeholder="Write your story..."
+              style={Object {}}
+              type="textarea"
+            />
+          </div>
+          <p
+            className="Editor__imagebox"
+          >
+            <input
+              id="inputfile"
+              onChange={[Function]}
+              type="file"
+            />
+            <label
+              htmlFor="inputfile"
+            >
+              <i
+                className="iconfont icon-picture"
+              />
+              <span>
+                Select image or paste it from the clipboard.
+              </span>
+            </label>
+          </p>
+        </div>
       </div>
     </div>
+    
     <div
       className="ant-row ant-form-item"
       style={undefined}
@@ -1632,10 +1769,10 @@ exports[`Storyshots Sidebar Start now 1`] = `
   }
 >
   <div
-    className="StartNow"
+    className="SidebarBlock"
   >
     <h3
-      className="StartNow__title"
+      className="SidebarBlock__title"
     >
       <span>
         Never written a post?
@@ -1646,7 +1783,7 @@ exports[`Storyshots Sidebar Start now 1`] = `
       onClick={[Function]}
     >
       <button
-        className="StartNow__button"
+        className="SidebarBlock__button"
       >
         <span>
           Start Now