Skip to content

Commit

Permalink
Merge stable into release 0.7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Berkus Decker committed Mar 2, 2016
2 parents eff6491 + f7d37b3 commit 8a7e990
Show file tree
Hide file tree
Showing 34 changed files with 822 additions and 125 deletions.
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "reactive-pepyatka",
"version": "0.6.4",
"version": "0.7.0",
"description": "",
"main": "index.js",
"dependencies": {
Expand All @@ -13,7 +13,7 @@
"extract-text-webpack-plugin": "^0.8.2",
"ff-url-finder": "^2.1.8",
"file-loader": "^0.8.4",
"history": "^1.17.0",
"history": "^2.0.0",
"isomorphic-fetch": "^2.1.1",
"jade": "^1.11.0",
"jade-html-loader": "bline/jade-html-loader",
Expand All @@ -32,14 +32,14 @@
"react-dropzone-component": "^0.8.1",
"react-google-recaptcha": "^0.5.2",
"react-redux": "~4.0.6",
"react-router": "1.0.3",
"react-router": "^2.0.0",
"react-router-redux": "^4.0.0",
"react-select": "^1.0.0-beta6",
"react-textarea-autosize": "^3.1.0",
"redux": "~3.0.5",
"redux-logger": "^2.0.0",
"redux-router": "^1.0.0-beta7",
"sass-loader": "^2.0.1",
"skin-deep": "^0.12.0",
"socket.io-client": "^1.4.4",
"style-loader": "^0.12.4",
"tap-webpack-plugin": "^1.0.0",
"tape": "^4.2.2",
Expand Down
1 change: 1 addition & 0 deletions src/components/create-post.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ export default class CreatePost extends React.Component {
{this.props.sendTo.expanded ? (
<SendTo ref="selectFeeds"
feeds={this.props.sendTo.feeds}
defaultFeed={this.props.sendTo.defaultFeed}
user={this.props.user}
onChange={this.checkCreatePostAvailability}/>
) : false}
Expand Down
4 changes: 2 additions & 2 deletions src/components/discussions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const FeedHandler = (props) => {
<div className='box-header-timeline'>
{props.boxHeader}
</div>
<PaginatedView firstPageHead={createPostComponent}>
<PaginatedView firstPageHead={createPostComponent} {...props}>
<Feed {...props}/>
</PaginatedView>
<div className='box-footer'>
Expand All @@ -43,7 +43,7 @@ function selectState(state) {
const createPostForm = joinCreatePostData(state)
const timelines = state.timelines
const boxHeader = state.boxHeader
const sendTo = state.sendTo
const sendTo = {...state.sendTo, defaultFeed: user.username}

return { user, authenticated, visibleEntries, createPostViewState, createPostForm, timelines, boxHeader, sendTo }
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/footer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {Link} from 'react-router'

export default (props) => (
<footer className="footer">
&copy; FreeFeed 0.6.4 (February 25, 2016)<br/>
&copy; FreeFeed 0.7.0 (March 2, 2016)<br/>
<Link to="/about">About</Link> | <Link to="/freefeed">News</Link> | <a href="https://twitter.com/freefeednet" target="_blank">Twitter</a> | <a href="https://status.freefeed.net/" target="_blank">Status</a>
</footer>
)
4 changes: 2 additions & 2 deletions src/components/group-settings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ const GroupSettings = (props) => (
)
)

function mapStateToProps(state) {
function mapStateToProps(state, ownProps) {
return {
group: (_.find(state.users, { 'username': state.router.params.userName }) || {}),
group: (_.find(state.users, { 'username': ownProps.params.userName }) || {}),
groupSettings: state.groupSettings,
groupSettingsForm: state.groupSettingsForm
}
Expand Down
11 changes: 8 additions & 3 deletions src/components/home.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {getQuery} from '../utils'
import CreatePost from './create-post'
import Feed from './feed'
import PaginatedView from './paginated-view'
import RealtimeSwitch from './realtime-switch'
import Welcome from './welcome'

const FeedHandler = (props) => {
Expand All @@ -26,9 +27,12 @@ const FeedHandler = (props) => {
<div className='box'>
<div className='box-header-timeline'>
{props.boxHeader}
<div className='pull-right'>
{props.areOnFirstHomePage && props.authenticated ? <RealtimeSwitch/> : false}
</div>
</div>
{props.authenticated ? (
<PaginatedView firstPageHead={createPostComponent}>
<PaginatedView firstPageHead={createPostComponent} {...props}>
<Feed {...props} isInHomeFeed={true}/>
</PaginatedView>
) : (
Expand All @@ -49,13 +53,14 @@ function selectState(state) {
const createPostForm = joinCreatePostData(state)
const timelines = state.timelines
const boxHeader = state.boxHeader
const sendTo = state.sendTo
const sendTo = {...state.sendTo, defaultFeed: user.username}

return {
user, authenticated,
visibleEntries, hiddenEntries, isHiddenRevealed,
createPostViewState, createPostForm,
timelines, boxHeader, sendTo
timelines, boxHeader, sendTo,
areOnFirstHomePage: !state.routing.locationBeforeTransitions.query.offset,
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/components/layout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ const InternalLayout = ({authenticated, children}) => (
</div>
)

const logoHandler = (router, cb) => _ => {
if (getCurrentRouteName(router) === 'home') {
const logoHandler = (routeName, cb) => _ => {
if (routeName === 'home') {
return cb()
}
return false
Expand Down Expand Up @@ -130,7 +130,7 @@ class Layout extends React.Component {
<header className="row">
<div className="col-xs-9 col-sm-6">
<h1>
<IndexLink to="/" onClick={logoHandler(props.router, props.home)}>FreeFeed</IndexLink>
<IndexLink to="/" onClick={logoHandler(props.routeName, props.home)}>FreeFeed</IndexLink>
</h1>
</div>

Expand Down Expand Up @@ -168,13 +168,13 @@ class Layout extends React.Component {
}
}

function select(state) {
function select(state, ownProps) {
return {
user: state.user,
authenticated: state.authenticated,
loadingView: state.routeLoadingState,
recentGroups: state.recentGroups,
router: state.router,
routeName: getCurrentRouteName(ownProps),
}
}

Expand Down
9 changes: 4 additions & 5 deletions src/components/paginated-view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ const PaginatedView = props => (
</div>
)

const mapStateToProps = state => {
const offset = (+state.router.location.query.offset || 0)
const routename = getCurrentRouteName(state.router)
const router = state.router
return { offset, routename, router}
const mapStateToProps = (state, ownProps) => {
const offset = +state.routing.locationBeforeTransitions.query.offset || 0
const routename = getCurrentRouteName(ownProps)
return { offset, routename }
}

const mapDispatchToProps = dispatch => ({
Expand Down
14 changes: 6 additions & 8 deletions src/components/pagination-links.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import {Link} from 'react-router'

const PAGE_SIZE = 30

const minOffset = offset => Math.max(offset - PAGE_SIZE,0)
const offsetObject = offset => offset ? ({offset}) : undefined
const minOffset = offset => Math.max(offset - PAGE_SIZE, 0)
const maxOffset = offset => offset + PAGE_SIZE
const offsetObject = offset => offset ? ({offset}) : {}

//deep merge is deep indeed
const getNextRoute = (router, offset) => ({
Expand All @@ -19,22 +19,20 @@ const getNextRoute = (router, offset) => ({
}
})

const routingCallback = ({offset, routename, router, routingActions}, offsetSelector) => _ => routingActions(routename)(getNextRoute(router, offsetSelector(offset)))
const routingCallback = (props, offsetSelector) => _ => props.routingActions(props.routename)(getNextRoute(props, offsetSelector(props.offset)))

export default props => (
<ul className="pager p-pagination-controls">
{props.offset > 0 ?
<li>
<Link onClick={routingCallback(props, minOffset)}
to={props.router.location.pathname}
query={offsetObject(minOffset(props.offset))}
<Link to={{pathname:'', query: offsetObject(minOffset(props.offset))}}
onClick={routingCallback(props, minOffset)}
className="p-pagination-newer">« Newer items</Link>
</li>
: false}
<li>
<Link to={props.router.location.pathname}
<Link to={{pathname:'', query:offsetObject(maxOffset(props.offset))}}
onClick={routingCallback(props, maxOffset)}
query={offsetObject(maxOffset(props.offset))}
className="p-pagination-older">Older items »</Link>
</li>
</ul>
Expand Down
3 changes: 2 additions & 1 deletion src/components/post.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,9 @@ export default class Post extends React.Component {
}

// "Like" / "Un-like"
const amIAuthenticated = !!props.user.id
const didILikePost = _.find(props.usersLikedPost, {id: props.user.id})
const likeLink = (!props.isEditable ? (
const likeLink = (amIAuthenticated && !props.isEditable ? (
<span>
{' - '}
<a onClick={didILikePost ? unlikePost : likePost}>{didILikePost ? 'Un-like' : 'Like'}</a>
Expand Down
41 changes: 41 additions & 0 deletions src/components/realtime-switch.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react'
import {connect} from 'react-redux'
import {toggleRealtime, updateFrontendRealtimePreferences, home} from '../redux/action-creators'

const getStatusIcon = (active, status) => {
if (status === 'loading'){
return 'refresh'
}
return active ? 'pause' : 'play'
}

const realtimeSwitch = props => (
<div className='realtime-switch' onClick={_ => props.toggle(props.userId, !props.realtimeActive)}>
{props.realtimeActive ? false : 'Paused'}
<span className={`glyphicon glyphicon-${getStatusIcon(props.realtimeActive, props.status)}`}/>
</div>
)

const mapStateToProps = (state) => {
return {
userId: state.user.id,
realtimeActive: state.frontendRealtimePreferencesForm.realtimeActive,
status: state.frontendRealtimePreferencesForm.status,
}
}

const mapDispatchToProps = (dispatch) => {
return {
toggle: (userId, settingActive) => {
//send a request to change flag
dispatch(updateFrontendRealtimePreferences(userId, {realtimeActive: settingActive}))
//set a flag to show
dispatch(toggleRealtime())
if (settingActive) {
dispatch(home())
}
}
}
}

export default connect(mapStateToProps, mapDispatchToProps)(realtimeSwitch)
15 changes: 13 additions & 2 deletions src/components/select-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ export const joinPostData = state => postId => {
let comments = (post.comments || []).map(commentId => {
const comment = state.comments[commentId]
const commentViewState = state.commentViewState[commentId]
const author = state.users[comment.createdBy]
const placeholderUser = {id: comment.createdBy}
const author = state.users[comment.createdBy] || placeholderUser
if (author === placeholderUser) {
console.log('We\'ve got comment with unknown author with id', placeholderUser.id)
}
const isEditable = (user.id === comment.createdBy)
const isDeletable = (user.id === post.createdBy)
return { ...comment, ...commentViewState, user: author, isEditable, isDeletable }
Expand All @@ -51,7 +55,14 @@ export const joinPostData = state => postId => {
usersLikedPost = usersLikedPost.slice(0, MAX_LIKES)
}

const createdBy = state.users[post.createdBy]
const placeholderUser = {id: post.createdBy}

const createdBy = state.users[post.createdBy] || placeholderUser

if (createdBy === placeholderUser) {
console.log('We\'ve got post with unknown author with id', placeholderUser.id)
}

const isEditable = (post.createdBy === user.id)

// Check if the post is a direct message
Expand Down
39 changes: 21 additions & 18 deletions src/components/send-to.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,47 @@ import React from 'react'
import Select from 'react-select'
import {preventDefault} from '../utils'

const MY_FEED = 'My feed'
const MY_FEED_LABEL = 'My feed'

export default class SendTo extends React.Component {
constructor(props) {
super(props)

let options = props.feeds.map( function (item) {
let name = item.user.username
return { label: name, value: name, type: item.user.type }
})
let options = props.feeds.map((item) => ({
label: item.user.username,
value: item.user.username,
type: item.user.type
}))

let currentUsername = props.user.username
options.unshift({ label: MY_FEED, value: currentUsername, type: 'group' })
let myFeedUsername = props.user.username
options.unshift({ label: MY_FEED_LABEL, value: myFeedUsername, type: 'group' })

this._values = [currentUsername]
this._values = [props.defaultFeed]

this.state = {
value: this._values,
values: this._values,
options: options,
showFeedsOption: false,
isWarningDisplayed: false
}
}

get values() {
return this._values
}

isGroupsOrDirectsOnly = (value) => {
isGroupsOrDirectsOnly = (values) => {
let types = {}
for (let v of value) {
for (let v of values) {
types[v.type] = v
}
return Object.keys(types).length <= 1
}

selectChanged = (value) => {
this._values = value.map(item => item.value)
let isWarningDisplayed = !this.isGroupsOrDirectsOnly(value)
this.setState({ value, isWarningDisplayed })
selectChanged = (values) => {
this._values = values.map(item => item.value)
let isWarningDisplayed = !this.isGroupsOrDirectsOnly(values)
this.setState({ values, isWarningDisplayed })
this.props.onChange()
}

Expand All @@ -51,20 +52,22 @@ export default class SendTo extends React.Component {
}

render() {
const defaultFeedLabel = (this.state.values[0] === this.props.user.username ? MY_FEED_LABEL : this.state.values[0])

return (
<div className="send-to">
{!this.state.showFeedsOption ? (
<div>
To:&nbsp;
<span className="Select-value-label-standalone">My feed</span>&nbsp;
<span className="Select-value-label-standalone">{defaultFeedLabel}</span>&nbsp;
<a className="p-sendto-toggler" onClick={preventDefault(_=>this.toggleSendTo())}>Add/Edit</a>
</div>
) : (
<div>
<Select
name="select-feeds"
placeholder="Select feeds..."
value={this.state.value}
value={this.state.values}
options={this.state.options}
onChange={this.selectChanged}
multi={true}
Expand Down
Loading

0 comments on commit 8a7e990

Please sign in to comment.