diff --git a/client/coral-admin/src/routes/Moderation/components/Comment.css b/client/coral-admin/src/routes/Moderation/components/Comment.css new file mode 100644 index 000000000..f7aeac4d8 --- /dev/null +++ b/client/coral-admin/src/routes/Moderation/components/Comment.css @@ -0,0 +1,179 @@ +@custom-media --big-viewport (min-width: 780px); + +.root { + border-bottom: 1px solid #e0e0e0; + font-size: 18px; + width: 100%; + max-width: 650px; + min-width: 400px; + margin: 0 auto; + position: relative; + transition: all 200ms; + padding: 10px 0; + min-height: 0; + + /* + Fix rendering issues in Safari by promoting this + into its own layer. + + https://www.pivotaltracker.com/story/show/151142211 + */ + transform: translateZ(0); + + &:last-child { + border-bottom: none; + } +} + +.container { + padding: 0 14px; +} + +.itemHeader { + display: flex; + align-items: center; + justify-content: space-between; + +} + +.author { + font-weight: 300; + width: 100%; + display: flex; + align-items: center; + color: #262626; + font-size: 16px; + position: relative; +} + +.sideActions { + height: 100%; + top: 0; + box-sizing: border-box; +} + +.itemBody { + display: flex; + justify-content: space-between; + font-size: 14px; + line-height: 1.5; + font-weight: 300; +} + +.body { + margin-top: 0px; + flex: 1; + color: black; + max-width: 500px; + word-wrap: break-word; + font-weight: 300; + font-size: 16px; +} + +.created { + padding: 5px; + color: #262626; + font-size: 14px; + line-height: 1px; + font-weight: 300; +} + +.moderateArticle { + font-size: 14px; + margin: 10px 0; + font-weight: 500; + line-height: 1.2; + max-width: 500px; + + a { + display: inline-block; + color: #063b9a; + text-decoration: none; + font-weight: 500; + letter-spacing: .5px; + margin-left: 10px; + + font-size: 13px; + margin-left: 5px; + padding-bottom: 0px; + border-bottom: solid 1px; + line-height: 16px; + + &:hover { + opacity: .9; + cursor: pointer; + } + } +} + +.username { + color: #393B44; + text-decoration: none; + cursor: pointer; + font-weight: 600; + padding: 2px 5px; + border-radius: 2px; + margin-left: -5px; + transition: background-color 200ms ease; + &:hover { + background-color: #E0E0E0; + } +} + +.external { + font-size: .7em; + text-decoration: none; + color: #063b9a; + cursor: pointer; + font-weight: normal; + margin-left: 10px; + white-space: nowrap; + + &:hover { + text-decoration: underline; + opacity: .9; + } + + i { + font-size: 12px; + top: 2px; + position: relative; + } +} + +.editedMarker { + font-style: italic; + color: #666; + font-size: 12px; + line-height: 1px; + font-weight: 300; +} + +.adminCommentInfoBar { + min-width: 100px; + position: absolute; + right: 0px; + top: 0px; + text-align: right; +} + +.hasLinks { + color: #f00; + text-align: right; + display: flex; + align-items: center; + + i { + margin-right: 5px; + } +} + +@media (--big-viewport) { + .root { + margin-bottom: 30px; + + &:last-child { + border-bottom: 1px solid #e0e0e0; + } + } +} diff --git a/client/coral-admin/src/routes/Moderation/components/Comment.js b/client/coral-admin/src/routes/Moderation/components/Comment.js index b210d8f23..57d1ea7fb 100644 --- a/client/coral-admin/src/routes/Moderation/components/Comment.js +++ b/client/coral-admin/src/routes/Moderation/components/Comment.js @@ -4,7 +4,7 @@ import {Link} from 'react-router'; import {Icon} from 'coral-ui'; import FlagBox from 'coral-admin/src/components/FlagBox'; -import styles from './styles.css'; +import styles from './Comment.css'; import CommentLabels from 'coral-admin/src/components/CommentLabels'; import CommentAnimatedEdit from 'coral-admin/src/components/CommentAnimatedEdit'; import Slot from 'coral-framework/components/Slot'; @@ -72,7 +72,8 @@ class Comment extends React.Component { return (
  • diff --git a/client/coral-admin/src/routes/Moderation/components/Moderation.js b/client/coral-admin/src/routes/Moderation/components/Moderation.js index dcbb7510e..19a0d2ea7 100644 --- a/client/coral-admin/src/routes/Moderation/components/Moderation.js +++ b/client/coral-admin/src/routes/Moderation/components/Moderation.js @@ -1,6 +1,5 @@ import React, {Component} from 'react'; import key from 'keymaster'; -import styles from './styles.css'; import ModerationQueue from './ModerationQueue'; import ModerationMenu from './ModerationMenu'; @@ -10,11 +9,12 @@ import StorySearch from '../containers/StorySearch'; import Slot from 'coral-framework/components/Slot'; export default class Moderation extends Component { - constructor() { - super(); + constructor(props) { + super(props); + const comments = this.getComments(props); this.state = { - selectedIndex: 0 + selectedCommentId: comments[0] ? comments[0].id : null, }; } @@ -25,10 +25,10 @@ export default class Moderation extends Component { key('s', () => singleView()); key('shift+/', () => toggleModal(true)); key('esc', () => toggleModal(false)); - key('j', this.select(true)); - key('k', this.select(false)); - key('f', this.moderate(false)); - key('d', this.moderate(true)); + key('j', () => this.select(true)); + key('k', () => this.select(false)); + key('f', () => this.moderate(false)); + key('d', () => this.moderate(true)); } onClose = () => { @@ -44,11 +44,15 @@ export default class Moderation extends Component { this.props.toggleStorySearch(true); } - moderate = (accept) => () => { + getActiveTabCount = (props = this.props) => { + return props.root[`${props.activeTab}Count`]; + } + + moderate = (accept) => { const {acceptComment, rejectComment} = this.props; - const {selectedIndex} = this.state; + const {selectedCommentId} = this.state; const comments = this.getComments(); - const comment = comments[selectedIndex]; + const comment = comments[selectedCommentId]; const commentId = {commentId: comment.id}; if (accept) { @@ -58,25 +62,75 @@ export default class Moderation extends Component { } } - getComments = () => { - const {root, activeTab} = this.props; + getComments = (props = this.props) => { + const {root, activeTab} = props; return root[activeTab].nodes; } - select = (next) => () => { - if (next) { - this.setState((state) => ({ - ...state, - selectedIndex: state.selectedIndex < this.getComments().length - 1 - ? state.selectedIndex + 1 : state.selectedIndex - })); - } else { - this.setState((state) => ({ - ...state, - selectedIndex: state.selectedIndex > 0 - ? state.selectedIndex - 1 : state.selectedIndex - })); + scrollTo = (toId) => + document.querySelector(`#comment_${toId}`).scrollIntoView({behavior: 'smooth'}); + + select = async (next, props = this.props, selectedCommentId = this.state.selectedCommentId) => { + const comments = this.getComments(props); + + if (comments.length === 0){ + return; } + + const index = selectedCommentId + ? comments.findIndex((comment) => comment.id === selectedCommentId) + : null; + + if (next) { + if (!selectedCommentId) { + this.setState({selectedCommentId: comments[0].id}, () => this.scrollTo(comments[0].id)); + return; + } + + if (index < comments.length - 1) { + this.setState({selectedCommentId: comments[index + 1].id}, () => this.scrollTo(comments[index + 1].id)); + return; + } else { + + // We hit the end of the list, load more comments if we have. + if (comments.length < this.getActiveTabCount()) { + const res = await this.loadMore(); + + // If `loadMore` was already in progress, res would be false. + if (res) { + + // Select next comment after loading has completed. + this.select(true); + } + } + return; + } + } else { + if (!selectedCommentId) { + return; + } + + if (index > 0) { + this.setState({selectedCommentId: comments[index - 1].id}, () => this.scrollTo(comments[index - 1].id)); + return; + } + } + } + + loadMore = async () => { + if (!this.isLoadingMore) { + this.isLoadingMore = true; + try { + const result = await this.props.loadMore(this.props.activeTab); + this.isLoadingMore = false; + return result; + } + catch (e) { + this.isLoadingMore = false; + throw e; + } + } + return false; } componentWillUnmount() { @@ -89,14 +143,41 @@ export default class Moderation extends Component { key.unbind('d'); } - componentDidUpdate(_, prevState) { + componentWillReceiveProps(nextProps) { - // If paging through using keybaord shortcuts, scroll the page to keep the selected - // comment in view. - if (prevState.selectedIndex !== this.state.selectedIndex) { + if (this.props.activeTab !== nextProps.activeTab) { - // the 'smooth' flag only works in FF as of March 2017 - document.querySelector(`.${styles.selected}`).scrollIntoView({behavior: 'smooth'}); + // Reset selection when changing tabs. + this.select(true, nextProps, null); + } else { + + // Detect if comment has left the queue and find next or prev selected comment to set it + // as the new selectedCommentId. + const prevComments = this.getComments(this.props); + const nextComments = this.getComments(nextProps); + if (nextComments.length < prevComments.length) { + if ( + this.state.selectedCommentId && + !nextComments.some((comment) => comment.id === this.state.selectedCommentId) + ) { + const prevIndex = prevComments.findIndex((comment) => comment.id === this.state.selectedCommentId); + if (prevIndex !== prevComments.length - 1) { + this.setState({selectedCommentId: prevComments[prevIndex + 1].id}); + } else if(prevIndex > 0) { + this.setState({selectedCommentId: prevComments[prevIndex - 1].id}); + } else { + this.setState({selectedCommentId: null}); + } + } + } + } + } + + componentDidUpdate(prevProps) { + + // Scroll to comment when changing from single wiew to normal view. + if (prevProps.moderation.singleView !== this.props.moderation.singleView && this.state.selectedCommentId) { + this.scrollTo(this.state.selectedCommentId); } } @@ -107,7 +188,7 @@ export default class Moderation extends Component { const comments = root[activeTab]; - const activeTabCount = root[`${activeTab}Count`]; + const activeTabCount = this.getActiveTabCount(); const menuItems = Object.keys(queueConfig).map((queue) => ({ key: queue, name: queueConfig[queue].name, @@ -139,14 +220,14 @@ export default class Moderation extends Component { comments={comments.nodes} activeTab={activeTab} singleView={moderation.singleView} - selectedIndex={this.state.selectedIndex} + selectedCommentId={this.state.selectedCommentId} bannedWords={settings.wordlist.banned} suspectWords={settings.wordlist.suspect} showBanUserDialog={props.showBanUserDialog} showSuspendUserDialog={props.showSuspendUserDialog} acceptComment={props.acceptComment} rejectComment={props.rejectComment} - loadMore={props.loadMore} + loadMore={this.loadMore} assetId={assetId} sort={this.props.moderation.sortOrder} commentCount={activeTabCount} diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationHeader.css b/client/coral-admin/src/routes/Moderation/components/ModerationHeader.css new file mode 100644 index 000000000..a86688944 --- /dev/null +++ b/client/coral-admin/src/routes/Moderation/components/ModerationHeader.css @@ -0,0 +1,39 @@ +.header { + background-color: #2c2c2c; + color: white; + margin-bottom: -1px; +} + +.searchTrigger { + position: relative; + top: .2em; +} + +.moderateAsset { + a { + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1; + color: white; + text-transform: capitalize; + font-weight: 400; + font-size: 20px; + letter-spacing: 1px; + transition: background-color 200ms; + opacity: 1; + + &:hover { + cursor: pointer; + background-color: #212121; + } + span { + text-align: center; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + max-width: 344px; + display: inline-block; + vertical-align: top; + } + } +} diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationHeader.js b/client/coral-admin/src/routes/Moderation/components/ModerationHeader.js index b9bd0caff..a0ed36a62 100644 --- a/client/coral-admin/src/routes/Moderation/components/ModerationHeader.js +++ b/client/coral-admin/src/routes/Moderation/components/ModerationHeader.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import {Icon} from 'coral-ui'; -import styles from './styles.css'; +import styles from './ModerationHeader.css'; import t from 'coral-framework/services/i18n'; const ModerationHeader = ({asset, searchVisible, openSearch, closeSearch}) => { diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationMenu.css b/client/coral-admin/src/routes/Moderation/components/ModerationMenu.css new file mode 100644 index 000000000..2ee0b4ec4 --- /dev/null +++ b/client/coral-admin/src/routes/Moderation/components/ModerationMenu.css @@ -0,0 +1,102 @@ +@custom-media --big-viewport (min-width: 780px); + +.tabBar { + background-color: rgba(44, 44, 44, 0.89); + z-index: 5; + display: flex; + justify-content: space-between; +} + +.tabBarPadding { + width: 150px; +} + +.tab { + flex: 1; + color: #BDBDBD; + text-transform: capitalize; + font-weight: 100; + font-size: 14px; + letter-spacing: 1px; + transition: border-bottom 200ms; + transition: color 200ms; + padding: 0px 10px; + margin-right: 20px; + &:hover { + color: white; + /*border-bottom: solid 2px #F36451;*/ + box-sizing: border-box; + } +} + +.active { + color: white; + box-sizing: border-box; + border-bottom: solid 4px #F36451; + font-weight: 400; + &:hover { + border-bottom: solid 4px #F36451; + font-weight: 400; + } +} + +.active > span { + color: white; +} + +.active:after { + background: transparent !important; +} + +.selectField { + position: relative; + width: 140px; + height: 36px; + top: 5px; + margin-right: 10px; + background: #FFF; + padding: 10px 15px; + box-sizing: border-box; + border-radius: 2px; + bor + box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.12); + + > div { + padding: 0; + } + + i { + position: absolute; + top: 7px; + right: 7px; + } + + input { + padding: 0; + font-size: 13px; + letter-spacing: 0.7px; + font-weight: 400; + border-bottom: 0px; + } + + label { + top: -4px; + } + + &:hover { + cursor: pointer; + } +} + +.tabIcon { + position: relative; + top: 3px; + font-size: 16px; +} + + +@media (--big-viewport) { + .tab { + flex: none; + } +} diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationMenu.js b/client/coral-admin/src/routes/Moderation/components/ModerationMenu.js index 27b8409c6..74c3e2327 100644 --- a/client/coral-admin/src/routes/Moderation/components/ModerationMenu.js +++ b/client/coral-admin/src/routes/Moderation/components/ModerationMenu.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import CountBadge from '../../../components/CountBadge'; -import styles from './styles.css'; +import styles from './ModerationMenu.css'; import {SelectField, Option} from 'react-mdl-selectfield'; import {Icon} from 'coral-ui'; import {Link} from 'react-router'; diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.css b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.css index e69de29bb..f3866f55a 100644 --- a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.css +++ b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.css @@ -0,0 +1,28 @@ +.list { + padding: 8px 0; + list-style: none; + display: block; +} + +.emptyCardContainer { + margin-top: 16px; +} + +.commentLeave { + opacity: 1.0; +} + +.commentLeaveActive { + opacity: 0; + transition: opacity 800ms; +} + +.commentEnter { + opacity: 0; +} + +.commentEnterActive { + opacity: 1.0; + transition: opacity 800ms; +} + diff --git a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js index 904662364..d4838e5e0 100644 --- a/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js +++ b/client/coral-admin/src/routes/Moderation/components/ModerationQueue.js @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import Comment from '../containers/Comment'; -import styles from './styles.css'; +import styles from './ModerationQueue.css'; import EmptyCard from '../../../components/EmptyCard'; import {actionsMap} from '../../../utils/moderationQueueActionsMap'; import LoadMore from '../../../components/LoadMore'; @@ -59,18 +59,6 @@ class ModerationQueue extends React.Component { comments: PropTypes.array.isRequired } - loadMore = () => { - if (!this.isLoadingMore) { - this.isLoadingMore = true; - this.props.loadMore(this.props.activeTab) - .then(() => this.isLoadingMore = false) - .catch((e) => { - this.isLoadingMore = false; - throw e; - }); - } - } - constructor(props) { super(props); this.state = { @@ -85,7 +73,7 @@ class ModerationQueue extends React.Component { // AND there are more comments available on the server, // go ahead and load more comments if (prev.comments.length > 0 && comments.length === 0 && commentCount > 0) { - this.loadMore(); + this.props.loadMore(); } } @@ -145,7 +133,7 @@ class ModerationQueue extends React.Component { render () { const { comments, - selectedIndex, + selectedCommentId, commentCount, singleView, viewUserDetail, @@ -153,10 +141,47 @@ class ModerationQueue extends React.Component { ...props } = this.props; + if (comments.length === 0) { + return ( +
    +
    + {t('modqueue.empty_queue')} +
    +
    + ); + } + + if (singleView) { + const index = comments.findIndex((comment) => comment.id === selectedCommentId); + const comment = comments[index]; + const status = comment.action_summaries ? 'FLAGGED' : comment.status; + return ( +
    + ; +
    + ); + } + const view = this.getVisibleComments(); return ( -
    +
    { - view.map((comment, i) => { - const status = comment.action_summaries ? 'FLAGGED' : comment.status; - return ; - }) + view + .map((comment) => { + const status = comment.action_summaries ? 'FLAGGED' : comment.status; + return ; + }) } - {comments.length === 0 && -
    - {t('modqueue.empty_queue')} -
    - }
    diff --git a/client/coral-admin/src/routes/Moderation/components/NotFoundAsset.css b/client/coral-admin/src/routes/Moderation/components/NotFoundAsset.css new file mode 100644 index 000000000..6b03bfd69 --- /dev/null +++ b/client/coral-admin/src/routes/Moderation/components/NotFoundAsset.css @@ -0,0 +1,20 @@ + +.notFound { + position: relative; + margin: 20px auto; + text-align: center; + padding: 68px 45px; + vertical-align: middle; + min-width: 500px; + + a { + color: rgb(244, 126, 107); + font-weight: 500; + } +} + +.goToStreams { + position: absolute; + right: 10px; + bottom: 10px; +} diff --git a/client/coral-admin/src/routes/Moderation/components/NotFoundAsset.js b/client/coral-admin/src/routes/Moderation/components/NotFoundAsset.js index ee5d2ccd1..4f6775f0a 100644 --- a/client/coral-admin/src/routes/Moderation/components/NotFoundAsset.js +++ b/client/coral-admin/src/routes/Moderation/components/NotFoundAsset.js @@ -1,6 +1,6 @@ import React from 'react'; import {Link} from 'react-router'; -import styles from './styles.css'; +import styles from './NotFoundAsset.css'; const NotFound = (props) => (
    diff --git a/client/coral-admin/src/routes/Moderation/components/Story.css b/client/coral-admin/src/routes/Moderation/components/Story.css new file mode 100644 index 000000000..fa43bc1cd --- /dev/null +++ b/client/coral-admin/src/routes/Moderation/components/Story.css @@ -0,0 +1,49 @@ + +.story { + padding: 7px 50px; + border-bottom: 1px solid #ddd; + cursor: pointer; + display: block; + text-decoration: none; + min-height: 50px; + box-sizing: border-box; + transition: background-color 400ms; + + &:hover { + background-color: #efefef; + } + + &:last-child { + border-bottom: none; + } +} + +.title, .meta { + margin: 0; + color: black; + font-size: 15px; +} + +.author, .createdAt, .status { + font-size: 17px; + display: inline-block; + font-size: .8em; +} + +.createdAt { + text-align: center; +} + +.author { + display: inline-block; + width: 200px; + color: #aaa; +} + +.createdAt { + display: inline-block; + width: 200px; + color: #aaa; +} + + diff --git a/client/coral-admin/src/routes/Moderation/components/Story.js b/client/coral-admin/src/routes/Moderation/components/Story.js index eaad6c2a6..364afce7f 100644 --- a/client/coral-admin/src/routes/Moderation/components/Story.js +++ b/client/coral-admin/src/routes/Moderation/components/Story.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import styles from './StorySearch.css'; +import styles from './Story.css'; const formatDate = (date) => { const d = new Date(date); diff --git a/client/coral-admin/src/routes/Moderation/components/StorySearch.css b/client/coral-admin/src/routes/Moderation/components/StorySearch.css index 973d97c24..1a317ad26 100644 --- a/client/coral-admin/src/routes/Moderation/components/StorySearch.css +++ b/client/coral-admin/src/routes/Moderation/components/StorySearch.css @@ -67,54 +67,6 @@ /*.storyList { border-top: 1px solid #ddd; }*/ - -.story { - padding: 7px 50px; - border-bottom: 1px solid #ddd; - cursor: pointer; - display: block; - text-decoration: none; - min-height: 50px; - box-sizing: border-box; - transition: background-color 400ms; - - &:hover { - background-color: #efefef; - } - - &:last-child { - border-bottom: none; - } -} - -.title, .meta { - margin: 0; - color: black; - font-size: 15px; -} - -.author, .createdAt, .status { - font-size: 17px; - display: inline-block; - font-size: .8em; -} - -.createdAt { - text-align: center; -} - -.author { - display: inline-block; - width: 200px; - color: #aaa; -} - -.createdAt { - display: inline-block; - width: 200px; - color: #aaa; -} - .searchButton { width: 90px; height: 35px; diff --git a/client/coral-admin/src/routes/Moderation/components/styles.css b/client/coral-admin/src/routes/Moderation/components/styles.css deleted file mode 100644 index 8d4214760..000000000 --- a/client/coral-admin/src/routes/Moderation/components/styles.css +++ /dev/null @@ -1,495 +0,0 @@ -/** - * @TODO: deprecated as this file contains styles from multiple components. Please remove this file - * when styles have been refactored. - */ - -@custom-media --big-viewport (min-width: 780px); - -.listContainer { - max-width: 860px; - margin: 0 auto; -} - -.tabBar { - background-color: rgba(44, 44, 44, 0.89); - z-index: 5; - display: flex; - justify-content: space-between; -} - -.tabBarPadding { - width: 150px; -} - -.tab { - flex: 1; - color: #BDBDBD; - text-transform: capitalize; - font-weight: 100; - font-size: 14px; - letter-spacing: 1px; - transition: border-bottom 200ms; - transition: color 200ms; - padding: 0px 10px; - margin-right: 20px; - &:hover { - color: white; - /*border-bottom: solid 2px #F36451;*/ - box-sizing: border-box; - } -} - -.active { - color: white; - box-sizing: border-box; - border-bottom: solid 4px #F36451; - font-weight: 400; - &:hover { - border-bottom: solid 4px #F36451; - font-weight: 400; - } -} - -.active > span { - color: white; -} - -.active:after { - background: transparent !important; -} - -.showShortcuts { - position: absolute; - right: 130px; - display: flex; - align-items: center; - font-size: 13px; - -span { - margin-left: 7px; -} -} - -@media (--big-viewport) { - .tab { - flex: none; - } -} - -.notFound { - position: relative; - margin: 20px auto; - text-align: center; - padding: 68px 45px; - vertical-align: middle; - min-width: 500px; - - a { - color: rgb(244, 126, 107); - font-weight: 500; - - &.goToStreams { - position: absolute; - right: 10px; - bottom: 10px; - } - } -} - -.header { - background-color: #2c2c2c; - color: white; - margin-bottom: -1px; - - .settingsButton { - vertical-align: middle; - margin-left: 10px; - margin-top: -4px; - font-size: 16px; - } - - .moderateAsset { - a { - -webkit-box-flex: 1; - -ms-flex: 1; - flex: 1; - color: white; - text-transform: capitalize; - font-weight: 400; - font-size: 20px; - letter-spacing: 1px; - transition: background-color 200ms; - opacity: 1; - - &:hover { - cursor: pointer; - background-color: #212121; - } - span { - text-align: center; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - max-width: 344px; - display: inline-block; - vertical-align: top; - } - - } - } -} - - -@custom-media --big-viewport (min-width: 780px); - -.list { - padding: 8px 0; - list-style: none; - display: block; - - &.singleView .listItem { - display: none; - } - - &.singleView .listItem.selected { - display: block; - height: 100%; - font-size: 1.5em; - line-height: 1.5em; - border: none; - - .actions { - position: fixed; - bottom: 60px; - left: 25%; - display: flex; - justify-content: space-around; - width: 50%; - margin: 0; - } - - .actionButton { - transform: scale(1.4); - } - } -} - -.listItem { - border-bottom: 1px solid #e0e0e0; - font-size: 18px; - width: 100%; - max-width: 650px; - min-width: 400px; - margin: 0 auto; - position: relative; - transition: all 200ms; - padding: 10px 0; - min-height: 0; - - /* - Fix rendering issues in Safari by promoting this - into its own layer. - - https://www.pivotaltracker.com/story/show/151142211 - */ - transform: translateZ(0); - - .container { - padding: 0 14px; - } - - &:last-child { - border-bottom: none; - } - - &.selected { - } - - .context { - a { - color: #f36451; - text-decoration: underline; - float: right; - } - } - - .sideActions { - height: 100%; - top: 0; - box-sizing: border-box; - } - - .itemHeader { - display: flex; - align-items: center; - justify-content: space-between; - - .author { - font-weight: 300; - width: 100%; - display: flex; - align-items: center; - color: #262626; - font-size: 16px; - position: relative; - } - } - - .itemBody { - display: flex; - justify-content: space-between; - font-size: 14px; - line-height: 1.5; - font-weight: 300; - } - - .avatar { - margin-right: 16px; - height: 40px; - width: 40px; - border-radius: 50%; - background-color: #757575; - font-size: 40px; - color: #fff; - } - - .created { - padding: 5px; - color: #262626; - font-size: 14px; - line-height: 1px; - font-weight: 300; - } - - .actionButton { - transform: scale(.8); - margin: 0; - } - - .body { - margin-top: 0px; - flex: 1; - color: black; - max-width: 500px; - word-wrap: break-word; - font-weight: 300; - font-size: 16px; - } - - .flagged { - color: rgba(255, 0, 0, .5); - padding-top: 15px; - padding-left: 10px; - } - - .flagCount{ - font-size: 12px; - color: #d32f2f; - } - -} - -.empty { - color: #444; - margin-top: 50px; - text-align: center; -} - - -@media (--big-viewport) { - .listItem { - margin-bottom: 30px; - - &:last-child { - border-bottom: 1px solid #e0e0e0; - } - - &.activeItem { - border: 2px solid #333; - } - } - -} - -.hasLinks { - color: #f00; - text-align: right; - display: flex; - align-items: center; - - i { - margin-right: 5px; - } -} - -.banned { - color: #f00; - text-align: left; - display: flex; - align-items: center; - - i { - margin-right: 5px; - } -} - -.ban { - display: block; - text-align: center; - margin-top: 5px; -} - -.Comment { - - .moderateArticle { - font-size: 14px; - margin: 10px 0; - font-weight: 500; - line-height: 1.2; - max-width: 500px; - - a { - display: inline-block; - color: #063b9a; - text-decoration: none; - font-weight: 500; - letter-spacing: .5px; - margin-left: 10px; - - font-size: 13px; - margin-left: 5px; - padding-bottom: 0px; - border-bottom: solid 1px; - line-height: 16px; - - &:hover { - opacity: .9; - cursor: pointer; - } - } - } -} - -.selectField { - position: relative; - width: 140px; - height: 36px; - top: 5px; - margin-right: 10px; - background: #FFF; - padding: 10px 15px; - box-sizing: border-box; - border-radius: 2px; - bor - box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.12); - - > div { - padding: 0; - } - - i { - position: absolute; - top: 7px; - right: 7px; - } - - input { - padding: 0; - font-size: 13px; - letter-spacing: 0.7px; - font-weight: 400; - border-bottom: 0px; - } - - label { - top: -4px; - } - - &:hover { - cursor: pointer; - } -} - -.tabIcon { - position: relative; - top: 3px; - font-size: 16px; -} - -.username { - color: #393B44; - text-decoration: none; - cursor: pointer; - font-weight: 600; - padding: 2px 5px; - border-radius: 2px; - margin-left: -5px; - transition: background-color 200ms ease; - &:hover { - background-color: #E0E0E0; - } -} - -.external { - font-size: .7em; - text-decoration: none; - color: #063b9a; - cursor: pointer; - font-weight: normal; - margin-left: 10px; - white-space: nowrap; - - &:hover { - text-decoration: underline; - opacity: .9; - } - - i { - font-size: 12px; - top: 2px; - position: relative; - } -} - -.emptyCardContainer { - margin-top: 16px; -} - -.commentLeave { - opacity: 1.0; -} - -.commentLeaveActive { - opacity: 0; - transition: opacity 800ms; -} - -.commentEnter { - opacity: 0; -} - -.commentEnterActive { - opacity: 1.0; - transition: opacity 800ms; -} - -.editedMarker { - font-style: italic; - color: #666; - font-size: 12px; - line-height: 1px; - font-weight: 300; -} - -.searchTrigger { - position: relative; - top: .2em; -} - -.adminCommentInfoBar { - min-width: 100px; - position: absolute; - right: 0px; - top: 0px; - text-align: right; -}