Merge branch 'master' into flag-reason

This commit is contained in:
Belén Curcio
2017-06-27 16:53:56 -03:00
committed by GitHub
23 changed files with 342 additions and 257 deletions
+1
View File
@@ -12,4 +12,5 @@ plugins/*
!plugins/coral-plugin-love
!plugins/coral-plugin-viewing-options
!plugins/coral-plugin-comment-content
!plugins/talk-plugin-permalink
node_modules
+1
View File
@@ -25,5 +25,6 @@ plugins/*
!plugins/coral-plugin-love
!plugins/coral-plugin-viewing-options
!plugins/coral-plugin-comment-content
!plugins/talk-plugin-permalink
**/node_modules/*
@@ -0,0 +1,51 @@
.root {
background-color: #fff;
border: 1px solid #ccc;
overflow: hidden;
padding-left: 5px;
padding-top: 5px;
}
.rootFocuesd {
border-color: rgb(142, 76, 65);
}
.tag {
background-color: rgb(255, 220, 214);
border-radius: 2px;
border: 1px solid rgb(244, 126, 107);
color: rgb(244, 126, 107);
display: inline-block;
font-family: sans-serif;
font-size: 13px;
font-weight: 400;
margin-bottom: 5px;
margin-right: 5px;
padding: 5px;
}
.tagRemove {
cursor: pointer;
font-weight: bold;
color: rgb(101, 24, 23);
&::before {
content: " ×";
}
}
.input > input {
background: transparent;
border: 0;
color: #777;
font-family: sans-serif;
font-size: 13px;
font-weight: 400;
margin-bottom: 6px;
margin-top: 1px;
outline: none;
padding: 5px;
}
@@ -0,0 +1,31 @@
import React from 'react';
import TagsInput from 'react-tagsinput';
import styles from './TagsInput.css';
import AutosizeInput from 'react-input-autosize';
const autosizingRenderInput = ({onChange, value, addTag: _, ...other}) =>
<AutosizeInput type='text' onChange={onChange} value={value} {...other} />;
export default (props) => {
return (
<TagsInput
addOnBlur={true}
addOnPaste={true}
pasteSplit={(data) => data.split(',').map((d) => d.trim())}
className={styles.root}
focusedClassName={styles.rootFocus}
renderInput={autosizingRenderInput}
{...props}
tagProps={{
className: styles.tag,
classNameRemove: styles.tagRemove,
...props.tagProps,
}}
inputProps={{
className: styles.input,
...props.inputProps,
}}
/>
);
};
@@ -136,13 +136,6 @@
resize: none;
}
#bannedWordlist, #suspectWordlist {
display: block;
input {
width: 100%;
}
}
.customCSSInput {
width: 100%;
font-size: 14px;
@@ -1,7 +1,7 @@
import React from 'react';
import {Card} from 'coral-ui';
import styles from './Configure.css';
import TagsInput from 'react-tagsinput';
import TagsInput from 'coral-admin/src/components/TagsInput';
import t from 'coral-framework/services/i18n';
const Domainlist = ({domains, onChangeDomainlist}) => {
@@ -14,8 +14,6 @@ const Domainlist = ({domains, onChangeDomainlist}) => {
<TagsInput
value={domains}
inputProps={{placeholder: 'URL'}}
addOnPaste={true}
pasteSplit={(data) => data.split(',').map((d) => d.trim())}
onChange={(tags) => onChangeDomainlist('whitelist', tags)}
/>
</div>
@@ -1,6 +1,6 @@
import React from 'react';
import t from 'coral-framework/services/i18n';
import TagsInput from 'react-tagsinput';
import TagsInput from 'coral-admin/src/components/TagsInput';
import styles from './Configure.css';
import {Card} from 'coral-ui';
@@ -13,8 +13,6 @@ const Wordlist = ({suspectWords, bannedWords, onChangeWordlist}) => (
<TagsInput
value={bannedWords}
inputProps={{placeholder: 'word or phrase'}}
addOnPaste={true}
pasteSplit={(data) => data.split(',').map((d) => d.trim())}
onChange={(tags) => onChangeWordlist('banned', tags)}
/>
</div>
@@ -26,8 +24,6 @@ const Wordlist = ({suspectWords, bannedWords, onChangeWordlist}) => (
<TagsInput
value={suspectWords}
inputProps={{placeholder: 'word or phrase'}}
addOnPaste={true}
pasteSplit={(data) => data.split(',').map((d) => d.trim())}
onChange={(tags) => onChangeWordlist('suspect', tags)} />
</div>
</Card>
@@ -1,7 +1,7 @@
import React from 'react';
import styles from './style.css';
import {Button, Card} from 'coral-ui';
import TagsInput from 'react-tagsinput';
import TagsInput from 'coral-admin/src/components/TagsInput';
import t from 'coral-framework/services/i18n';
@@ -16,9 +16,6 @@ const PermittedDomainsStep = (props) => {
<TagsInput
value={domains}
inputProps={{placeholder: 'URL'}}
addOnBlur={true}
addOnPaste={true}
pasteSplit={(data) => data.split(',').map((d) => d.trim())}
onChange={(tags) => handleDomainsChange(tags)}
/>
</Card>
@@ -1,6 +1,5 @@
import React, {PropTypes} from 'react';
import PermalinkButton from 'coral-plugin-permalinks/PermalinkButton';
import AuthorName from 'coral-plugin-author-name/AuthorName';
import TagLabel from 'coral-plugin-tag-label/TagLabel';
import PubDate from 'coral-plugin-pubdate/PubDate';
@@ -509,19 +508,18 @@ export default class Comment extends React.Component {
currentUserId={currentUser && currentUser.id}
/>
</ActionButton>}
</div>
<div className="commentActionsRight comment__action-container">
<Slot
fill="commentActions"
wrapperComponent={ActionButton}
data={this.props.data}
root={this.props.root}
asset={asset}
comment={comment}
commentId={comment.id}
inline
/>
</div>
<div className="commentActionsRight comment__action-container">
<ActionButton>
<PermalinkButton articleURL={asset.url} commentId={comment.id} />
</ActionButton>
<ActionButton>
<FlagComment
flaggedByCurrentUser={!!myFlag}
@@ -335,33 +335,6 @@ button.comment__action-button[disabled],
display: inline-block;
}
.coral-plugin-permalinks-container {
/*position: relative;*/
z-index: 2;
}
.coral-plugin-permalinks-popover {
display: none;
background-color: white;
border: 1px solid black;
position: absolute;
padding: 5px;
}
.coral-plugin-permalinks-popover.active {
display: block;
}
.coral-plugin-permalinks-copy-field {
display: block;
width: calc(100% - 5px);
}
.coral-plugin-permalinks-copied-text {
float: right;
margin: 8px;
}
/* Flag Styles */
.coral-plugin-flags-popup-form {
@@ -1,81 +0,0 @@
import React, {PropTypes} from 'react';
const name = 'coral-plugin-permalinks';
import {Button} from 'coral-ui';
import styles from './styles.css';
import ClickOutside from 'coral-framework/components/ClickOutside';
import t from 'coral-framework/services/i18n';
export default class PermalinkButton extends React.Component {
static propTypes = {
articleURL: PropTypes.string.isRequired,
commentId: PropTypes.string.isRequired
}
constructor (props) {
super(props);
this.state = {popoverOpen: false, copySuccessful: null, copyFailure: null};
this.toggle = this.toggle.bind(this);
this.copyPermalink = this.copyPermalink.bind(this);
}
toggle () {
// I wish I could position this with a stylesheet, but top-level comments with
// nested replies throws everything off, as well as very long comments
this.popover.style.top = `${this.linkButton.offsetTop - 80}px`;
this.setState({popoverOpen: !this.state.popoverOpen});
}
handleClickOutside = () => {
this.setState({popoverOpen: false});
}
copyPermalink () {
this.permalinkInput.select();
try {
document.execCommand('copy');
this.setState({copySuccessful: true, copyFailure: null});
} catch (err) {
this.setState({copyFailure: true, copySuccessful: null});
}
setTimeout(() => {
this.setState({copyFailure: null, copySuccessful: null});
}, 3000);
}
render () {
const {copySuccessful, copyFailure} = this.state;
return (
<ClickOutside onClickOutside={this.handleClickOutside}>
<div className={`${name}-container`}>
<button
ref={(ref) => this.linkButton = ref}
onClick={this.toggle}
className={`${name}-button`}>
{t('permalink')}
<i className={`${name}-icon material-icons`} aria-hidden={true}>link</i>
</button>
<div
ref={(ref) => this.popover = ref}
className={`${name}-popover ${styles.container} ${this.state.popoverOpen ? 'active' : ''}`}>
<input
className={`${name}-copy-field`}
type='text'
ref={(input) => this.permalinkInput = input}
value={`${this.props.articleURL}#${this.props.commentId}`}
onChange={() => {}} />
<Button className={`${name}-copy-button ${copySuccessful ? styles.success : ''} ${copyFailure ? styles.failure : ''}`}
onClick={this.copyPermalink} >
{!copyFailure && !copySuccessful && 'Copy'}
{copySuccessful && 'Copied'}
{copyFailure && 'Not supported'}
</Button>
</div>
</div>
</ClickOutside>
);
}
}
-67
View File
@@ -1,67 +0,0 @@
.container {
border-radius: 3px;
padding: 15px 10px;
box-sizing: border-box;
/* box-shadow: 3px 3px 5px 0 rgba(0, 0, 0, 0.3); */
border: solid 1px rgba(153, 153, 153, 0.33);
left: 0;
width: 100%;
&::before {
content: '';
border: 10px solid transparent;
border-top-color: white;
position: absolute;
right: 7em;
bottom: -20px;
z-index: 2;
}
&::after{
content: '';
border: 10px solid transparent;
border-top-color: rgba(153, 153, 153, 0.33);
position: absolute;
right: 7em;
bottom: -21px;
z-index: 1;
}
input {
display: inline-block;
width: calc(100% - 78px);
padding: 8px;
border-radius: 3px;
border: solid 1px #e0e0e0;
height: 32px;
box-sizing: border-box;
font-size: 1em;
}
button {
display: inline-block;
float: right;
box-sizing: border-box;
margin: 0;
background-color: #e0e0e0;
font-size: 1em;
width: auto;
height: auto;
padding: 2px;
transition: background-color 0.4s ease;
&:hover{
color: black;
}
&.success {
background-color: #00897B;
color: white;
}
&.failure {
background-color: #FF5252;
color: white;
}
}
}
+2 -1
View File
@@ -109,6 +109,7 @@
"passport-local": "^1.0.0",
"prop-types": "^15.5.10",
"react-apollo": "^1.1.0",
"react-input-autosize": "^1.1.4",
"react-recaptcha": "^2.2.6",
"react-toastify": "^1.5.0",
"react-transition-group": "^1.1.3",
@@ -195,7 +196,7 @@
"react-mdl-selectfield": "^0.2.0",
"react-redux": "^4.4.5",
"react-router": "^3.0.0",
"react-tagsinput": "^3.14.0",
"react-tagsinput": "^3.17.0",
"redux": "^3.6.0",
"redux-mock-store": "^1.2.1",
"redux-thunk": "^2.1.0",
@@ -1 +1,2 @@
export {Slot} from 'coral-framework/components';
export {default as ClickOutside} from 'coral-framework/components/ClickOutside';
@@ -0,0 +1,14 @@
{
"presets": [
"es2015"
],
"plugins": [
"add-module-exports",
"transform-class-properties",
"transform-decorators-legacy",
"transform-object-assign",
"transform-object-rest-spread",
"transform-async-to-generator",
"transform-react-jsx"
]
}
@@ -0,0 +1,23 @@
{
"env": {
"browser": true,
"es6": true,
"mocha": true
},
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"jsx": true
}
},
"parser": "babel-eslint",
"plugins": [
"react"
],
"rules": {
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"no-console": ["warn", { "allow": ["warn", "error"] }]
}
}
@@ -0,0 +1,107 @@
import React from 'react';
import cn from 'classnames';
import styles from './styles.css';
import {t} from 'plugin-api/beta/client/services';
import {ClickOutside} from 'plugin-api/beta/client/components';
import {Icon, Button} from 'plugin-api/beta/client/components/ui';
const name = 'talk-plugin-permalink';
export default class PermalinkButton extends React.Component {
constructor (props) {
super(props);
this.state = {
popoverOpen: false,
copySuccessful: null,
copyFailure: null
};
}
toggle = () => {
this.popover.style.top = `${this.linkButton.offsetTop - 80}px`;
this.setState({
popoverOpen: !this.state.popoverOpen
});
}
handleClickOutside = () => {
this.setState({
popoverOpen: false
});
}
copyPermalink = () => {
this.permalinkInput.select();
try {
document.execCommand('copy');
this.setState({
copySuccessful: true,
copyFailure: null
});
} catch (err) {
this.setState({
copyFailure: true,
copySuccessful: null
});
}
this.timeout = window.setTimeout(() => {
this.setState({
copyFailure: null,
copySuccessful: null
});
}, 3000);
}
componentWillUnmount() {
window.clearTimeout(this.timeout);
}
render () {
const {copySuccessful, copyFailure, popoverOpen} = this.state;
const {asset} = this.props;
return (
<ClickOutside onClickOutside={this.handleClickOutside}>
<div className={cn(`${name}-container`, styles.container)}>
<button
ref={(ref) => this.linkButton = ref}
onClick={this.toggle}
className={`${name}-button`}>
{t('permalink')}
<Icon name="link" />
</button>
<div
ref={(ref) => this.popover = ref}
className={cn([`${name}-popover`, styles.popover, {[styles.active]: popoverOpen}])}>
<input
className={cn(styles.input, `${name}-copy-field`)}
type='text'
ref={(input) => this.permalinkInput = input}
defaultValue={`${asset.url}#${this.props.commentId}`}
/>
<Button
onClick={this.copyPermalink}
className={cn([
styles.button,
`${name}-copy-button`, {
[styles.success]:copySuccessful,
[styles.failure]: copyFailure
}])}>
{!copyFailure && !copySuccessful && 'Copy'}
{copySuccessful && 'Copied'}
{copyFailure && 'Not supported'}
</Button>
</div>
</div>
</ClickOutside>
);
}
}
@@ -0,0 +1,77 @@
.popover {
display: none;
background-color: white;
position: absolute;
border-radius: 3px;
padding: 15px 10px;
box-sizing: border-box;
border: solid 1px rgba(153, 153, 153, 0.33);
left: 0;
width: 100%;
z-index: 10;
}
.popover::before {
content: '';
border: 10px solid transparent;
border-top-color: white;
position: absolute;
right: 7em;
bottom: -20px;
z-index: 2;
}
.popover::after{
content: '';
border: 10px solid transparent;
border-top-color: rgba(153, 153, 153, 0.33);
position: absolute;
right: 7em;
bottom: -21px;
z-index: 1;
}
.input {
display: inline-block;
width: calc(100% - 78px);
padding: 8px;
border-radius: 3px;
border: solid 1px #e0e0e0;
height: 32px;
box-sizing: border-box;
font-size: 1em;
}
.button {
display: inline-block;
float: right;
box-sizing: border-box;
margin: 0;
background-color: #e0e0e0;
font-size: 1em;
width: auto;
height: auto;
padding: 2px;
transition: background-color 0.4s ease;
}
.button:hover{
color: black;
}
.button.success {
background-color: #00897B;
color: white;
}
.button.failure {
background-color: #FF5252;
color: white;
}
.container {
z-index: 2;
}
.active {
display: block;
}
@@ -0,0 +1,7 @@
import PermalinkButton from './components/PermalinkButton';
export default {
slots: {
commentActions: [PermalinkButton]
}
};
+1
View File
@@ -0,0 +1 @@
module.exports = {};
@@ -0,0 +1,8 @@
{
"name": "talk-plugin-permalink",
"version": "1.0.0",
"description": "",
"main": "index.js",
"author": "",
"license": "ISC"
}
-52
View File
@@ -33,58 +33,6 @@
#root > div {
height: 100%;
}
/* putting this here until I can get webpack to behave */
.react-tagsinput {
background-color: #fff;
border: 1px solid #ccc;
overflow: hidden;
padding-left: 5px;
padding-top: 5px;
}
.react-tagsinput--focused {
border-color: rgb(142, 76, 65);
}
.react-tagsinput-tag {
background-color: rgb(255, 220, 214);
border-radius: 2px;
border: 1px solid rgb(244, 126, 107);
color: rgb(244, 126, 107);
display: inline-block;
font-family: sans-serif;
font-size: 13px;
font-weight: 400;
margin-bottom: 5px;
margin-right: 5px;
padding: 5px;
}
.react-tagsinput-remove {
cursor: pointer;
font-weight: bold;
color: rgb(101, 24, 23);
}
.react-tagsinput-tag a::before {
content: " ×";
}
.react-tagsinput-input {
background: transparent;
border: 0;
color: #777;
font-family: sans-serif;
font-size: 13px;
font-weight: 400;
margin-bottom: 6px;
margin-top: 1px;
outline: none;
padding: 5px;
width: 90px;
}
</style>
<% if (data != null) { %>
<script id="data" type="application/json"><%- JSON.stringify(data) %></script>
+11 -4
View File
@@ -2041,7 +2041,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2:
create-hash "^1.1.0"
inherits "^2.0.1"
create-react-class@^15.5.1:
create-react-class@^15.5.1, create-react-class@^15.5.2:
version "15.5.2"
resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.5.2.tgz#6a8758348df660b88326a0e764d569f274aad681"
dependencies:
@@ -6878,6 +6878,13 @@ react-highlight-words@^0.6.0:
dependencies:
highlight-words-core "^1.0.2"
react-input-autosize@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-1.1.4.tgz#cbc45072d4084ddc57806db8e3b34e644b8366ac"
dependencies:
create-react-class "^15.5.2"
prop-types "^15.5.8"
react-linkify@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/react-linkify/-/react-linkify-0.1.3.tgz#6e886180bda6c8fdc5f9f8a7ebe82fc0f48db7ad"
@@ -6931,9 +6938,9 @@ react-router@^3.0.0:
prop-types "^15.5.6"
warning "^3.0.0"
react-tagsinput@^3.14.0:
version "3.16.1"
resolved "https://registry.yarnpkg.com/react-tagsinput/-/react-tagsinput-3.16.1.tgz#dfb3bcbe5fc4430f60c145716c17cdc2613ce117"
react-tagsinput@^3.17.0:
version "3.17.0"
resolved "https://registry.yarnpkg.com/react-tagsinput/-/react-tagsinput-3.17.0.tgz#d699bc7ff3be3492d5a3d2a57f6976908774fba3"
react-toastify@^1.5.0:
version "1.5.0"