Merge pull request #879 from coralproject/questionbox

Question Box Builder
This commit is contained in:
Kim Gardner
2017-08-25 20:58:41 +01:00
committed by GitHub
22 changed files with 342 additions and 98 deletions
+2 -1
View File
@@ -9,6 +9,7 @@
"transform-object-assign",
"transform-object-rest-spread",
"transform-async-to-generator",
"transform-react-jsx"
"transform-react-jsx",
"syntax-dynamic-import"
]
}
@@ -4,7 +4,7 @@ import t from 'coral-framework/services/i18n';
import styles from './Configure.css';
import {Checkbox, Textfield} from 'react-mdl';
import {Card, Icon, TextArea} from 'coral-ui';
import MarkdownEditor from 'coral-admin/src/components/MarkdownEditor';
import MarkdownEditor from 'coral-framework/components/MarkdownEditor';
const TIMESTAMPS = {
weeks: 60 * 60 * 24 * 7,
@@ -12,10 +12,6 @@
padding: 0;
}
.wrapper ul ul {
padding-left: 20px
}
.checkbox {
vertical-align: top;
margin: 12px 12px 12px 0;
@@ -36,4 +32,4 @@
.hidden {
display: none;
}
}
@@ -1,5 +1,6 @@
import React from 'react';
import {Button, Checkbox, TextField} from 'coral-ui';
import {Button, Checkbox} from 'coral-ui';
import QuestionBoxBuilder from './QuestionBoxBuilder';
import styles from './ConfigureCommentStream.css';
@@ -55,17 +56,14 @@ export default ({handleChange, handleApply, changed, ...props}) => (
title: t('configure.enable_questionbox'),
description: t('configure.enable_questionbox_description')
}} />
<div className={`${props.questionBoxEnable ? null : styles.hidden}`} >
<TextField
id="qboxcontent"
onChange={handleChange}
rows={3}
value={props.questionBoxContent}
label={t('configure.include_question_here')}
/>
</div>
{
props.questionBoxEnable && <QuestionBoxBuilder
questionBoxIcon={props.questionBoxIcon}
questionBoxContent={props.questionBoxContent}
handleChange={handleChange}
/>
}
</li>
</ul>
</div>
</form>
@@ -0,0 +1,27 @@
.iconBubble{
position: absolute;
top: 8px;
left: 10px;
color: #9E9E9E;
font-size: 24px;
z-index: 0;
}
.iconPerson{
z-index: 2;
top: 12px;
left: 12px;
position: absolute;
font-size: 33px;
color: #262626;
}
.qbIconContainer {
position: relative;
border: 0;
color: white;
display: inline-block;
padding: 5px 20px;
vertical-align: middle;
width: 10px;
}
@@ -0,0 +1,13 @@
import React from 'react';
import cn from 'classnames';
import styles from './DefaultIcon.css';
import {Icon} from 'coral-ui';
const DefaultIcon = ({className}) => (
<div className={cn(styles.qbIconContainer, className)}>
<Icon name="chat_bubble" className={cn(styles.iconBubble)} />
<Icon name="person" className={cn(styles.iconPerson)} />
</div>
);
export default DefaultIcon;
@@ -0,0 +1,45 @@
.qbBuilder {
margin-left: 50px;
}
.qbItemIconList {
padding: 0;
margin: 10px 0;
}
.qbItemIcon {
background: #F0F0F0;
width: 45px;
height: 45px;
font-size: 24px;
text-align: center;
line-height: 45px;
color: #252525;
border-radius: 3px;
display: inline-block;
overflow: hidden;
margin-right: 10px;
position: relative;
border: solid 2px #F0F0F0;
transition: border 0.3s cubic-bezier(.4,0,.2,1);
}
.qbItemIcon:hover {
cursor: pointer;
}
.qbItemIconActive {
border: solid 2px #00796B;
}
.defaultIcon {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.qb {
margin: 10px 0;
}
@@ -0,0 +1,98 @@
import React from 'react';
import QuestionBox from 'talk-plugin-questionbox/QuestionBox';
import {Icon, Spinner} from 'coral-ui';
import DefaultIcon from './DefaultIcon';
import cn from 'classnames';
import styles from './QuestionBoxBuilder.css';
class QuestionBoxBuilder extends React.Component {
constructor() {
super();
this.state = {
loading: true
};
}
componentWillMount() {
this.loadEditor();
}
async loadEditor() {
const MarkdownEditor = await import('coral-framework/components/MarkdownEditor');
return this.setState({
loading : false,
MarkdownEditor
});
}
render() {
const {handleChange, questionBoxIcon, questionBoxContent} = this.props;
const {loading, MarkdownEditor} = this.state;
if (loading) {
return <Spinner/>;
}
return (
<div className={styles.qbBuilder}>
<h4>Include an Icon</h4>
<ul className={styles.qbItemIconList}>
<li className={cn(
styles.qbItemIcon,
{[styles.qbItemIconActive]: questionBoxIcon === 'default'}
)}
id="qboxicon"
onClick={handleChange}
data-icon="default" >
<DefaultIcon className={styles.defaultIcon} />
</li>
<li className={cn(
styles.qbItemIcon,
{[styles.qbItemIconActive]: questionBoxIcon === 'forum'}
)}
id="qboxicon"
onClick={handleChange}
data-icon="forum" >
<Icon name="forum" />
</li>
<li className={cn(
styles.qbItemIcon,
{[styles.qbItemIconActive]: questionBoxIcon === 'build'}
)}
id="qboxicon"
onClick={handleChange}
data-icon="build" >
<Icon name="build" />
</li>
<li className={cn(
styles.qbItemIcon,
{[styles.qbItemIconActive]: questionBoxIcon === 'format_quote'}
)}
id="qboxicon"
onClick={handleChange}
data-icon="format_quote" >
<Icon name="format_quote" />
</li>
</ul>
<QuestionBox
className={styles.qb}
enable={true}
icon={questionBoxIcon}
content={questionBoxContent}
/>
<MarkdownEditor
value={questionBoxContent}
onChange={(value) => handleChange({}, {questionBoxContent: value})}
/>
</div>
);
}
}
export default QuestionBoxBuilder;
@@ -27,10 +27,9 @@ class ConfigureStreamContainer extends Component {
handleApply (e) {
e.preventDefault();
const {elements} = e.target;
const {questionBoxIcon, questionBoxContent} = this.state.dirtySettings;
const premod = elements.premod.checked;
const questionBoxEnable = elements.qboxenable.checked;
const questionBoxContent = elements.qboxcontent.value;
const premodLinksEnable = elements.plinksenable.checked;
const {changed} = this.state;
@@ -38,6 +37,7 @@ class ConfigureStreamContainer extends Component {
moderation: premod ? 'PRE' : 'POST',
questionBoxEnable,
questionBoxContent,
questionBoxIcon,
premodLinksEnable
};
@@ -51,14 +51,18 @@ class ConfigureStreamContainer extends Component {
}
}
handleChange (e) {
const changes = {};
handleChange (e, newChanges) {
let changes = {};
if (changes) {
changes = {...newChanges};
}
if (e.target && e.target.id === 'qboxenable') {
changes.questionBoxEnable = e.target.checked;
}
if (e.target && e.target.id === 'qboxcontent') {
changes.questionBoxContent = e.target.value;
if (e.currentTarget && e.currentTarget.id === 'qboxicon') {
changes.questionBoxIcon = e.currentTarget.dataset.icon;
}
if (e.target && e.target.id === 'plinksenable') {
changes.premodLinksEnable = e.target.value;
@@ -105,6 +109,7 @@ class ConfigureStreamContainer extends Component {
changed={this.state.changed}
premodLinksEnable={dirtySettings.premodLinksEnable}
premod={premod}
questionBoxIcon={dirtySettings.questionBoxIcon}
questionBoxEnable={dirtySettings.questionBoxEnable}
questionBoxContent={dirtySettings.questionBoxContent}
/>
@@ -129,6 +129,7 @@ class Stream extends React.Component {
<QuestionBox
content={asset.settings.questionBoxContent}
enable={asset.settings.questionBoxEnable}
icon={asset.settings.questionBoxIcon}
/>
{!banned &&
temporarilySuspended &&
@@ -247,6 +247,7 @@ const fragments = {
premodLinksEnable
questionBoxEnable
questionBoxContent
questionBoxIcon
closeTimeout
closedMessage
charCountEnable
+6 -61
View File
@@ -79,6 +79,12 @@ body {
}
/* Info Box Styles */
.hidden {
visibility: hidden;
display: none;
}
.talk-plugin-infobox-info {
top: 0;
border: 0;
@@ -93,7 +99,6 @@ body {
border-radius: 2px;
}
.talk-plugin-infobox-info em{
font-style: italic;
}
@@ -113,66 +118,6 @@ body {
}
/* Question Box Styles */
.talk-plugin-questionbox-info {
top: 0;
border: 0;
background: #F0F0F0;
color: black;
width: 100%;
text-align: left;
padding-left: 0px;
margin-bottom: 0px;
font-weight: bold;
font-size: 14px;
overflow: hidden;
min-height: 50px;
display: flex;
}
.talk-plugin-questionbox-icon.bubble{
position: absolute;
top: 8px;
left: 10px;
color: #9E9E9E;
font-size: 24px;
z-index: 0;
}
.talk-plugin-questionbox-icon.person{
z-index: 2;
top: 12px;
left: 12px;
position: absolute;
font-size: 33px;
color: #262626;
}
.talk-plugin-questionbox-box {
position: relative;
border: 0;
color: white;
padding: 20px;
margin-left: 0px !important;
margin-right: 10px;
display: inline-block;
width: 10px;
min-height: 100%;
padding: 5px 20px;
vertical-align: middle;
}
.talk-plugin-questionbox-content {
padding: 5px;
display: flex;
align-items: center;
justify-content: center;
font-weight: 400;
}
.hidden {
visibility: hidden;
display: none;
}
.talk-stream-comments-container {
position: relative;
@@ -0,0 +1,23 @@
import React, {PureComponent, PropTypes} from 'react';
import marked from 'marked';
const renderer = new marked.Renderer();
// Set link target to `_parent` to work properly in an embed.
renderer.link = (href, title, text) =>
`<a target="_parent" href="${href}" ${title ? `title="${title}"` : ''}>${text}</a>`;
marked.setOptions({renderer});
export default class Markdown extends PureComponent {
render() {
const {content, ...rest} = this.props;
const __html = marked(content);
return <div {...rest} dangerouslySetInnerHTML={{__html}} />;
}
}
Markdown.propTypes = {
content: PropTypes.string,
};
@@ -467,7 +467,6 @@ $fullscreenZIndex: 10;
text-align: center;
text-decoration: none!important;
color: #2c3e50!important;
width: 30px;
height: 30px;
margin: 0;
border: 1px solid transparent;
@@ -475,6 +474,8 @@ $fullscreenZIndex: 10;
cursor: pointer;
outline: 0;
margin-right: 2px;
font-size: 1.5em;
width: 25px;
&.active {
background: #fcfcfc;
border-color: #95a5a6;
+1 -1
View File
@@ -1,5 +1,5 @@
import React from 'react';
import Markdown from './Markdown';
import Markdown from 'coral-framework/components/Markdown';
const packagename = 'talk-plugin-infobox';
@@ -0,0 +1,70 @@
.qbInfo {
top: 0;
border: 0;
background: #F0F0F0;
color: black;
width: 100%;
text-align: left;
padding-left: 0px;
margin-bottom: 0px;
font-weight: bold;
font-size: 14px;
overflow: hidden;
min-height: 50px;
display: flex;
border-radius: 3px;
}
.icon {
z-index: 2;
top: 12px;
left: 12px;
position: absolute;
font-size: 33px;
color: #262626;
}
.iconBubble{
position: absolute;
top: 8px;
left: 10px;
color: #9E9E9E;
font-size: 24px;
z-index: 0;
}
.iconPerson{
z-index: 2;
top: 12px;
left: 12px;
position: absolute;
font-size: 33px;
color: #262626;
}
.qbIconContainer {
position: relative;
border: 0;
color: white;
padding: 20px;
margin-left: 0px !important;
margin-right: 10px;
display: inline-block;
width: 10px;
min-height: 100%;
padding: 5px 20px;
vertical-align: middle;
}
.qbContent {
padding: 5px;
display: flex;
align-items: center;
justify-content: center;
font-weight: 400;
}
.hidden {
visibility: hidden;
display: none;
}
+25 -11
View File
@@ -1,17 +1,31 @@
import React from 'react';
const packagename = 'talk-plugin-questionbox';
import cn from 'classnames';
import styles from './QuestionBox.css';
import {Icon} from 'coral-ui';
import Markdown from 'coral-framework/components/Markdown';
import Slot from 'coral-framework/components/Slot';
const QuestionBox = ({enable, content}) =>
<div className={`${packagename}-info ${enable ? null : 'hidden'}` }>
<div className={`${packagename}-box`}>
<i className={`${packagename}-icon material-icons bubble`}>chat_bubble</i>
<i className={`${packagename}-icon material-icons person`}>person</i>
const QuestionBox = ({content, enable, icon = '', className = ''}) => (
<div className={cn(styles.qbInfo, {[styles.hidden]: !enable}, 'questionbox-info', className)}>
{
icon === 'default' ? (
<div className={cn(styles.qbIconContainer)}>
<Icon name="chat_bubble" className={cn(styles.iconBubble)} />
<Icon name="person" className={cn(styles.iconPerson)} />
</div>
) : (
<div className={cn(styles.qbIconContainer)}>
<Icon name={icon} className={cn(styles.icon)} />
</div>
)
}
<div className={cn(styles.qbContent, 'questionbox-content')}>
<Markdown content={content} />
</div>
<Slot fill="streamQuestionArea" />
</div>
<div className={`${packagename}-content`}>
{content}
</div>
<Slot fill="streamQuestionArea" />
</div>;
);
export default QuestionBox;
+1
View File
@@ -545,6 +545,7 @@ type Settings {
premodLinksEnable: Boolean
questionBoxEnable: Boolean
questionBoxContent: String
questionBoxIcon: String
closeTimeout: Int
closedMessage: String
charCountEnable: Boolean
+4
View File
@@ -33,6 +33,10 @@ const SettingSchema = new Schema({
type: Boolean,
default: false
},
questionBoxIcon: {
type: String,
default: 'default'
},
questionBoxContent: {
type: String,
default: ''
+1
View File
@@ -144,6 +144,7 @@
"babel-jest": "^19.0.0",
"babel-loader": "^6.4.1",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-async-to-generator": "^6.16.0",
"babel-plugin-transform-class-properties": "^6.23.0",
"babel-plugin-transform-decorators-legacy": "^1.3.4",