diff --git a/client/coral-admin/src/containers/Dashboard/FlagWidget.js b/client/coral-admin/src/containers/Dashboard/FlagWidget.js
index 468875d3d..17be2acbd 100644
--- a/client/coral-admin/src/containers/Dashboard/FlagWidget.js
+++ b/client/coral-admin/src/containers/Dashboard/FlagWidget.js
@@ -19,7 +19,11 @@ const FlagWidget = ({assets}) => {
{
assets.length
? assets.map(asset => {
- const flagSummary = asset.action_summaries.find(s => s.type === 'FlagAssetActionSummary');
+ let flagSummary = null;
+ if (asset.action_summaries) {
+ flagSummary = asset.action_summaries.find(s => s.type === 'FlagAssetActionSummary');
+ }
+
return (
Moderate
diff --git a/client/coral-admin/src/containers/Streams/Streams.css b/client/coral-admin/src/containers/Stories/Stories.css
similarity index 100%
rename from client/coral-admin/src/containers/Streams/Streams.css
rename to client/coral-admin/src/containers/Stories/Stories.css
diff --git a/client/coral-admin/src/containers/Streams/Streams.js b/client/coral-admin/src/containers/Stories/Stories.js
similarity index 97%
rename from client/coral-admin/src/containers/Streams/Streams.js
rename to client/coral-admin/src/containers/Stories/Stories.js
index bd5ce6e85..4d2ad086a 100644
--- a/client/coral-admin/src/containers/Streams/Streams.js
+++ b/client/coral-admin/src/containers/Stories/Stories.js
@@ -1,5 +1,5 @@
import React, {Component} from 'react';
-import styles from './Streams.css';
+import styles from './Stories.css';
import {connect} from 'react-redux';
import I18n from 'coral-framework/modules/i18n/i18n';
import {fetchAssets, updateAssetState} from '../../actions/assets';
@@ -12,7 +12,7 @@ import EmptyCard from 'coral-admin/src/components/EmptyCard';
const limit = 25;
-class Streams extends Component {
+class Stories extends Component {
state = {
search: '',
@@ -182,6 +182,6 @@ const mapDispatchToProps = (dispatch) => {
};
};
-export default connect(mapStateToProps, mapDispatchToProps)(Streams);
+export default connect(mapStateToProps, mapDispatchToProps)(Stories);
const lang = new I18n(translations);
diff --git a/client/coral-admin/src/containers/Streams/Stories.js b/client/coral-admin/src/containers/Streams/Stories.js
new file mode 100644
index 000000000..4d2ad086a
--- /dev/null
+++ b/client/coral-admin/src/containers/Streams/Stories.js
@@ -0,0 +1,187 @@
+import React, {Component} from 'react';
+import styles from './Stories.css';
+import {connect} from 'react-redux';
+import I18n from 'coral-framework/modules/i18n/i18n';
+import {fetchAssets, updateAssetState} from '../../actions/assets';
+import translations from '../../translations.json';
+import {Link} from 'react-router';
+
+import {Pager, Icon} from 'coral-ui';
+import {DataTable, TableHeader, RadioGroup, Radio} from 'react-mdl';
+import EmptyCard from 'coral-admin/src/components/EmptyCard';
+
+const limit = 25;
+
+class Stories extends Component {
+
+ state = {
+ search: '',
+ sort: 'desc',
+ filter: 'all',
+ statusMenus: {},
+ timer: null,
+ page: 0
+ }
+
+ componentDidMount () {
+ this.props.fetchAssets(0, limit, '', this.state.sortBy);
+ }
+
+ onSettingChange = (setting) => (e) => {
+ let options = this.state;
+ this.setState({[setting]: e.target.value});
+ options[setting] = e.target.value;
+ this.props.fetchAssets(0, limit, options.search, options.sort, options.filter);
+ }
+
+ onSearchChange = (e) => {
+ const search = e.target.value;
+ this.setState((prevState) => {
+ prevState.search = search;
+ clearTimeout(prevState.timer);
+ const fetchAssets = this.props.fetchAssets;
+ prevState.timer = setTimeout(() => {
+ fetchAssets(0, limit, search, this.state.sort, this.state.filter);
+ }, 350);
+ return prevState;
+ });
+ }
+
+ renderDate = (date) => {
+ const d = new Date(date);
+ return `${d.getMonth() + 1}/${d.getDate()}/${d.getFullYear()}`;
+ }
+
+ onStatusClick = (closeStream, id, statusMenuOpen) => () => {
+ if (statusMenuOpen) {
+ this.setState(prev => {
+ prev.statusMenus[id] = false;
+ return prev;
+ });
+ this.props.updateAssetState(id, closeStream ? Date.now() : null)
+ .then(() => {
+ const {search, sort, filter, page} = this.state;
+ this.props.fetchAssets(page, limit, search, sort, filter);
+ });
+ } else {
+ this.setState(prev => {
+ prev.statusMenus[id] = true;
+ return prev;
+ });
+ }
+ }
+
+ renderTitle = (title, {id}) =>
{title}
+
+ renderStatus = (closedAt, {id}) => {
+ const closed = closedAt && new Date(closedAt).getTime() < Date.now();
+ const statusMenuOpen = this.state.statusMenus[id];
+ return
+
+ {!statusMenuOpen && }
+ {closed ? lang.t('streams.closed') : lang.t('streams.open')}
+
+ {
+ statusMenuOpen &&
+
+ {!closed ? lang.t('streams.closed') : lang.t('streams.open')}
+
+ }
+
;
+ }
+
+ onPageClick = (page) => {
+ this.setState({page});
+ const {search, sort, filter} = this.state;
+ this.props.fetchAssets((page - 1) * limit, limit, search, sort, filter);
+ }
+
+ render () {
+ const {search, sort, filter} = this.state;
+ const {assets} = this.props;
+
+ const assetsIds = assets.ids.map((id) => assets.byId[id]);
+
+ return (
+
+
+
+
+
+
+
{lang.t('streams.filter-streams')}
+
{lang.t('streams.stream-status')}
+
+ {lang.t('streams.all')}
+ {lang.t('streams.open')}
+ {lang.t('streams.closed')}
+
+
{lang.t('streams.sort-by')}
+
+ {lang.t('streams.newest')}
+ {lang.t('streams.oldest')}
+
+
+ {
+ assetsIds.length
+ ?
+
+ {lang.t('streams.article')}
+
+ {lang.t('streams.pubdate')}
+
+
+ {lang.t('streams.status')}
+
+
+
+
+ :
{lang.t('streams.empty_result')}
+ }
+
+ );
+ }
+}
+
+const mapStateToProps = ({assets}) => {
+ return {
+ assets: assets.toJS()
+ };
+};
+
+const mapDispatchToProps = (dispatch) => {
+ return {
+ fetchAssets: (...args) => {
+ dispatch(fetchAssets.apply(this, args));
+ },
+ updateAssetState: (...args) => dispatch(updateAssetState.apply(this, args))
+ };
+};
+
+export default connect(mapStateToProps, mapDispatchToProps)(Stories);
+
+const lang = new I18n(translations);
diff --git a/client/coral-admin/src/translations.json b/client/coral-admin/src/translations.json
index 8a8c0ee14..13538e224 100644
--- a/client/coral-admin/src/translations.json
+++ b/client/coral-admin/src/translations.json
@@ -82,7 +82,7 @@
"moderate": "Moderate",
"configure": "Configure",
"community": "Community",
- "streams": "Streams",
+ "stories": "Stories",
"closed-comments-desc": "Write a message to be displayed when when your comment stream is closed and no longer accepting comments.",
"closed-comments-label": "Write a message...",
"hours": "Hours",
@@ -139,9 +139,9 @@
"sort-by": "Sort By",
"open": "Open",
"closed": "Closed",
- "article": "Article",
+ "article": "Story",
"pubdate": "Publication Date",
- "status": "Status"
+ "status": "Stream Status"
}
},
"es": {
@@ -214,7 +214,7 @@
"moderate": "Moderar",
"configure": "Configurar",
"community": "Comunidad",
- "streams": "Streams",
+ "stories": "Artículos",
"closed-comments-desc": "Escribe un mensaje que será mostrado cuando los comentarios estén cerrados y no se acepten más comentarios.",
"closed-comments-label": "Escribe un mensaje...",
"never": "Nunca",
@@ -261,7 +261,7 @@
"sort-by": "",
"open": "",
"closed": "",
- "article": "",
+ "article": "artículo",
"pubdate": "",
"status": ""
}
diff --git a/client/coral-framework/actions/auth.js b/client/coral-framework/actions/auth.js
index ba1952e29..9dedaa2f2 100644
--- a/client/coral-framework/actions/auth.js
+++ b/client/coral-framework/actions/auth.js
@@ -48,7 +48,7 @@ export const fetchSignIn = (formData) => (dispatch) => {
dispatch(signInRequest());
return coralApi('/auth/local', {method: 'POST', body: formData})
.then(({user}) => {
- const isAdmin = !!user.roles.filter(i => i === 'ADMIN').length;
+ const isAdmin = !!user && !!user.roles.filter(i => i === 'ADMIN').length;
dispatch(signInSuccess(user, isAdmin));
dispatch(hideSignInDialog());
})