Updated NewsView, TrendsHeadlinesPanel, TrendsRSSPanel
• Updated: - NewsView, TrendsHeadlinesPanel, TrendsRSSPanel
This commit is contained in:
parent
b6f8674054
commit
bef3ad6fca
|
@ -1,6 +1,7 @@
|
|||
import api from '../api'
|
||||
import axios from 'axios'
|
||||
import { importFetchedStatuses } from './importer'
|
||||
import { TRENDS_RSS_SOURCES } from '../constants'
|
||||
|
||||
export const GAB_TRENDS_FETCH_REQUEST = 'GAB_TRENDS_FETCH_REQUEST'
|
||||
export const GAB_TRENDS_FETCH_SUCCESS = 'GAB_TRENDS_FETCH_SUCCESS'
|
||||
|
@ -54,36 +55,40 @@ const fetchGabTrendsFail = (error) => ({
|
|||
/**
|
||||
*
|
||||
*/
|
||||
export const expandGabTrendsFeed = (feedId, page = 0) => (dispatch, getState) => {
|
||||
dispatch(expandGabTrendsFeedRequest(feedId, page))
|
||||
export const expandGabTrendsFeed = (feedId) => (dispatch, getState) => {
|
||||
if (!feedId) return
|
||||
const exists = !!TRENDS_RSS_SOURCES.find((block) => block.id === feedId)
|
||||
if (!exists) return
|
||||
|
||||
// const url = `http://trends.gab.com/feed/${feedId}?fmt=json`
|
||||
api(getState).get(`/api/v1/gab_trends?type=rss`).then((response) => {
|
||||
const page = getState().getIn(['news', 'trends_feeds', `${feedId}`, 'curPage'], 0) + 1
|
||||
|
||||
dispatch(expandGabTrendsFeedRequest(feedId))
|
||||
|
||||
// const url = `http://trends.gab.com/feed/${feedId}?fmt=json&p=${page}`
|
||||
api(getState).get(`/api/v1/gab_trends?type=rss&page=${page}&feedId=${feedId}`).then((response) => {
|
||||
// axios.get(url).then((response) => {
|
||||
dispatch(expandGabTrendsFeedSuccess(response.data, feedId, page))
|
||||
dispatch(expandGabTrendsFeedSuccess(response.data.rssFeedItems, feedId, response.data.pagination.p))
|
||||
}).catch((error) => {
|
||||
dispatch(expandGabTrendsFeedFail(error, feedId, page))
|
||||
dispatch(expandGabTrendsFeedFail(error, feedId))
|
||||
})
|
||||
}
|
||||
|
||||
const expandGabTrendsFeedRequest = (feedId, page) => ({
|
||||
const expandGabTrendsFeedRequest = (feedId) => ({
|
||||
type: GAB_TREND_FEED_EXPAND_REQUEST,
|
||||
feedId,
|
||||
page,
|
||||
})
|
||||
|
||||
const expandGabTrendsFeedSuccess = (items, feedId, page) => ({
|
||||
const expandGabTrendsFeedSuccess = (items, feedId, curPage) => ({
|
||||
type: GAB_TREND_FEED_EXPAND_SUCCESS,
|
||||
items,
|
||||
feedId,
|
||||
page,
|
||||
curPage,
|
||||
})
|
||||
|
||||
const expandGabTrendsFeedFail = (error, feedId, page) => ({
|
||||
const expandGabTrendsFeedFail = (error, feedId) => ({
|
||||
type: GAB_TREND_FEED_EXPAND_FAIL,
|
||||
error,
|
||||
feedId,
|
||||
page,
|
||||
})
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,11 +21,11 @@ class TrendsHeadlinesPanel extends ImmutablePureComponent {
|
|||
} = this.props
|
||||
|
||||
const count = !!items ? items.count() : 0
|
||||
const trendsLeadlineTitle = trendsLeadline.get('title')
|
||||
const trendsLeadlineImage = trendsLeadline.get('image')
|
||||
const trendsLeadlineUrl = trendsLeadline.get('trends_url')
|
||||
const trendsLeadlineTitle = trendsLeadline ? trendsLeadline.get('title') : null
|
||||
const trendsLeadlineImage = trendsLeadline ? trendsLeadline.get('image') : null
|
||||
const trendsLeadlineUrl = trendsLeadline ? trendsLeadline.get('trends_url') : null
|
||||
|
||||
if ((count === 0 && isFetched) && (!trendsLeadlineTitle || !trendsLeadlineTitle || !trendsLeadlineTitle)) return null
|
||||
if ((count === 0 && isFetched) && (!trendsLeadlineImage || !trendsLeadlineTitle || !trendsLeadlineTitle)) return null
|
||||
|
||||
const leadlineButtonClasses = CX({
|
||||
d: 1,
|
||||
|
@ -64,18 +64,21 @@ class TrendsHeadlinesPanel extends ImmutablePureComponent {
|
|||
</Button>
|
||||
))
|
||||
}
|
||||
<Button
|
||||
noClasses
|
||||
href={''}
|
||||
className={leadlineButtonClasses}
|
||||
>
|
||||
<Image
|
||||
src='https://trends.gab.com/image/5fa5d8badf30e602384b08ed'
|
||||
/>
|
||||
<Text className={[_s.px15, _s.py15, _s.w100PC, _s.borderTop1PX, _s.borderColorSecondary].join(' ')}>
|
||||
Lawsuit: At Least 21K Dead People on Pennsylvania Voter Rolls
|
||||
</Text>
|
||||
</Button>
|
||||
{
|
||||
!!trendsLeadlineImage && !!trendsLeadlineTitle && trendsLeadlineUrl &&
|
||||
<Button
|
||||
noClasses
|
||||
href={trendsLeadlineUrl}
|
||||
className={leadlineButtonClasses}
|
||||
>
|
||||
<Image
|
||||
src={trendsLeadlineImage}
|
||||
/>
|
||||
<Text className={[_s.px15, _s.py15, _s.w100PC, _s.borderTop1PX, _s.borderColorSecondary].join(' ')}>
|
||||
{trendsLeadlineTitle}
|
||||
</Text>
|
||||
</Button>
|
||||
}
|
||||
</PanelLayout>
|
||||
)
|
||||
}
|
||||
|
@ -85,7 +88,7 @@ const mapStateToProps = (state) => ({
|
|||
isLoading: state.getIn(['news', 'trends_headlines', 'isLoading']),
|
||||
isFetched: state.getIn(['news', 'trends_headlines', 'isFetched']),
|
||||
items: state.getIn(['news', 'trends_headlines', 'items']),
|
||||
trendsLeadline: state.getIn(['news', 'trends_leadline']),
|
||||
trendsLeadline: state.getIn(['news', 'trends_leadline', 'items']),
|
||||
})
|
||||
|
||||
TrendsHeadlinesPanel.propTypes = {
|
||||
|
|
|
@ -1,33 +1,143 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'react-redux'
|
||||
import { List as ImmutableList } from 'immutable'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { expandGabTrendsFeed } from '../../actions/news'
|
||||
import {
|
||||
CX,
|
||||
BREAKPOINT_EXTRA_SMALL,
|
||||
} from '../../constants'
|
||||
import { getWindowDimension } from '../../utils/is_mobile'
|
||||
import PanelLayout from './panel_layout'
|
||||
import TrendsCard from '../trends_card'
|
||||
import Button from '../button'
|
||||
import LoadMore from '../load_more'
|
||||
import ScrollableList from '../scrollable_list'
|
||||
|
||||
const initialState = getWindowDimension()
|
||||
|
||||
class TrendsRSSPanel extends ImmutablePureComponent {
|
||||
|
||||
state = {
|
||||
viewType: 0,
|
||||
fetched: false,
|
||||
isXS: initialState.width <= BREAKPOINT_EXTRA_SMALL,
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
if (nextProps.shouldLoad && !prevState.fetched) {
|
||||
return { fetched: true }
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if ((!prevState.fetched && this.state.fetched && this.props.isLazy) ||
|
||||
((prevProps.trendsRSSId !== this.props.trendsRSSId) && !!prevProps.trendsRSSId)) {
|
||||
this.handleOnExpand()
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.isLazy) {
|
||||
this.handleOnExpand()
|
||||
this.setState({ fetched: true })
|
||||
}
|
||||
|
||||
this.handleResize()
|
||||
window.addEventListener('keyup', this.handleKeyUp, false)
|
||||
window.addEventListener('resize', this.handleResize, false)
|
||||
}
|
||||
|
||||
handleResize = () => {
|
||||
const { width } = getWindowDimension()
|
||||
|
||||
this.setState({ isXS: width <= BREAKPOINT_EXTRA_SMALL })
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('keyup', this.handleKeyUp)
|
||||
window.removeEventListener('resize', this.handleResize, false)
|
||||
}
|
||||
|
||||
onItemViewClick = () => {
|
||||
this.setState({ viewType: this.state.viewType === 0 ? 1 : 0 })
|
||||
}
|
||||
|
||||
handleOnExpand = () => {
|
||||
this.props.dispatch(expandGabTrendsFeed(this.props.trendsRSSId))
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
intl,
|
||||
onChange,
|
||||
settings,
|
||||
trendsRSSId,
|
||||
isLoading,
|
||||
isFetched,
|
||||
items,
|
||||
hideReadMore,
|
||||
feed,
|
||||
} = this.props
|
||||
const {
|
||||
fetched,
|
||||
viewType,
|
||||
isXS,
|
||||
} = this.state
|
||||
|
||||
const count = !!items ? items.count() : 0
|
||||
if (count === 0 && fetched) return null
|
||||
const hasMore = count % 10 === 0
|
||||
|
||||
const containerClasses = CX({
|
||||
d: 1,
|
||||
w100PC: 1,
|
||||
flexRow: viewType === 1,
|
||||
flexWrap: viewType === 1,
|
||||
})
|
||||
|
||||
return (
|
||||
<PanelLayout>
|
||||
TrendsRSSPanel
|
||||
</PanelLayout>
|
||||
<div className={[_s.d, _s.w100PC].join(' ')}>
|
||||
<div className={containerClasses} >
|
||||
<ScrollableList
|
||||
scrollKey={`trends-rss-panel-${trendsRSSId}`}
|
||||
onLoadMore={this.handleOnExpand}
|
||||
hasMore={hasMore}
|
||||
isLoading={isLoading}
|
||||
emptyMessage='No feed items found.'
|
||||
disableInfiniteScroll
|
||||
>
|
||||
{
|
||||
items.map((trend, i) => (
|
||||
<TrendsCard
|
||||
isXS={isXS}
|
||||
trend={trend}
|
||||
viewType={viewType}
|
||||
key={`trend-card-rss-${i}`}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
//
|
||||
const mapStateToProps = (state, { trendsRSSId }) => ({
|
||||
isLoading: state.getIn(['news', 'trends_feeds', `${trendsRSSId}`, 'isLoading'], false),
|
||||
isFetched: state.getIn(['news', 'trends_feeds', `${trendsRSSId}`, 'isFetched'], false),
|
||||
items: state.getIn(['news', 'trends_feeds', `${trendsRSSId}`, 'items'], ImmutableList()),
|
||||
})
|
||||
|
||||
TrendsFeedsPanel.propTypes = {
|
||||
//
|
||||
TrendsRSSPanel.propTypes = {
|
||||
isLazy: PropTypes.bool,
|
||||
isLoading: PropTypes.bool,
|
||||
isFetched: PropTypes.bool,
|
||||
trendsRSSId: PropTypes.string.isRequired,
|
||||
items: ImmutablePropTypes.list,
|
||||
isPage: PropTypes.bool,
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(TrendsRSSPanel)
|
|
@ -4,20 +4,78 @@ import { connect } from 'react-redux'
|
|||
import { TRENDS_RSS_SOURCES } from '../constants'
|
||||
import WrappedBundle from './ui/util/wrapped_bundle'
|
||||
import { TrendsRSSPanel } from './ui/util/async_components'
|
||||
import Button from '../components/button'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
import Text from '../components/text'
|
||||
|
||||
class NewsView extends React.PureComponent {
|
||||
|
||||
state = {
|
||||
exists: false,
|
||||
orderedSources: [],
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { params: { trendsRSSId } } = this.props
|
||||
this.setState({
|
||||
exists: this.getExists(trendsRSSId),
|
||||
orderedSources: this.getOrderedSources(trendsRSSId)
|
||||
})
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
const { params: { trendsRSSId } } = this.props
|
||||
if (prevProps.params.trendsRSSId !== trendsRSSId) {
|
||||
this.setState({
|
||||
exists: this.getExists(trendsRSSId),
|
||||
orderedSources: this.getOrderedSources(trendsRSSId),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
getExists = (trendsRSSId) => {
|
||||
return !!TRENDS_RSS_SOURCES.find((source) => source.id === trendsRSSId)
|
||||
}
|
||||
|
||||
getOrderedSources = (trendsRSSId) => {
|
||||
const source = TRENDS_RSS_SOURCES.find((source) => source.id === trendsRSSId)
|
||||
const sourceIndex = TRENDS_RSS_SOURCES.findIndex((source) => source.id === trendsRSSId)
|
||||
if (!source) return []
|
||||
let orderedSources = TRENDS_RSS_SOURCES.filter((source) => source.id !== trendsRSSId);
|
||||
const activeSource = { ...source, isActive: 1 }
|
||||
orderedSources[sourceIndex] = activeSource
|
||||
orderedSources.unshift(activeSource);
|
||||
return orderedSources
|
||||
}
|
||||
|
||||
render() {
|
||||
const { params: { trendsRSSId } } = this.props
|
||||
console.log("trendsRSSId:", trendsRSSId)
|
||||
const exists = !!TRENDS_RSS_SOURCES.find((block) => block.id === trendsRSSId)
|
||||
const { orderedSources, exists } = this.state
|
||||
|
||||
if (!exists) return <ColumnIndicator type='missing' />
|
||||
|
||||
return (
|
||||
<div className={[_s.d, _s.w100PC].join(' ')}>
|
||||
<WrappedBundle component={TrendsRSSPanel} />
|
||||
<div className={[_s.d, _s.flexRow, _s.w100PC, _s.overflowXScroll, _s.py10, _s.px10, _s.mb5].join(' ')}>
|
||||
{
|
||||
orderedSources.map((block, i) => (
|
||||
<Button
|
||||
isNarrow
|
||||
to={block.isActive ? undefined : `/news/view/${block.id}`}
|
||||
color={block.isActive ? 'white' : 'primary'}
|
||||
backgroundColor={block.isActive ? 'brand' : 'tertiary'}
|
||||
className={[_s.mr10, _s.mb10].join(' ')}
|
||||
key={`trends-feeds-panel-${i}`}
|
||||
>
|
||||
<Text color='inherit'>
|
||||
{block.title}
|
||||
</Text>
|
||||
</Button>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
<WrappedBundle component={TrendsRSSPanel} componentParams={{ trendsRSSId }} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -25,11 +25,7 @@ const defaultMap = ImmutableMap({
|
|||
})
|
||||
|
||||
const initialState = ImmutableMap({
|
||||
trends_leadline: ImmutableMap({
|
||||
title: null,
|
||||
image: null,
|
||||
trends_url: null,
|
||||
}),
|
||||
trends_leadline: ImmutableMap(),
|
||||
trends_headlines: defaultMap,
|
||||
trends_breaking: defaultMap,
|
||||
gab_news: defaultMap,
|
||||
|
@ -72,7 +68,9 @@ const normalizeNewsItem = (item) => {
|
|||
|
||||
const setStateKeysOnRequest = (state, keys) => {
|
||||
return state.withMutations((map) => {
|
||||
keys.map((key) => map.setIn([key, 'isLoading'], true))
|
||||
keys.map((key) => {
|
||||
map.setIn([key, 'isLoading'], true)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -107,19 +105,18 @@ export default function (state = initialState, action) {
|
|||
try {
|
||||
trendsFetchData.trends_headlines = ImmutableList(action.items.trends.leadHeadlines.map((item) => normalizeHeadlineItem(item)))
|
||||
trendsFetchData.trends_breaking = ImmutableList(action.items.trends.rssFeedItems.map((item) => normalizeTrendsItem(item)))
|
||||
trendsFetchData.trends_leadline = ImmutableMap({
|
||||
title: action.items.trends.headline.title,
|
||||
image: `https://trends.gab.com/image/${action.items.trends.headline.image._id}`,
|
||||
trends_url: `https://trends.gab.com/trend?url=${action.items.trends.headline.href}`,
|
||||
})
|
||||
} catch (error) {
|
||||
trendsFetchData = {
|
||||
breakingItems: ImmutableList(),
|
||||
headlineItems: ImmutableList(),
|
||||
trends_leadline: ImmutableMap(),
|
||||
}
|
||||
}
|
||||
// : todo :
|
||||
// trends_leadline: ImmutableMap({
|
||||
// title: null,
|
||||
// image: null,
|
||||
// trends_url: null,
|
||||
// }),
|
||||
|
||||
return setStateKeysOnSuccess(state, trendsFetchData)
|
||||
|
||||
//
|
||||
|
@ -148,13 +145,48 @@ export default function (state = initialState, action) {
|
|||
try {
|
||||
latestGabNewsData.gab_news = ImmutableList(action.items.map((item) => normalizeNewsItem(item)))
|
||||
} catch (error) {
|
||||
console.log("news reducer error: ", error)
|
||||
latestGabNewsData = {
|
||||
gab_news: ImmutableList(),
|
||||
}
|
||||
}
|
||||
return setStateKeysOnSuccess(state, latestGabNewsData)
|
||||
|
||||
//
|
||||
case GAB_TREND_FEED_EXPAND_REQUEST:
|
||||
return state.withMutations((map) => {
|
||||
const exists = !!map.getIn(['trends_feeds', `${action.feedId}`], null)
|
||||
if (!exists) {
|
||||
map.setIn(['trends_feeds', `${action.feedId}`], ImmutableMap({
|
||||
isLoading: false,
|
||||
isFetched: false,
|
||||
items: ImmutableList(),
|
||||
}))
|
||||
} else {
|
||||
map.setIn(['trends_feeds', `${action.feedId}`, 'isLoading'], true)
|
||||
}
|
||||
})
|
||||
case GAB_TREND_FEED_EXPAND_FAIL:
|
||||
return state.withMutations((map) => {
|
||||
map.setIn(['trends_feeds', `${action.feedId}`], ImmutableMap({
|
||||
isLoading: false,
|
||||
isFetched: true,
|
||||
items: ImmutableList(),
|
||||
}))
|
||||
})
|
||||
case GAB_TREND_FEED_EXPAND_SUCCESS:
|
||||
let latestGabTrendFeedData = []
|
||||
try {
|
||||
latestGabTrendFeedData = state.getIn(['trends_feeds', `${action.feedId}`, 'items']).concat(action.items.map((item) => normalizeTrendsItem(item)))
|
||||
} catch (error) {
|
||||
latestGabTrendFeedData = ImmutableList()
|
||||
}
|
||||
|
||||
return state.withMutations((map) => {
|
||||
map.setIn(['trends_feeds', `${action.feedId}`, 'isLoading'], false)
|
||||
map.setIn(['trends_feeds', `${action.feedId}`, 'isFetched'], true)
|
||||
map.setIn(['trends_feeds', `${action.feedId}`, 'curPage'], action.curPage)
|
||||
map.setIn(['trends_feeds', `${action.feedId}`, 'items'], latestGabTrendFeedData)
|
||||
})
|
||||
default:
|
||||
return state
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue