Merge pull request #269 from coralproject/design-pass-tweaks

Design pass tweaks
This commit is contained in:
Belén Curcio
2017-02-02 12:21:47 -03:00
committed by GitHub
23 changed files with 371 additions and 187 deletions
+3 -1
View File
@@ -1 +1,3 @@
.Reply {
position: relative;
}
+9 -7
View File
@@ -16,6 +16,8 @@ import {ReplyBox, ReplyButton} from 'coral-plugin-replies';
import FlagComment from 'coral-plugin-flags/FlagComment'; import FlagComment from 'coral-plugin-flags/FlagComment';
import LikeButton from 'coral-plugin-likes/LikeButton'; import LikeButton from 'coral-plugin-likes/LikeButton';
import styles from './Comment.css';
const getAction = (type, comment) => comment.actions.filter((a) => a.type === type)[0]; const getAction = (type, comment) => comment.actions.filter((a) => a.type === type)[0];
class Comment extends React.Component { class Comment extends React.Component {
@@ -87,7 +89,7 @@ class Comment extends React.Component {
return ( return (
<div <div
className={parentId ? 'reply' : 'comment'} className={parentId ? `reply ${styles.Reply}` : `comment ${styles.Comment}`}
id={`c_${comment.id}`} id={`c_${comment.id}`}
style={{marginLeft: depth * 30}}> style={{marginLeft: depth * 30}}>
<hr aria-hidden={true} /> <hr aria-hidden={true} />
@@ -103,11 +105,6 @@ class Comment extends React.Component {
<PubDate created_at={comment.created_at} /> <PubDate created_at={comment.created_at} />
<Content body={comment.body} /> <Content body={comment.body} />
<div className="commentActionsLeft"> <div className="commentActionsLeft">
<ReplyButton
onClick={() => setActiveReplyBox(comment.id)}
parentCommentId={parentId || comment.id}
currentUserId={currentUser && currentUser.id}
banned={false} />
<LikeButton <LikeButton
like={like} like={like}
id={comment.id} id={comment.id}
@@ -115,8 +112,14 @@ class Comment extends React.Component {
deleteAction={deleteAction} deleteAction={deleteAction}
showSignInDialog={showSignInDialog} showSignInDialog={showSignInDialog}
currentUser={currentUser} /> currentUser={currentUser} />
<ReplyButton
onClick={() => setActiveReplyBox(comment.id)}
parentCommentId={parentId || comment.id}
currentUserId={currentUser && currentUser.id}
banned={false} />
</div> </div>
<div className="commentActionsRight"> <div className="commentActionsRight">
<PermalinkButton articleURL={asset.url} commentId={comment.id} />
<FlagComment <FlagComment
flag={flag} flag={flag}
id={comment.id} id={comment.id}
@@ -125,7 +128,6 @@ class Comment extends React.Component {
deleteAction={deleteAction} deleteAction={deleteAction}
showSignInDialog={showSignInDialog} showSignInDialog={showSignInDialog}
currentUser={currentUser} /> currentUser={currentUser} />
<PermalinkButton articleURL={asset.url} commentId={comment.id} />
</div> </div>
{ {
activeReplyBox === comment.id activeReplyBox === comment.id
+98 -102
View File
@@ -3,7 +3,7 @@ import {compose} from 'react-apollo';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import isEqual from 'lodash/isEqual'; import isEqual from 'lodash/isEqual';
import {TabBar, Tab, TabContent, Spinner} from '../../coral-ui'; import {TabBar, Tab, TabContent, Spinner} from 'coral-ui';
const {logout, showSignInDialog, requestConfirmEmail} = authActions; const {logout, showSignInDialog, requestConfirmEmail} = authActions;
const {addNotification, clearNotification} = notificationActions; const {addNotification, clearNotification} = notificationActions;
@@ -17,27 +17,24 @@ import Stream from './Stream';
import InfoBox from 'coral-plugin-infobox/InfoBox'; import InfoBox from 'coral-plugin-infobox/InfoBox';
import Count from 'coral-plugin-comment-count/CommentCount'; import Count from 'coral-plugin-comment-count/CommentCount';
import CommentBox from 'coral-plugin-commentbox/CommentBox'; import CommentBox from 'coral-plugin-commentbox/CommentBox';
import UserBox from '../../coral-sign-in/components/UserBox'; import UserBox from 'coral-sign-in/components/UserBox';
import SignInContainer from '../../coral-sign-in/containers/SignInContainer'; import SignInContainer from 'coral-sign-in/containers/SignInContainer';
import SuspendedAccount from '../../coral-framework/components/SuspendedAccount'; import SuspendedAccount from 'coral-framework/components/SuspendedAccount';
import SettingsContainer from '../../coral-settings/containers/SettingsContainer'; import SettingsContainer from 'coral-settings/containers/SettingsContainer';
import RestrictedContent from '../../coral-framework/components/RestrictedContent'; import RestrictedContent from 'coral-framework/components/RestrictedContent';
import ConfigureStreamContainer from '../../coral-configure/containers/ConfigureStreamContainer'; import ConfigureStreamContainer from 'coral-configure/containers/ConfigureStreamContainer';
class Embed extends Component { class Embed extends Component {
constructor (props) { state = {activeTab: 0, showSignInDialog: false};
super(props);
this.state = { changeTab = (tab) => {
activeTab: 0,
showSignInDialog: false
};
this.changeTab = this.changeTab.bind(this); // Everytime the comes from another tab, the Stream needs to be updated.
} if (tab === 0) {
this.props.data.refetch();
}
changeTab (tab) {
this.setState({ this.setState({
activeTab: tab activeTab: tab
}); });
@@ -51,15 +48,6 @@ class Embed extends Component {
} }
componentDidMount () { componentDidMount () {
// stream id, logged in user, settings
// Set up messaging between embedded Iframe an parent component
// this.props.getStream(path || window.location);
// this.path = window.location.href.split('#')[0];
//
pym.sendMessage('childReady'); pym.sendMessage('childReady');
pym.onMessage('DOMContentLoaded', hash => { pym.onMessage('DOMContentLoaded', hash => {
@@ -78,7 +66,6 @@ class Embed extends Component {
} }
}, 100); }, 100);
}); });
} }
componentWillReceiveProps (nextProps) { componentWillReceiveProps (nextProps) {
@@ -100,86 +87,89 @@ class Embed extends Component {
minHeight: document.body.scrollHeight + 200 minHeight: document.body.scrollHeight + 200
} : {}; } : {};
return <div style={expandForLogin}> if (loading) {
{ return <Spinner />;
loading ? <Spinner/> }
: <div className="commentStream">
return (
<div style={expandForLogin}>
<div className="commentStream">
<TabBar onChange={this.changeTab} activeTab={activeTab}> <TabBar onChange={this.changeTab} activeTab={activeTab}>
<Tab><Count count={asset.commentCount}/></Tab> <Tab><Count count={asset.commentCount}/></Tab>
<Tab>Settings</Tab> <Tab>Settings</Tab>
<Tab restricted={!isAdmin}>Configure Stream</Tab> <Tab restricted={!isAdmin}>Configure Stream</Tab>
</TabBar> </TabBar>
{loggedIn && <UserBox user={user} logout={this.props.logout} />} {loggedIn && <UserBox user={user} logout={this.props.logout} changeTab={this.changeTab} />}
<TabContent show={activeTab === 0}> <TabContent show={activeTab === 0}>
{ {
openStream openStream
? <div id="commentBox"> ? <div id="commentBox">
<InfoBox <InfoBox
content={asset.settings.infoBoxContent} content={asset.settings.infoBoxContent}
enable={asset.settings.infoBoxEnable} enable={asset.settings.infoBoxEnable}
/> />
<RestrictedContent restricted={false} restrictedComp={<SuspendedAccount />}> <RestrictedContent restricted={false} restrictedComp={<SuspendedAccount />}>
{ {
user user
? <CommentBox ? <CommentBox
commentPostedHandler={refetch} commentPostedHandler={refetch}
addNotification={this.props.addNotification} addNotification={this.props.addNotification}
postItem={this.props.postItem} postItem={this.props.postItem}
appendItemArray={this.props.appendItemArray} appendItemArray={this.props.appendItemArray}
updateItem={this.props.updateItem} updateItem={this.props.updateItem}
assetId={asset.id} assetId={asset.id}
premod={asset.settings.moderation} premod={asset.settings.moderation}
isReply={false} isReply={false}
currentUser={this.props.auth.user} currentUser={this.props.auth.user}
banned={false} banned={false}
authorId={user.id} authorId={user.id}
charCount={asset.settings.charCountEnable && asset.settings.charCount} /> charCount={asset.settings.charCountEnable && asset.settings.charCount} />
: null : null
} }
</RestrictedContent> </RestrictedContent>
</div> </div>
: <p>{asset.settings.closedMessage}</p> : <p>{asset.settings.closedMessage}</p>
} }
{!loggedIn && <SignInContainer offset={signInOffset}/>} {!loggedIn && <SignInContainer offset={signInOffset}/>}
<Stream <Stream
refetch={refetch} refetch={refetch}
addNotification={this.props.addNotification} addNotification={this.props.addNotification}
postItem={this.props.postItem} postItem={this.props.postItem}
asset={asset} asset={asset}
currentUser={user} currentUser={user}
postAction={this.props.postAction} postAction={this.props.postAction}
deleteAction={this.props.deleteAction} deleteAction={this.props.deleteAction}
showSignInDialog={this.props.showSignInDialog} showSignInDialog={this.props.showSignInDialog}
comments={asset.comments} /> comments={asset.comments} />
<Notification <Notification
notifLength={4500} notifLength={4500}
clearNotification={this.props.clearNotification} clearNotification={this.props.clearNotification}
notification={{text: null}} notification={{text: null}}
/> />
</TabContent> </TabContent>
<TabContent show={activeTab === 1}> <TabContent show={activeTab === 1}>
<SettingsContainer <SettingsContainer
loggedIn={loggedIn} loggedIn={loggedIn}
userData={this.props.userData} userData={this.props.userData}
showSignInDialog={this.props.showSignInDialog} showSignInDialog={this.props.showSignInDialog}
/> />
</TabContent> </TabContent>
<TabContent show={activeTab === 2}> <TabContent show={activeTab === 2}>
<RestrictedContent restricted={!loggedIn}> <RestrictedContent restricted={!loggedIn}>
<ConfigureStreamContainer <ConfigureStreamContainer
status={status} status={status}
onClick={this.toggleStatus} onClick={this.toggleStatus}
/> />
</RestrictedContent> </RestrictedContent>
</TabContent> </TabContent>
<Notification <Notification
notifLength={4500} notifLength={4500}
clearNotification={this.props.clearNotification} clearNotification={this.props.clearNotification}
notification={this.props.notification} notification={this.props.notification}
/> />
</div> </div>
} </div>
</div>; );
} }
} }
@@ -193,7 +183,13 @@ const mapStateToProps = state => ({
const mapDispatchToProps = dispatch => ({ const mapDispatchToProps = dispatch => ({
requestConfirmEmail: () => dispatch(requestConfirmEmail()), requestConfirmEmail: () => dispatch(requestConfirmEmail()),
loadAsset: (asset) => dispatch(fetchAssetSuccess(asset)), loadAsset: (asset) => dispatch(fetchAssetSuccess(asset)),
addNotification: (type, text) => dispatch(addNotification(type, text)), addNotification: (type, text) => {
pym.sendMessage('getPosition');
pym.onMessage('position', position => {
dispatch(addNotification(type, text, position));
});
},
clearNotification: () => dispatch(clearNotification()), clearNotification: () => dispatch(clearNotification()),
showSignInDialog: (offset) => dispatch(showSignInDialog(offset)), showSignInDialog: (offset) => dispatch(showSignInDialog(offset)),
logout: () => dispatch(logout()), logout: () => dispatch(logout()),
+8 -2
View File
@@ -1,3 +1,8 @@
html, body {
width:auto;
height:auto;
}
body { body {
font-family: 'Lato', sans-serif; font-family: 'Lato', sans-serif;
font-family: 'Open Sans', sans-serif; font-family: 'Open Sans', sans-serif;
@@ -46,7 +51,6 @@ hr {
/* Notification styles */ /* Notification styles */
#coral-notif { #coral-notif {
position: fixed; position: fixed;
bottom: 0;
border: 0; border: 0;
background: rgb(105,105,105); background: rgb(105,105,105);
color: white; color: white;
@@ -76,6 +80,8 @@ hr {
.commentStream { .commentStream {
/* prevent absolutely positioned final permalink popover from being clipped */ /* prevent absolutely positioned final permalink popover from being clipped */
padding-bottom: 50px; padding-bottom: 50px;
min-height: 600px;
position: relative;
} }
/* Comment Box Styles */ /* Comment Box Styles */
@@ -219,8 +225,8 @@ hr {
.coral-plugin-flags-popup span { .coral-plugin-flags-popup span {
min-width: 280px; min-width: 280px;
bottom: 36px; bottom: 36px;
left: -190px;
position: absolute; position: absolute;
right: 10px;
} }
.coral-plugin-flags-popup-form { .coral-plugin-flags-popup-form {
@@ -1,11 +1,12 @@
export const ADD_NOTIFICATION = 'ADD_NOTIFICATION'; export const ADD_NOTIFICATION = 'ADD_NOTIFICATION';
export const CLEAR_NOTIFICATION = 'CLEAR_NOTIFICATION'; export const CLEAR_NOTIFICATION = 'CLEAR_NOTIFICATION';
export const addNotification = (notifType, text) => { export const addNotification = (notifType, text, position) => {
return { return {
type: ADD_NOTIFICATION, type: ADD_NOTIFICATION,
notifType, notifType,
text text,
position
}; };
}; };
@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import {SnackBar} from 'coral-ui';
const Notification = (props) => { const Notification = (props) => {
if (props.notification.text) { if (props.notification.text) {
@@ -6,14 +7,16 @@ const Notification = (props) => {
props.clearNotification(); props.clearNotification();
}, props.notifLength); }, props.notifLength);
} }
return <div> return (
{ <div>
props.notification.text && {
<dialog open id='coral-notif' className={`coral-notif-${ props.notification.type}`}> props.notification.text &&
{props.notification.text} <SnackBar id='coral-notif' className={`coral-notif-${props.notification.type}`} position={props.notification.position}>
</dialog> {props.notification.text}
} </SnackBar>
</div>; }
</div>
);
}; };
export default Notification; export default Notification;
@@ -1,14 +1,21 @@
/* Items Notifications */
import * as actions from '../actions/notification'; import * as actions from '../actions/notification';
import {fromJS} from 'immutable'; import {Map} from 'immutable';
const initialState = fromJS({}); const initialState = Map({
text: '',
type: '',
position: 400
});
export default (state = initialState, action) => { export default (state = initialState, action) => {
switch (action.type) { switch (action.type) {
case actions.ADD_NOTIFICATION: case actions.ADD_NOTIFICATION:
return state.set('text', action.text).set('type', action.notifType); return state
.merge({
type: action.notifType,
text: action.text,
position: action.position
});
case actions.CLEAR_NOTIFICATION: case actions.CLEAR_NOTIFICATION:
return initialState; return initialState;
default: default:
+23 -27
View File
@@ -1,51 +1,47 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import {Tooltip} from 'coral-ui'; import {Tooltip} from 'coral-ui';
import FlagBio from '../coral-plugin-flags/FlagBio'; import FlagBio from 'coral-plugin-flags/FlagBio';
const packagename = 'coral-plugin-author-name'; const packagename = 'coral-plugin-author-name';
import styles from './styles.css';
export default class AuthorName extends Component { export default class AuthorName extends Component {
constructor (props) {
super(props);
this.state = { state = {showTooltip: false}
showTooltip: false
};
this.handleMouseOver = this.handleMouseOver.bind(this); handleClick = () => {
this.handleMouseLeave = this.handleMouseLeave.bind(this); this.setState(state => ({
showTooltip: !state.showTooltip
}));
} }
handleMouseOver () { handleMouseLeave = () => {
this.setState({ setTimeout(() => {
showTooltip: true this.setState({
}); showTooltip: false
} });
}, 500);
handleMouseLeave () {
this.setState({
showTooltip: false
});
} }
render () { render () {
const {author} = this.props; const {author} = this.props;
const {showTooltip} = this.state; const {showTooltip} = this.state;
return ( return (
<div <div className={`${packagename}-text ${styles.container}`} onClick={this.handleClick} onMouseLeave={this.handleMouseLeave}>
className={`${packagename}-text`} <a className={`${styles.authorName} ${author.settings.bio ? styles.hasBio : ''}`}>
onMouseOver={this.handleMouseOver} {author && author.name}
onMouseLeave={this.handleMouseLeave} {author.settings.bio ? <span className={`${styles.arrowDown} ${showTooltip ? styles.arrowUp : ''}`} /> : null}
> </a>
{author && author.name} {showTooltip && author.settings.bio
{ showTooltip && author.settings.bio && <Tooltip> && (
<Tooltip>
<div className={`${packagename}-bio`}> <div className={`${packagename}-bio`}>
{author.settings.bio} {author.settings.bio}
</div> </div>
<div className={`${packagename}-bio-flag`}> <div className={`${packagename}-bio-flag`}>
<FlagBio {...this.props}/> <FlagBio {...this.props}/>
</div> </div>
</Tooltip> </Tooltip>
} )}
</div> </div>
); );
} }
@@ -0,0 +1,34 @@
.authorName {
color: black;
display: inline-block;
margin: 10px 0;
}
.hasBio {
&:hover {
cursor: pointer;
}
}
.arrowDown {
top: 0;
width: 0;
height: 0;
margin-top: -2px;
margin-left: 2px;
display: inline-block;
vertical-align: middle;
border-bottom: 0;
border-left: 3px solid transparent;
border-right: 3px solid transparent;
border-top: 3px solid #000000;
}
.arrowUp {
width: 0;
height: 0;
border-top: 0;
border-left: 3px solid transparent;
border-right: 3px solid transparent;
border-bottom: 3px solid black;
}
+2 -2
View File
@@ -10,8 +10,8 @@ const getPopupMenu = [
return { return {
header: lang.t('step-1-header'), header: lang.t('step-1-header'),
options: [ options: [
{val: 'USERS', text: lang.t('flag-username')}, {val: 'COMMENTS', text: lang.t('flag-comment')},
{val: 'COMMENTS', text: lang.t('flag-comment')} {val: 'USERS', text: lang.t('flag-username')}
], ],
button: lang.t('continue'), button: lang.t('continue'),
sets: 'itemType' sets: 'itemType'
@@ -3,6 +3,8 @@ import I18n from 'coral-framework/modules/i18n/i18n';
import translations from './translations'; import translations from './translations';
import onClickOutside from 'react-onclickoutside'; import onClickOutside from 'react-onclickoutside';
const name = 'coral-plugin-permalinks'; const name = 'coral-plugin-permalinks';
import {Button} from 'coral-ui';
import styles from './styles.css';
const lang = new I18n(translations); const lang = new I18n(translations);
@@ -32,40 +34,37 @@ class PermalinkButton extends React.Component {
this.permalinkInput.select(); this.permalinkInput.select();
try { try {
document.execCommand('copy'); document.execCommand('copy');
this.setState({copySuccessful: true}); this.setState({copySuccessful: true, copyFailure: null});
} catch (err) { } catch (err) {
this.setState({copyFailure: true}); this.setState({copyFailure: true, copySuccessful: null});
} }
setTimeout(() => { setTimeout(() => {
this.setState({copyFailure: null, copySuccessful: null}); this.setState({copyFailure: null, copySuccessful: null});
}, 4500); }, 3000);
} }
render () { render () {
const {copySuccessful, copyFailure} = this.state;
return ( return (
<div className={`${name}-container`}> <div className={`${name}-container`}>
<button onClick={this.toggle} className={`${name}-button`}> <button onClick={this.toggle} className={`${name}-button`}>
<i className={`${name}-icon material-icons`} aria-hidden={true}>link</i> <i className={`${name}-icon material-icons`} aria-hidden={true}>link</i>
{lang.t('permalink.permalink')} {lang.t('permalink.permalink')}
</button> </button>
<div <div className={`${name}-popover ${styles.container} ${this.state.popoverOpen ? 'active' : ''}`}>
className={`${name}-popover ${this.state.popoverOpen ? 'active' : ''}`}>
<input <input
className={`${name}-copy-field`} className={`${name}-copy-field`}
type='text' type='text'
ref={input => this.permalinkInput = input} ref={input => this.permalinkInput = input}
value={`${this.props.articleURL}#${this.props.commentId}`} value={`${this.props.articleURL}#${this.props.commentId}`}
onChange={() => {}} /> onChange={() => {}} />
<button className={`${name}-copy-button`} onClick={this.copyPermalink}>Copy</button> <Button className={`${name}-copy-button ${copySuccessful ? styles.success : ''} ${copyFailure ? styles.failure : ''}`}
{ onClick={this.copyPermalink} >
this.state.copySuccessful ? <p className={`${name}-copied-text`}>copied to clipboard</p> : null {!copyFailure && !copySuccessful && 'Copy'}
} {copySuccessful && 'Copied'}
{ {copyFailure && 'Not supported'}
this.state.copyFailure </Button>
? <p className={`${name}-copied-error`}>copying to clipboard not supported in this browser. Use Cmd + C.</p>
: null
}
</div> </div>
</div> </div>
); );
+74
View File
@@ -0,0 +1,74 @@
.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);
width: auto;
margin: 0 auto;
left: 0;
margin: 0 5px;
top: 0;
left: 0;
width: 100%;
margin: 0;
margin-top: -13px;
&::before {
content: '';
border: 10px solid transparent;
border-top-color: white;
position: absolute;
right: 8.69em;
bottom: -20px;
z-index: 2;
}
&::after{
content: '';
border: 10px solid transparent;
border-top-color: rgba(153, 153, 153, 0.33);
position: absolute;
right: 8.69em;
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;
}
}
}
@@ -1,12 +1,12 @@
{ {
"en": { "en": {
"permalink": { "permalink": {
"permalink": "Permalink" "permalink": "Link"
} }
}, },
"es": { "es": {
"permalink": { "permalink": {
"permalink": "Enlace permanente" "permalink": "Enlace"
} }
} }
} }
+4 -7
View File
@@ -4,14 +4,11 @@ import I18n from 'coral-framework/modules/i18n/i18n';
import translations from '../translations'; import translations from '../translations';
const lang = new I18n(translations); const lang = new I18n(translations);
const UserBox = ({className, user, logout, ...props}) => ( const UserBox = ({className, user, logout, changeTab}) => (
<div <div className={`${styles.userBox} ${className ? className : ''}`}>
className={`${styles.userBox} ${className ? className : ''}`}
{...props}
>
{lang.t('signIn.loggedInAs')} {lang.t('signIn.loggedInAs')}
<a>{user.displayName}</a>. {lang.t('signIn.notYou')} <a onClick={() => changeTab(1)}>{user.displayName}</a>. {lang.t('signIn.notYou')}
<a onClick={logout} id='logout'>{lang.t('signIn.logout')}</a> <a className={styles.logout} onClick={logout} id='logout'>{lang.t('signIn.logout')}</a>
</div> </div>
); );
+4 -1
View File
@@ -93,7 +93,10 @@ input.error{
margin: 0px; margin: 0px;
margin-left: 4px; margin-left: 4px;
padding-bottom: 2px; padding-bottom: 2px;
border-bottom: solid 1px black; }
.userBox .logout {
border-bottom: solid 1px black;
} }
.attention { .attention {
+2 -2
View File
@@ -1,9 +1,9 @@
import React from 'react'; import React from 'react';
import styles from './Checkbox.css'; import styles from './Checkbox.css';
export default ({name, cStyle = 'base', onChange, label, className, info, ...props}) => ( export default ({name, cStyle = 'base', onChange, label, className, info, ...attrs}) => (
<label className={`${styles.label} ${styles[`type--${cStyle}`]} ${className}`} htmlFor={name}> <label className={`${styles.label} ${styles[`type--${cStyle}`]} ${className}`} htmlFor={name}>
<input type="checkbox" id={name} name={name} onChange={onChange} {...props} /> <input type="checkbox" id={name} name={name} onChange={onChange} {...attrs} />
<span className={styles.checkbox}></span> <span className={styles.checkbox}></span>
{label && <span>{label}</span>} {label && <span>{label}</span>}
{info && ( {info && (
+19
View File
@@ -0,0 +1,19 @@
.SnackBar {
position: fixed;
cursor: default;
background-color: #323232;
z-index: 3;
display: flex;
will-change: transform;
transition: transform .25s cubic-bezier(.4,0,1,1);
pointer-events: none;
padding: 18px 14px;
vertical-align: middle;
color: #fff;
border-radius: 3px;
text-align: center;
left: 50%;
transform: translate(-50%, 0);
top: 0;
bottom: auto;
}
+16
View File
@@ -0,0 +1,16 @@
import React from 'react';
import styles from './SnackBar.css';
const SnackBar = ({children, className, position, ...attrs}) => {
return (
<div className={`${styles.SnackBar} ${className}`}
style={ position ? {top: `${position}px`} : fixedStyle}
{...attrs} >
{children}
</div>
);
};
const fixedStyle = {bottom: '200px', top: 'auto'};
export default SnackBar;
+1 -1
View File
@@ -3,7 +3,7 @@
position: absolute; position: absolute;
width: 100%; width: 100%;
border: solid 1px #2376D8; border: solid 1px #2376D8;
top: 33px; top: 48px;
left: 0; left: 0;
box-sizing: border-box; box-sizing: border-box;
background: white; background: white;
+1
View File
@@ -16,3 +16,4 @@ export {default as Card} from './components/Card';
export {default as FormField} from './components/FormField'; export {default as FormField} from './components/FormField';
export {default as Success} from './components/Success'; export {default as Success} from './components/Success';
export {default as Pager} from './components/Pager'; export {default as Pager} from './components/Pager';
export {default as SnackBar} from './components/SnackBar';
+5 -1
View File
@@ -73,7 +73,7 @@ const getCountsByParentID = (context, parent_ids) => {
* @param {Object} context graph context * @param {Object} context graph context
* @param {Object} query query terms to apply to the comments query * @param {Object} query query terms to apply to the comments query
*/ */
const getCommentsByQuery = ({user}, {ids, statuses, asset_id, parent_id, limit, cursor, sort}) => { const getCommentsByQuery = ({user}, {ids, statuses, asset_id, parent_id, author_id, limit, cursor, sort}) => {
let comments = CommentModel.find(); let comments = CommentModel.find();
// Only administrators can search for comments with statuses that are not // Only administrators can search for comments with statuses that are not
@@ -100,6 +100,10 @@ const getCommentsByQuery = ({user}, {ids, statuses, asset_id, parent_id, limit,
}); });
} }
if (user && (user.hasRoles('ADMIN') || user.id === author_id)) {
comments = comments.where({author_id});
}
if (asset_id) { if (asset_id) {
comments = comments.where({asset_id}); comments = comments.where({asset_id});
} }
@@ -28,8 +28,8 @@ describe ('notificationsReducer', () => {
type: 'test' type: 'test'
}); });
const result = notificationReducer(store, action); const result = notificationReducer(store, action);
expect(result.get('text')).to.equal(undefined); expect(result.get('text')).to.equal('');
expect(result.get('type')).to.equal(undefined); expect(result.get('type')).to.equal('');
}); });
}); });
}); });
+25 -1
View File
@@ -28,6 +28,7 @@
<script type='text/javascript' src='<%= basePath %>/pym.v1.min.js'></script> <script type='text/javascript' src='<%= basePath %>/pym.v1.min.js'></script>
<script> <script>
var ready = false; var ready = false;
var notificationOffset = 200;
// default to using the window.location // default to using the window.location
var url = window.location.protocol + '//' + window.location.host + window.location.pathname; var url = window.location.protocol + '//' + window.location.host + window.location.pathname;
@@ -38,7 +39,21 @@
<%}%> <%}%>
var pymParent = new pym.Parent('coralStreamEmbed', '/embed/stream?asset_url=' + encodeURIComponent(url), {title: 'Talk Comments', id:'coralStreamIframe', name: 'coralStreamIframe', asset_url: url}); var pymParent = new pym.Parent('coralStreamEmbed', '/embed/stream?asset_url=' + encodeURIComponent(url), {title: 'Talk Comments', id:'coralStreamIframe', name: 'coralStreamIframe', asset_url: url});
pymParent.onMessage('height', function(height) {document.querySelector('#coralStreamEmbed iframe').height = height + 'px'}) pymParent.onMessage('height', function(height) {
document.querySelector('#coralStreamEmbed iframe').height = height + 'px';
})
pymParent.onMessage('getPosition', function(notification) {
var position = viewport().height + document.body.scrollTop;
if (position > notificationOffset) {
position = position - notificationOffset;
}
pymParent.sendMessage('position', position);
});
pymParent.onMessage('childReady', function () { pymParent.onMessage('childReady', function () {
var interval = setInterval(function () { var interval = setInterval(function () {
if (ready) { if (ready) {
@@ -65,6 +80,15 @@
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
ready = true; ready = true;
}); });
function viewport() {
var e = window, a = 'inner';
if ( !( 'innerWidth' in window ) ){
a = 'client';
e = document.documentElement || document.body;
}
return { width : e[ a+'Width' ] , height : e[ a+'Height' ] }
}
</script> </script>
</body> </body>
</html> </html>