Merge branch 'master' of github.com:coralproject/talk into action-focus-states

This commit is contained in:
Belen Curcio
2017-06-19 14:03:07 -03:00
13 changed files with 53 additions and 53 deletions
@@ -1,6 +1,5 @@
.layout {
max-width: 1280px;
margin: 0 auto;
overflow: hidden;
background-color: #FAFAFA;
}
@@ -11,6 +11,7 @@ import NotFoundAsset from './NotFoundAsset';
import ModerationKeysModal from '../../../components/ModerationKeysModal';
import UserDetail from '../containers/UserDetail';
import StorySearch from '../containers/StorySearch';
import {Spinner} from 'coral-ui';
export default class Moderation extends Component {
state = {
@@ -102,18 +103,22 @@ export default class Moderation extends Component {
}
render () {
const {root, moderation, settings, assets, viewUserDetail, hideUserDetail, ...props} = this.props;
const {root, moderation, settings, viewUserDetail, hideUserDetail, ...props} = this.props;
const providedAssetId = this.props.params.id;
const activeTab = this.props.route.path === ':id' ? 'premod' : this.props.route.path;
let asset;
const {asset} = root;
if (providedAssetId) {
asset = assets.find((asset) => asset.id === this.props.params.id);
if (asset === null) {
if (!asset) {
// Not found.
return <NotFoundAsset assetId={providedAssetId} />;
}
if (asset === undefined || asset.id !== providedAssetId) {
// Still loading.
return <Spinner />;
}
}
const comments = root[activeTab];
@@ -9,12 +9,12 @@ const formatDate = (date) => {
const Story = ({author, title, createdAt, open, id, goToStory}) => {
return (
<li className={styles.story} onClick={() => goToStory(id)}>
<p className={styles.title}>{title}</p>
<p className={styles.meta}>
<span className={styles.title}>{title}</span>
<div className={styles.meta}>
<span className={styles.author}>By {author}</span>
<span className={styles.createdAt}>{formatDate(createdAt)}</span>
<span className={styles.status}>{open ? 'Open' : 'Closed'}</span>
</p>
</div>
</li>
);
};
@@ -12,7 +12,7 @@
.container {
position: absolute;
background-color: white;
top: 100px;
top: 106px;
left: 0;
right: 0;
margin-left: auto;
@@ -29,8 +29,7 @@
.headInput {
background-color: #efefef;
padding: 17px 56px;
height: 80px;
padding: 10px 27px;
box-sizing: border-box;
}
@@ -41,12 +40,13 @@
font-size: 16px;
margin-right: 5px;
position: relative;
top: 2px;
top: 3px;
box-sizing: border-box;
border-radius: 3px;
border: solid 1px #dfdfdf;
max-height: 45px;
max-width: 600px;
font-weight: 300;
}
.cta {
@@ -59,20 +59,22 @@
font-size: 15px;
font-weight: 500;
padding: 12px 30px;
letter-spacing: 0.7px;
letter-spacing: 0.25px;
}
.storyList {
/*.storyList {
border-top: 1px solid #ddd;
}
}*/
.story {
padding: 10px 63px;
padding: 7px 50px;
border-bottom: 1px solid #ddd;
cursor: pointer;
display: block;
text-decoration: none;
height: 50px;
box-sizing: border-box;
transition: background-color 400ms;
&:hover {
background-color: #efefef;
@@ -86,7 +88,7 @@
.title, .meta {
margin: 0;
color: black;
font-size: 17px;
font-size: 15px;
}
.author, .createdAt, .status {
@@ -117,7 +119,8 @@
}
.searchResults {
padding: 10px 24px;
padding: 7px 27px;
background: #F5F5F5;
}
.searchResults i {
@@ -132,12 +135,11 @@
.headlineRecent {
font-size: 15px;
font-weight: 500;
letter-spacing: 0.7px;
letter-spacing: 0.25px;
vertical-align: middle;
margin-left: 10px;
margin-left: 8px;
}
.noResults {
padding: 10px 24px 15px 49px;
}
@@ -19,7 +19,7 @@ const StorySearch = (props) => {
return (
<div>
<div className={styles.container} role='alertdialog'>
<div className={styles.container} role='alertdialog' onKeyDown={props.handleEsc}>
<div className={styles.positionShim}>
<div className={styles.headInput}>
<input
@@ -2,7 +2,6 @@ import React, {Component} from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {compose, gql} from 'react-apollo';
import isEqual from 'lodash/isEqual';
import withQuery from 'coral-framework/hocs/withQuery';
import {getDefinitionName} from 'coral-framework/utils';
import * as notification from 'coral-admin/src/services/notification';
@@ -12,7 +11,6 @@ import update from 'immutability-helper';
import {withSetUserStatus, withSuspendUser, withSetCommentStatus} from 'coral-framework/graphql/mutations';
import {fetchSettings} from 'actions/settings';
import {updateAssets} from 'actions/assets';
import {
toggleModal,
singleView,
@@ -39,13 +37,6 @@ class ModerationContainer extends Component {
this.props.fetchSettings();
}
componentWillReceiveProps(nextProps) {
const {updateAssets} = this.props;
if(!isEqual(nextProps.root.assets, this.props.root.assets)) {
updateAssets(nextProps.root.assets);
}
}
suspendUser = async (args) => {
this.props.hideSuspendUserDialog();
try {
@@ -175,7 +166,7 @@ const commentConnectionFragment = gql`
`;
const withModQueueQuery = withQuery(gql`
query CoralAdmin_Moderation($asset_id: ID, $sort: SORT_ORDER) {
query CoralAdmin_Moderation($asset_id: ID, $sort: SORT_ORDER, $allAssets: Boolean!) {
all: comments(query: {
statuses: [NONE, PREMOD, ACCEPTED, REJECTED],
asset_id: $asset_id,
@@ -212,7 +203,7 @@ const withModQueueQuery = withQuery(gql`
}) {
...CoralAdmin_Moderation_CommentConnection
}
assets: assets(query: {}) {
asset(id: $asset_id) @skip(if: $allAssets) {
id
title
url
@@ -248,6 +239,7 @@ const withModQueueQuery = withQuery(gql`
variables: {
asset_id: id,
sort: sortOrder,
allAssets: id === null
}
};
},
@@ -291,14 +283,12 @@ const mapStateToProps = (state) => ({
moderation: state.moderation.toJS(),
settings: state.settings.toJS(),
auth: state.auth.toJS(),
assets: state.assets.get('assets')
});
const mapDispatchToProps = (dispatch) => ({
...bindActionCreators({
toggleModal,
singleView,
updateAssets,
fetchSettings,
showBanUserDialog,
hideBanUserDialog,
@@ -20,6 +20,13 @@ class StorySearchContainer extends React.Component {
});
}
handleEsc = (e) => {
if (e.key === 'Escape') {
e.preventDefault();
this.props.closeSearch();
}
}
handleEnter = (e) => {
if (e.key === 'Enter') {
e.preventDefault();
@@ -43,6 +50,7 @@ class StorySearchContainer extends React.Component {
<StorySearch
search={this.search}
goToStory={this.goToStory}
handleEsc={this.handleEsc}
handleEnter={this.handleEnter}
searchValue={this.state.searchValue}
handleSearchChange={this.handleSearchChange}
@@ -54,7 +62,7 @@ class StorySearchContainer extends React.Component {
export const withAssetSearchQuery = withQuery(gql`
query SearchStories($value: String = "") {
assets(query: {value: $value}) {
assets(query: {value: $value, limit: 10}) {
id
title
url
+4 -5
View File
@@ -22,12 +22,11 @@ const genAssetsByID = (context, ids) => AssetModel.find({
/**
* [getAssetsByQuery description]
* @param {Object} context the context of the request
* @param {String} value text string to search agains the documents
* @param {Number} limit limit the number of results
* @param {Object} query the query
* @return {Promise} resolves the assets
*/
const getAssetsByQuery = (context, value, limit) => {
return AssetsService.search(value, null, limit);
const getAssetsByQuery = (context, query) => {
return AssetsService.search(query);
};
/**
@@ -76,7 +75,7 @@ module.exports = (context) => ({
// this operation create a new asset if one isn't found.
getByURL: (url) => findOrCreateAssetByURL(context, url),
search: (value, limit) => getAssetsByQuery(context, value, limit),
search: (query) => getAssetsByQuery(context, query),
getByID: new DataLoader((ids) => genAssetsByID(context, ids)),
getForMetrics: () => getAssetsForMetrics(context),
getAll: new util.SingletonResolver(() => AssetModel.find({}))
+1 -3
View File
@@ -11,9 +11,7 @@ const RootQuery = {
return null;
}
const {value = '', limit} = query;
return Assets.search(value, limit);
return Assets.search(query);
},
asset(_, query, {loaders: {Assets}}) {
if (query.id) {
+1 -1
View File
@@ -634,7 +634,7 @@ type RootQuery {
comment(id: ID!): Comment
# All assets. Requires the `ADMIN` role.
assets(query: AssetsQuery!): [Asset]
assets(query: AssetsQuery): [Asset]
# Find or create an asset by url, or just find with the ID.
asset(id: ID, url: String): Asset
+2 -2
View File
@@ -48,13 +48,13 @@ router.get('/', (req, res, next) => {
Promise.all([
// Find the actuall assets.
FilterOpenAssets(AssetsService.search(search), filter)
FilterOpenAssets(AssetsService.search({value: search}), filter)
.sort({[field]: (sort === 'asc') ? 1 : -1})
.skip(parseInt(skip))
.limit(parseInt(limit)),
// Get the count of actual assets.
FilterOpenAssets(AssetsService.search(search), filter)
FilterOpenAssets(AssetsService.search({value: search}), filter)
.count()
])
.then(([result, count]) => {
+3 -4
View File
@@ -104,13 +104,12 @@ module.exports = class AssetsService {
}
/**
* Finds assets matching keywords on the model. If `value` is an empty string,
* then it will not even perform a text search query.
* Finds assets matching keywords on the model.
* @param {String} value string to search by.
* @return {Promise}
*/
static search(value = '', skip = null, limit = null) {
if (value.length === 0) {
static search({value, skip, limit} = {}) {
if (!value) {
return AssetsService.all(skip, limit);
} else {
return AssetModel
+1 -1
View File
@@ -43,7 +43,7 @@ describe('/api/v1/assets', () => {
.set(passport.inject({roles: ['ADMIN']}))
.then((res) => {
const body = res.body;
expect(body).to.have.property('count', 2);
expect(body).to.have.property('result');