diff --git a/client/coral-admin/src/components/ModerationKeysModal.js b/client/coral-admin/src/components/ModerationKeysModal.js index fabd5098c..c4f3f1e1d 100644 --- a/client/coral-admin/src/components/ModerationKeysModal.js +++ b/client/coral-admin/src/components/ModerationKeysModal.js @@ -16,8 +16,8 @@ const shortcuts = [ { title: 'modqueue.actions', shortcuts: { - 't': 'modqueue.approve', - 'r': 'modqueue.reject' + 'd': 'modqueue.approve', + 'f': 'modqueue.reject' } } ]; @@ -40,8 +40,8 @@ export default class ModerationKeysModal extends React.Component {

{t('modqueue.mod_faster')}

{t('modqueue.try_these')}:

{t('modqueue.view_more_shortcuts')} {t('modqueue.shift_key')} + /

diff --git a/client/coral-admin/src/components/ui/Header.css b/client/coral-admin/src/components/ui/Header.css index d99a7f295..f85a7cdf9 100644 --- a/client/coral-admin/src/components/ui/Header.css +++ b/client/coral-admin/src/components/ui/Header.css @@ -40,12 +40,12 @@ height: 100%; } -.rightPanel ul { +.rightPanel > ul { list-style: none; margin-right: 20px; } -.rightPanel li { +.rightPanel > ul > li { display: inline-block; float: right; margin-left: 15px; @@ -54,6 +54,12 @@ line-height: 33px; } +.rightPanel a { + color: black; + text-decoration: none; + font-weight: 400; +} + .rightPanel .settings { line-height: 0; } diff --git a/client/coral-admin/src/components/ui/Header.js b/client/coral-admin/src/components/ui/Header.js index bbc78a321..f2a0b06e3 100644 --- a/client/coral-admin/src/components/ui/Header.js +++ b/client/coral-admin/src/components/ui/Header.js @@ -71,13 +71,25 @@ const CoralHeader = ({ showShortcuts(true)}>{t('configure.shortcuts')} - {t('configure.sign_out')} + + + View latest version + + + + + Report a bug or give feedback + + + + {t('configure.sign_out')} + + + Talk {`v${process.env.VERSION}`} + -
  • - {`v${process.env.VERSION}`} -
  • diff --git a/client/coral-admin/src/routes/Moderation/components/Comment.js b/client/coral-admin/src/routes/Moderation/components/Comment.js index 9d1019b5e..8a23cc5ba 100644 --- a/client/coral-admin/src/routes/Moderation/components/Comment.js +++ b/client/coral-admin/src/routes/Moderation/components/Comment.js @@ -60,7 +60,7 @@ const Comment = ({ return (
  • diff --git a/client/coral-admin/src/routes/Moderation/components/Moderation.js b/client/coral-admin/src/routes/Moderation/components/Moderation.js index c2036247d..63c9e13ab 100644 --- a/client/coral-admin/src/routes/Moderation/components/Moderation.js +++ b/client/coral-admin/src/routes/Moderation/components/Moderation.js @@ -14,8 +14,13 @@ import StorySearch from '../containers/StorySearch'; import {Spinner} from 'coral-ui'; export default class Moderation extends Component { - state = { - selectedIndex: 0, + constructor() { + super(); + + this.state = { + selectedIndex: 0 + }; + } componentWillMount() { @@ -31,7 +36,7 @@ export default class Moderation extends Component { } onClose = () => { - this.toggleModal(false); + this.props.toggleModal(false); } closeSearch = () => { @@ -60,24 +65,22 @@ export default class Moderation extends Component { getComments = () => { const {root, route} = this.props; const activeTab = route.path === ':id' ? 'premod' : route.path; - return root[activeTab]; + return root[activeTab].nodes; } select = (next) => () => { if (next) { - this.setState((prevState) => - ({ - ...prevState, - selectedIndex: prevState.selectedIndex < this.getComments().length - 1 - ? prevState.selectedIndex + 1 : prevState.selectedIndex - })); + this.setState((state) => ({ + ...state, + selectedIndex: state.selectedIndex < this.getComments().length - 1 + ? state.selectedIndex + 1 : state.selectedIndex + })); } else { - this.setState((prevState) => - ({ - ...prevState, - selectedIndex: prevState.selectedIndex > 0 ? - prevState.selectedIndex - 1 : prevState.selectedIndex - })); + this.setState((state) => ({ + ...state, + selectedIndex: state.selectedIndex > 0 + ? state.selectedIndex - 1 : state.selectedIndex + })); } } diff --git a/client/coral-admin/src/routes/Moderation/components/UserDetail.js b/client/coral-admin/src/routes/Moderation/components/UserDetail.js index 688ac75d0..abc9f4440 100644 --- a/client/coral-admin/src/routes/Moderation/components/UserDetail.js +++ b/client/coral-admin/src/routes/Moderation/components/UserDetail.js @@ -1,11 +1,19 @@ import React, {PropTypes} from 'react'; -import {Button, Drawer} from 'coral-ui'; +import {Button, Drawer, Copy} from 'coral-ui'; import styles from './UserDetail.css'; import Slot from 'coral-framework/components/Slot'; import Comment from './Comment'; import {actionsMap} from '../helpers/moderationQueueActionsMap'; export default class UserDetail extends React.Component { + + constructor() { + super(); + this.state = { + emailCopied: false + }; + } + static propTypes = { id: PropTypes.string.isRequired, hideUserDetail: PropTypes.func.isRequired, @@ -22,16 +30,6 @@ export default class UserDetail extends React.Component { bulkReject: PropTypes.func.isRequired, } - copyPermalink = () => { - this.profile.select(); - try { - document.execCommand('copy'); - } catch (e) { - - /* nothing */ - } - } - rejectThenReload = (info) => { this.props.rejectComment(info).then(() => { this.props.data.refetch(); @@ -52,6 +50,16 @@ export default class UserDetail extends React.Component { this.props.changeStatus('rejected'); } + showCopied() { + this.setState({ + emailCopied: true + }, () => { + setTimeout(() => this.setState({ + emailCopied: false + }), 3000); + }); + } + render () { const { root: { @@ -90,8 +98,14 @@ export default class UserDetail extends React.Component { return (

    {user.username}

    - {profile && this.profile = ref} value={profile} />} + + this.showCopied()} text={profile} className={styles.profileEmail}> + + + - + {open ?
    :

    {asset.settings.closedMessage}

    } + + {loggedIn && ( div span { - display: none; - } - .commentActionsLeft.comment__action-container .coral-plugin-replies-reply-button { visibility: collapse; margin-left: -30px; diff --git a/client/coral-ui/components/Copy.js b/client/coral-ui/components/Copy.js new file mode 100644 index 000000000..7162cd141 --- /dev/null +++ b/client/coral-ui/components/Copy.js @@ -0,0 +1,38 @@ +import React, {Component} from 'react'; +import Clipboard from 'clipboard'; + +export default class Copy extends Component { + + constructor(props) { + super(props); + this.refCopyButton = this.refCopyButton.bind(this); + } + + componentDidMount() { + const clipboard = new Clipboard(this.copyButtonEl); + + clipboard.on('success', (e) => { + this.props.onCopy(); + e.clearSelection(); + }); + } + + refCopyButton(button) { + this.copyButtonEl = button; + } + + render() { + const {children, target = '', text = ''} = this.props; + + return ( + + {children} + + ); + } +} diff --git a/client/coral-ui/index.js b/client/coral-ui/index.js index 3e9456727..d9f960eb2 100644 --- a/client/coral-ui/index.js +++ b/client/coral-ui/index.js @@ -24,3 +24,4 @@ export {default as Option} from './components/Option'; export {default as SnackBar} from './components/SnackBar'; export {default as TextArea} from './components/TextArea'; export {default as Drawer} from './components/Drawer'; +export {default as Copy} from './components/Copy'; diff --git a/package.json b/package.json index c1671c11e..fe0bd6117 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,7 @@ "body-parser": "^1.17.1", "bowser": "^1.7.0", "cli-table": "^0.3.1", + "clipboard": "^1.7.1", "colors": "^1.1.2", "commander": "^2.9.0", "compression": "^1.6.2", diff --git a/yarn.lock b/yarn.lock index fe99eec83..c298f6063 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1671,6 +1671,14 @@ cli-width@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" +clipboard@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-1.7.1.tgz#360d6d6946e99a7a1fef395e42ba92b5e9b5a16b" + dependencies: + good-listener "^1.2.2" + select "^1.1.2" + tiny-emitter "^2.0.0" + cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" @@ -2399,6 +2407,10 @@ delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" +delegate@^3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.1.3.tgz#9a8251a777d7025faa55737bc3b071742127a9fd" + delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" @@ -3536,6 +3548,12 @@ globby@^5.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" +good-listener@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" + dependencies: + delegate "^3.1.2" + got@^3.2.0: version "3.3.1" resolved "https://registry.yarnpkg.com/got/-/got-3.3.1.tgz#e5d0ed4af55fc3eef4d56007769d98192bcb2eca" @@ -6569,13 +6587,7 @@ promise@^7.0.1, promise@^7.1.1: dependencies: asap "~2.0.3" -prop-types@^15.5.0, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@~15.5.7: - version "15.5.8" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.8.tgz#6b7b2e141083be38c8595aa51fc55775c7199394" - dependencies: - fbjs "^0.8.9" - -prop-types@^15.5.10: +prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@~15.5.7: version "15.5.10" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154" dependencies: @@ -7411,6 +7423,10 @@ sax@^1.1.4, sax@^1.2.1, sax@~1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.2.tgz#fd8631a23bc7826bef5d871bdb87378c95647828" +select@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" + selenium-standalone@^5.11.2: version "5.11.2" resolved "https://registry.yarnpkg.com/selenium-standalone/-/selenium-standalone-5.11.2.tgz#724ccaa72fb26f3711e0e20989e478c4133df844" @@ -8025,6 +8041,10 @@ timers-browserify@^2.0.2: dependencies: setimmediate "^1.0.4" +tiny-emitter@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.0.tgz#bad327adb1804b42a231afa741532bd884cd09ad" + title-case-minors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/title-case-minors/-/title-case-minors-1.0.0.tgz#51f17037c294747a1d1cda424b5004c86d8eb115"