mirror of
https://github.com/wassname/talk.git
synced 2026-06-29 06:50:44 +08:00
Merge pull request #269 from coralproject/design-pass-tweaks
Design pass tweaks
This commit is contained in:
@@ -1 +1,3 @@
|
||||
|
||||
.Reply {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ import {ReplyBox, ReplyButton} from 'coral-plugin-replies';
|
||||
import FlagComment from 'coral-plugin-flags/FlagComment';
|
||||
import LikeButton from 'coral-plugin-likes/LikeButton';
|
||||
|
||||
import styles from './Comment.css';
|
||||
|
||||
const getAction = (type, comment) => comment.actions.filter((a) => a.type === type)[0];
|
||||
|
||||
class Comment extends React.Component {
|
||||
@@ -87,7 +89,7 @@ class Comment extends React.Component {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={parentId ? 'reply' : 'comment'}
|
||||
className={parentId ? `reply ${styles.Reply}` : `comment ${styles.Comment}`}
|
||||
id={`c_${comment.id}`}
|
||||
style={{marginLeft: depth * 30}}>
|
||||
<hr aria-hidden={true} />
|
||||
@@ -103,11 +105,6 @@ class Comment extends React.Component {
|
||||
<PubDate created_at={comment.created_at} />
|
||||
<Content body={comment.body} />
|
||||
<div className="commentActionsLeft">
|
||||
<ReplyButton
|
||||
onClick={() => setActiveReplyBox(comment.id)}
|
||||
parentCommentId={parentId || comment.id}
|
||||
currentUserId={currentUser && currentUser.id}
|
||||
banned={false} />
|
||||
<LikeButton
|
||||
like={like}
|
||||
id={comment.id}
|
||||
@@ -115,8 +112,14 @@ class Comment extends React.Component {
|
||||
deleteAction={deleteAction}
|
||||
showSignInDialog={showSignInDialog}
|
||||
currentUser={currentUser} />
|
||||
<ReplyButton
|
||||
onClick={() => setActiveReplyBox(comment.id)}
|
||||
parentCommentId={parentId || comment.id}
|
||||
currentUserId={currentUser && currentUser.id}
|
||||
banned={false} />
|
||||
</div>
|
||||
<div className="commentActionsRight">
|
||||
<PermalinkButton articleURL={asset.url} commentId={comment.id} />
|
||||
<FlagComment
|
||||
flag={flag}
|
||||
id={comment.id}
|
||||
@@ -125,7 +128,6 @@ class Comment extends React.Component {
|
||||
deleteAction={deleteAction}
|
||||
showSignInDialog={showSignInDialog}
|
||||
currentUser={currentUser} />
|
||||
<PermalinkButton articleURL={asset.url} commentId={comment.id} />
|
||||
</div>
|
||||
{
|
||||
activeReplyBox === comment.id
|
||||
|
||||
@@ -3,7 +3,7 @@ import {compose} from 'react-apollo';
|
||||
import {connect} from 'react-redux';
|
||||
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 {addNotification, clearNotification} = notificationActions;
|
||||
@@ -17,27 +17,24 @@ import Stream from './Stream';
|
||||
import InfoBox from 'coral-plugin-infobox/InfoBox';
|
||||
import Count from 'coral-plugin-comment-count/CommentCount';
|
||||
import CommentBox from 'coral-plugin-commentbox/CommentBox';
|
||||
import UserBox from '../../coral-sign-in/components/UserBox';
|
||||
import SignInContainer from '../../coral-sign-in/containers/SignInContainer';
|
||||
import SuspendedAccount from '../../coral-framework/components/SuspendedAccount';
|
||||
import SettingsContainer from '../../coral-settings/containers/SettingsContainer';
|
||||
import RestrictedContent from '../../coral-framework/components/RestrictedContent';
|
||||
import ConfigureStreamContainer from '../../coral-configure/containers/ConfigureStreamContainer';
|
||||
import UserBox from 'coral-sign-in/components/UserBox';
|
||||
import SignInContainer from 'coral-sign-in/containers/SignInContainer';
|
||||
import SuspendedAccount from 'coral-framework/components/SuspendedAccount';
|
||||
import SettingsContainer from 'coral-settings/containers/SettingsContainer';
|
||||
import RestrictedContent from 'coral-framework/components/RestrictedContent';
|
||||
import ConfigureStreamContainer from 'coral-configure/containers/ConfigureStreamContainer';
|
||||
|
||||
class Embed extends Component {
|
||||
|
||||
constructor (props) {
|
||||
super(props);
|
||||
state = {activeTab: 0, showSignInDialog: false};
|
||||
|
||||
this.state = {
|
||||
activeTab: 0,
|
||||
showSignInDialog: false
|
||||
};
|
||||
changeTab = (tab) => {
|
||||
|
||||
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({
|
||||
activeTab: tab
|
||||
});
|
||||
@@ -51,15 +48,6 @@ class Embed extends Component {
|
||||
}
|
||||
|
||||
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.onMessage('DOMContentLoaded', hash => {
|
||||
@@ -78,7 +66,6 @@ class Embed extends Component {
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
@@ -100,86 +87,89 @@ class Embed extends Component {
|
||||
minHeight: document.body.scrollHeight + 200
|
||||
} : {};
|
||||
|
||||
return <div style={expandForLogin}>
|
||||
{
|
||||
loading ? <Spinner/>
|
||||
: <div className="commentStream">
|
||||
if (loading) {
|
||||
return <Spinner />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={expandForLogin}>
|
||||
<div className="commentStream">
|
||||
<TabBar onChange={this.changeTab} activeTab={activeTab}>
|
||||
<Tab><Count count={asset.commentCount}/></Tab>
|
||||
<Tab>Settings</Tab>
|
||||
<Tab restricted={!isAdmin}>Configure Stream</Tab>
|
||||
</TabBar>
|
||||
{loggedIn && <UserBox user={user} logout={this.props.logout} />}
|
||||
<TabContent show={activeTab === 0}>
|
||||
{
|
||||
openStream
|
||||
? <div id="commentBox">
|
||||
<InfoBox
|
||||
content={asset.settings.infoBoxContent}
|
||||
enable={asset.settings.infoBoxEnable}
|
||||
/>
|
||||
<RestrictedContent restricted={false} restrictedComp={<SuspendedAccount />}>
|
||||
{
|
||||
user
|
||||
? <CommentBox
|
||||
commentPostedHandler={refetch}
|
||||
addNotification={this.props.addNotification}
|
||||
postItem={this.props.postItem}
|
||||
appendItemArray={this.props.appendItemArray}
|
||||
updateItem={this.props.updateItem}
|
||||
assetId={asset.id}
|
||||
premod={asset.settings.moderation}
|
||||
isReply={false}
|
||||
currentUser={this.props.auth.user}
|
||||
banned={false}
|
||||
authorId={user.id}
|
||||
charCount={asset.settings.charCountEnable && asset.settings.charCount} />
|
||||
: null
|
||||
}
|
||||
</RestrictedContent>
|
||||
</div>
|
||||
: <p>{asset.settings.closedMessage}</p>
|
||||
}
|
||||
{!loggedIn && <SignInContainer offset={signInOffset}/>}
|
||||
<Stream
|
||||
refetch={refetch}
|
||||
addNotification={this.props.addNotification}
|
||||
postItem={this.props.postItem}
|
||||
asset={asset}
|
||||
currentUser={user}
|
||||
postAction={this.props.postAction}
|
||||
deleteAction={this.props.deleteAction}
|
||||
showSignInDialog={this.props.showSignInDialog}
|
||||
comments={asset.comments} />
|
||||
<Notification
|
||||
notifLength={4500}
|
||||
clearNotification={this.props.clearNotification}
|
||||
notification={{text: null}}
|
||||
/>
|
||||
</TabContent>
|
||||
<TabContent show={activeTab === 1}>
|
||||
<SettingsContainer
|
||||
loggedIn={loggedIn}
|
||||
userData={this.props.userData}
|
||||
showSignInDialog={this.props.showSignInDialog}
|
||||
/>
|
||||
</TabContent>
|
||||
<TabContent show={activeTab === 2}>
|
||||
<RestrictedContent restricted={!loggedIn}>
|
||||
<ConfigureStreamContainer
|
||||
status={status}
|
||||
onClick={this.toggleStatus}
|
||||
/>
|
||||
</RestrictedContent>
|
||||
</TabContent>
|
||||
<Notification
|
||||
notifLength={4500}
|
||||
clearNotification={this.props.clearNotification}
|
||||
notification={this.props.notification}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div>;
|
||||
{loggedIn && <UserBox user={user} logout={this.props.logout} changeTab={this.changeTab} />}
|
||||
<TabContent show={activeTab === 0}>
|
||||
{
|
||||
openStream
|
||||
? <div id="commentBox">
|
||||
<InfoBox
|
||||
content={asset.settings.infoBoxContent}
|
||||
enable={asset.settings.infoBoxEnable}
|
||||
/>
|
||||
<RestrictedContent restricted={false} restrictedComp={<SuspendedAccount />}>
|
||||
{
|
||||
user
|
||||
? <CommentBox
|
||||
commentPostedHandler={refetch}
|
||||
addNotification={this.props.addNotification}
|
||||
postItem={this.props.postItem}
|
||||
appendItemArray={this.props.appendItemArray}
|
||||
updateItem={this.props.updateItem}
|
||||
assetId={asset.id}
|
||||
premod={asset.settings.moderation}
|
||||
isReply={false}
|
||||
currentUser={this.props.auth.user}
|
||||
banned={false}
|
||||
authorId={user.id}
|
||||
charCount={asset.settings.charCountEnable && asset.settings.charCount} />
|
||||
: null
|
||||
}
|
||||
</RestrictedContent>
|
||||
</div>
|
||||
: <p>{asset.settings.closedMessage}</p>
|
||||
}
|
||||
{!loggedIn && <SignInContainer offset={signInOffset}/>}
|
||||
<Stream
|
||||
refetch={refetch}
|
||||
addNotification={this.props.addNotification}
|
||||
postItem={this.props.postItem}
|
||||
asset={asset}
|
||||
currentUser={user}
|
||||
postAction={this.props.postAction}
|
||||
deleteAction={this.props.deleteAction}
|
||||
showSignInDialog={this.props.showSignInDialog}
|
||||
comments={asset.comments} />
|
||||
<Notification
|
||||
notifLength={4500}
|
||||
clearNotification={this.props.clearNotification}
|
||||
notification={{text: null}}
|
||||
/>
|
||||
</TabContent>
|
||||
<TabContent show={activeTab === 1}>
|
||||
<SettingsContainer
|
||||
loggedIn={loggedIn}
|
||||
userData={this.props.userData}
|
||||
showSignInDialog={this.props.showSignInDialog}
|
||||
/>
|
||||
</TabContent>
|
||||
<TabContent show={activeTab === 2}>
|
||||
<RestrictedContent restricted={!loggedIn}>
|
||||
<ConfigureStreamContainer
|
||||
status={status}
|
||||
onClick={this.toggleStatus}
|
||||
/>
|
||||
</RestrictedContent>
|
||||
</TabContent>
|
||||
<Notification
|
||||
notifLength={4500}
|
||||
clearNotification={this.props.clearNotification}
|
||||
notification={this.props.notification}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +183,13 @@ const mapStateToProps = state => ({
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
requestConfirmEmail: () => dispatch(requestConfirmEmail()),
|
||||
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()),
|
||||
showSignInDialog: (offset) => dispatch(showSignInDialog(offset)),
|
||||
logout: () => dispatch(logout()),
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
html, body {
|
||||
width:auto;
|
||||
height:auto;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
@@ -46,7 +51,6 @@ hr {
|
||||
/* Notification styles */
|
||||
#coral-notif {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
border: 0;
|
||||
background: rgb(105,105,105);
|
||||
color: white;
|
||||
@@ -76,6 +80,8 @@ hr {
|
||||
.commentStream {
|
||||
/* prevent absolutely positioned final permalink popover from being clipped */
|
||||
padding-bottom: 50px;
|
||||
min-height: 600px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Comment Box Styles */
|
||||
@@ -219,8 +225,8 @@ hr {
|
||||
.coral-plugin-flags-popup span {
|
||||
min-width: 280px;
|
||||
bottom: 36px;
|
||||
left: -190px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.coral-plugin-flags-popup-form {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
export const ADD_NOTIFICATION = 'ADD_NOTIFICATION';
|
||||
export const CLEAR_NOTIFICATION = 'CLEAR_NOTIFICATION';
|
||||
|
||||
export const addNotification = (notifType, text) => {
|
||||
export const addNotification = (notifType, text, position) => {
|
||||
return {
|
||||
type: ADD_NOTIFICATION,
|
||||
notifType,
|
||||
text
|
||||
text,
|
||||
position
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React from 'react';
|
||||
import {SnackBar} from 'coral-ui';
|
||||
|
||||
const Notification = (props) => {
|
||||
if (props.notification.text) {
|
||||
@@ -6,14 +7,16 @@ const Notification = (props) => {
|
||||
props.clearNotification();
|
||||
}, props.notifLength);
|
||||
}
|
||||
return <div>
|
||||
{
|
||||
props.notification.text &&
|
||||
<dialog open id='coral-notif' className={`coral-notif-${ props.notification.type}`}>
|
||||
{props.notification.text}
|
||||
</dialog>
|
||||
}
|
||||
</div>;
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
props.notification.text &&
|
||||
<SnackBar id='coral-notif' className={`coral-notif-${props.notification.type}`} position={props.notification.position}>
|
||||
{props.notification.text}
|
||||
</SnackBar>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Notification;
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
/* Items Notifications */
|
||||
|
||||
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) => {
|
||||
switch (action.type) {
|
||||
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:
|
||||
return initialState;
|
||||
default:
|
||||
|
||||
@@ -1,51 +1,47 @@
|
||||
import React, {Component} from 'react';
|
||||
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';
|
||||
import styles from './styles.css';
|
||||
|
||||
export default class AuthorName extends Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
showTooltip: false
|
||||
};
|
||||
state = {showTooltip: false}
|
||||
|
||||
this.handleMouseOver = this.handleMouseOver.bind(this);
|
||||
this.handleMouseLeave = this.handleMouseLeave.bind(this);
|
||||
handleClick = () => {
|
||||
this.setState(state => ({
|
||||
showTooltip: !state.showTooltip
|
||||
}));
|
||||
}
|
||||
|
||||
handleMouseOver () {
|
||||
this.setState({
|
||||
showTooltip: true
|
||||
});
|
||||
}
|
||||
|
||||
handleMouseLeave () {
|
||||
this.setState({
|
||||
showTooltip: false
|
||||
});
|
||||
handleMouseLeave = () => {
|
||||
setTimeout(() => {
|
||||
this.setState({
|
||||
showTooltip: false
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
|
||||
render () {
|
||||
const {author} = this.props;
|
||||
const {showTooltip} = this.state;
|
||||
return (
|
||||
<div
|
||||
className={`${packagename}-text`}
|
||||
onMouseOver={this.handleMouseOver}
|
||||
onMouseLeave={this.handleMouseLeave}
|
||||
>
|
||||
{author && author.name}
|
||||
{ showTooltip && author.settings.bio && <Tooltip>
|
||||
<div className={`${packagename}-text ${styles.container}`} onClick={this.handleClick} onMouseLeave={this.handleMouseLeave}>
|
||||
<a className={`${styles.authorName} ${author.settings.bio ? styles.hasBio : ''}`}>
|
||||
{author && author.name}
|
||||
{author.settings.bio ? <span className={`${styles.arrowDown} ${showTooltip ? styles.arrowUp : ''}`} /> : null}
|
||||
</a>
|
||||
{showTooltip && author.settings.bio
|
||||
&& (
|
||||
<Tooltip>
|
||||
<div className={`${packagename}-bio`}>
|
||||
{author.settings.bio}
|
||||
</div>
|
||||
<div className={`${packagename}-bio-flag`}>
|
||||
<FlagBio {...this.props}/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
}
|
||||
</Tooltip>
|
||||
)}
|
||||
</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;
|
||||
}
|
||||
@@ -10,8 +10,8 @@ const getPopupMenu = [
|
||||
return {
|
||||
header: lang.t('step-1-header'),
|
||||
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'),
|
||||
sets: 'itemType'
|
||||
|
||||
@@ -3,6 +3,8 @@ import I18n from 'coral-framework/modules/i18n/i18n';
|
||||
import translations from './translations';
|
||||
import onClickOutside from 'react-onclickoutside';
|
||||
const name = 'coral-plugin-permalinks';
|
||||
import {Button} from 'coral-ui';
|
||||
import styles from './styles.css';
|
||||
|
||||
const lang = new I18n(translations);
|
||||
|
||||
@@ -32,40 +34,37 @@ class PermalinkButton extends React.Component {
|
||||
this.permalinkInput.select();
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
this.setState({copySuccessful: true});
|
||||
this.setState({copySuccessful: true, copyFailure: null});
|
||||
} catch (err) {
|
||||
this.setState({copyFailure: true});
|
||||
this.setState({copyFailure: true, copySuccessful: null});
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.setState({copyFailure: null, copySuccessful: null});
|
||||
}, 4500);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
render () {
|
||||
const {copySuccessful, copyFailure} = this.state;
|
||||
return (
|
||||
<div className={`${name}-container`}>
|
||||
<button onClick={this.toggle} className={`${name}-button`}>
|
||||
<i className={`${name}-icon material-icons`} aria-hidden={true}>link</i>
|
||||
{lang.t('permalink.permalink')}
|
||||
</button>
|
||||
<div
|
||||
className={`${name}-popover ${this.state.popoverOpen ? 'active' : ''}`}>
|
||||
<div 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`} onClick={this.copyPermalink}>Copy</button>
|
||||
{
|
||||
this.state.copySuccessful ? <p className={`${name}-copied-text`}>copied to clipboard</p> : null
|
||||
}
|
||||
{
|
||||
this.state.copyFailure
|
||||
? <p className={`${name}-copied-error`}>copying to clipboard not supported in this browser. Use Cmd + C.</p>
|
||||
: null
|
||||
}
|
||||
<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>
|
||||
);
|
||||
|
||||
@@ -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": {
|
||||
"permalink": {
|
||||
"permalink": "Permalink"
|
||||
"permalink": "Link"
|
||||
}
|
||||
},
|
||||
"es": {
|
||||
"permalink": {
|
||||
"permalink": "Enlace permanente"
|
||||
"permalink": "Enlace"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,11 @@ import I18n from 'coral-framework/modules/i18n/i18n';
|
||||
import translations from '../translations';
|
||||
const lang = new I18n(translations);
|
||||
|
||||
const UserBox = ({className, user, logout, ...props}) => (
|
||||
<div
|
||||
className={`${styles.userBox} ${className ? className : ''}`}
|
||||
{...props}
|
||||
>
|
||||
const UserBox = ({className, user, logout, changeTab}) => (
|
||||
<div className={`${styles.userBox} ${className ? className : ''}`}>
|
||||
{lang.t('signIn.loggedInAs')}
|
||||
<a>{user.displayName}</a>. {lang.t('signIn.notYou')}
|
||||
<a onClick={logout} id='logout'>{lang.t('signIn.logout')}</a>
|
||||
<a onClick={() => changeTab(1)}>{user.displayName}</a>. {lang.t('signIn.notYou')}
|
||||
<a className={styles.logout} onClick={logout} id='logout'>{lang.t('signIn.logout')}</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
|
||||
@@ -93,7 +93,10 @@ input.error{
|
||||
margin: 0px;
|
||||
margin-left: 4px;
|
||||
padding-bottom: 2px;
|
||||
border-bottom: solid 1px black;
|
||||
}
|
||||
|
||||
.userBox .logout {
|
||||
border-bottom: solid 1px black;
|
||||
}
|
||||
|
||||
.attention {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
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}>
|
||||
<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>
|
||||
{label && <span>{label}</span>}
|
||||
{info && (
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -3,7 +3,7 @@
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
border: solid 1px #2376D8;
|
||||
top: 33px;
|
||||
top: 48px;
|
||||
left: 0;
|
||||
box-sizing: border-box;
|
||||
background: white;
|
||||
|
||||
@@ -16,3 +16,4 @@ export {default as Card} from './components/Card';
|
||||
export {default as FormField} from './components/FormField';
|
||||
export {default as Success} from './components/Success';
|
||||
export {default as Pager} from './components/Pager';
|
||||
export {default as SnackBar} from './components/SnackBar';
|
||||
|
||||
@@ -73,7 +73,7 @@ const getCountsByParentID = (context, parent_ids) => {
|
||||
* @param {Object} context graph context
|
||||
* @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();
|
||||
|
||||
// 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) {
|
||||
comments = comments.where({asset_id});
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ describe ('notificationsReducer', () => {
|
||||
type: 'test'
|
||||
});
|
||||
const result = notificationReducer(store, action);
|
||||
expect(result.get('text')).to.equal(undefined);
|
||||
expect(result.get('type')).to.equal(undefined);
|
||||
expect(result.get('text')).to.equal('');
|
||||
expect(result.get('type')).to.equal('');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+25
-1
@@ -28,6 +28,7 @@
|
||||
<script type='text/javascript' src='<%= basePath %>/pym.v1.min.js'></script>
|
||||
<script>
|
||||
var ready = false;
|
||||
var notificationOffset = 200;
|
||||
|
||||
// default to using the window.location
|
||||
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});
|
||||
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 () {
|
||||
var interval = setInterval(function () {
|
||||
if (ready) {
|
||||
@@ -65,6 +80,15 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
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>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user