Skip to content
This repository was archived by the owner on May 29, 2018. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,27 +66,26 @@
"express-session": "^1.12.1",
"file-loader": "^0.8.5",
"invariant": "^2.2.0",
"history": "1.17.0",
"hoist-non-react-statics": "^1.0.3",
"less": "^2.5.3",
"less-loader": "^2.2.1",
"lru-memoize": "^1.0.0",
"map-props": "^1.0.0",
"piping": "^0.3.0",
"pretty-error": "^1.2.0",
"query-string": "^3.0.0",
"react": "^0.14.2",
"react-bootstrap": "^0.28.1",
"react-helmet": "^2.2.0",
"react-dom": "^0.14.1",
"react-inline-css": "^2.0.0",
"react-redux": "^4.0.0",
"react-router": "1.0.3",
"react-router-bootstrap": "^0.19.3",
"react-router": "2.0.0",
"react-router-bootstrap": "^0.20.1",
"react-router-redux": "^3.0.0",
"redux": "^3.0.4",
"redux-async-connect": "andresgutgon/redux-async-connect#feature/deferred-first-class-citizen",
"redux-form": "^3.0.12",
"redux-router": "1.0.0-beta5",
"scroll-behavior": "^0.3.0",
"scroll-behavior": "^0.3.2",
"serialize-javascript": "^1.1.2",
"serve-favicon": "^2.3.0",
"superagent": "^1.4.0",
Expand Down
27 changes: 17 additions & 10 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,34 @@
import 'babel/polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
import createHistory from 'history/lib/createBrowserHistory';
import useScroll from 'scroll-behavior/lib/useStandardScroll';
import createStore from './redux/create';
import ApiClient from './helpers/ApiClient';
import {Provider} from 'react-redux';
import {reduxReactRouter, ReduxRouter} from 'redux-router';

import { Router, browserHistory } from 'react-router';
import { ReduxAsyncConnect } from 'redux-async-connect';
import useScroll from 'scroll-behavior/lib/useStandardScroll';

import getRoutes from './routes';
import makeRouteHooksSafe from './helpers/makeRouteHooksSafe';

const client = new ApiClient();

// Three differnt types of scroll behavior available.
// Documented here: https://github.com/rackt/scroll-behavior
const scrollableHistory = useScroll(createHistory);

const history = useScroll(() => browserHistory)();
const dest = document.getElementById('content');
const store = createStore(reduxReactRouter, makeRouteHooksSafe(getRoutes), scrollableHistory, client, window.__data);
const store = createStore(history, client, window.__data);

const component = (
<ReduxRouter routes={getRoutes(store)} />
<Router
render={(props) =>
<ReduxAsyncConnect
{...props}
helpers={{client}}
/>
}
history={history}
>
{getRoutes(store)}
</Router>
);

ReactDOM.render(
Expand Down
42 changes: 27 additions & 15 deletions src/containers/App/App.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,54 @@
import React, { Component, PropTypes } from 'react';
import { bindActionCreators } from 'redux';
import { IndexLink } from 'react-router';
import { LinkContainer } from 'react-router-bootstrap';
import { Navbar, Nav, NavItem } from 'react-bootstrap';
import Navbar from 'react-bootstrap/lib/Navbar';
import Nav from 'react-bootstrap/lib/Nav';
import NavItem from 'react-bootstrap/lib/NavItem';
import { connect } from 'react-redux';
import Helmet from 'react-helmet';
import { isLoaded as isAuthLoaded, load as loadAuth, logout } from 'redux/modules/auth';
import { pushState } from 'redux-router';
import connectData from 'helpers/connectData';
import { routeActions } from 'react-router-redux';
import { asyncConnect } from 'redux-async-connect';

import config from '../../config';

function fetchData(getState, dispatch) {
if (!isAuthLoaded(getState())) {
return dispatch(loadAuth());
}
}
@asyncConnect([{
promise: (options) => {
const {
store: { dispatch, getState },
} = options;
const promises = [];

@connectData(fetchData)
if (!isAuthLoaded(getState())) {
promises.push(dispatch(loadAuth()));
}

return Promise.all(promises);
}
}])
@connect(
state => ({user: state.auth.user}),
dispatch => bindActionCreators({logout, pushState}, dispatch))
state => ({user: state.auth.user}),
{logout, push: routeActions.push}
)
export default class App extends Component {
static propTypes = {
children: PropTypes.object.isRequired,
user: PropTypes.object,
logout: PropTypes.func.isRequired,
pushState: PropTypes.func.isRequired
push: PropTypes.func.isRequired
};

static contextTypes = {
store: PropTypes.object.isRequired
};

componentWillReceiveProps(nextProps) {
const { push } = this.props;

if (!this.props.user && nextProps.user) {
this.props.pushState(null, '/groups');
push('/groups');
} else if (this.props.user && !nextProps.user) {
this.props.pushState(null, '/login');
push('/login');
// Full real page reload to clean local data
window.location.reload();
}
Expand Down
4 changes: 2 additions & 2 deletions src/containers/DevTools/DevTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import DockMonitor from 'redux-devtools-dock-monitor';

export default createDevTools(
<DockMonitor
toggleVisibilityKey="H"
changePositionKey="Q">
toggleVisibilityKey="ctrl+H"
changePositionKey="ctrl+Q">
<LogMonitor />
</DockMonitor>
);
68 changes: 33 additions & 35 deletions src/containers/Group/Base.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,63 @@
import _ from 'underscore';
import React, {Component, PropTypes} from 'react';
import {connect} from 'react-redux';
import { asyncConnect } from 'redux-async-connect';

import connectData from 'helpers/connectData';
import { loadEntity as loadGroup } from 'redux/modules/groups/groups';
import { load as loadUsers } from 'redux/modules/users/users';
import { load as loadMemberships } from 'redux/modules/groups/memberships';
import { load as loadInvitations } from 'redux/modules/invitations/list';
import { membersWithUserSelector } from 'selectors/members';

function fetchData(getState, dispatch, location, params) {
const {
groupsReducer: {groups: { byId }},
usersReducer: { users },
membershipsReducer: { memberships },
} = getState();
const promises = [];
const id = params.id;
const group = byId[id];

promises.push(dispatch(loadInvitations(id)));

if (!users.entities.length) {
promises.push(dispatch(loadUsers()));
}

if (!memberships.entities.length) {
promises.push(dispatch(loadMemberships()));
}


if (!group) {
promises.push(dispatch(loadGroup(id)));
}

return Promise.all(promises);
}

function groupSelector(state) {
return {
...membersWithUserSelector(state),
invitations: state.invitationsReducer.invitations,
user: state.auth.user,
};
}

@connectData(fetchData)
@asyncConnect([{
promise: (options) => {
const {
store: { dispatch, getState },
params,
} = options;

const {
groupsReducer: {groups: { byId }},
usersReducer: { users },
membershipsReducer: { memberships },
} = getState();
const promises = [];
const id = params.id;
const group = byId[id];

if (!users.entities.length) {
promises.push(dispatch(loadUsers()));
}

if (!memberships.entities.length) {
promises.push(dispatch(loadMemberships()));
}

if (!group) {
promises.push(dispatch(loadGroup(id)));
}

return Promise.all(promises);
}
}])
@connect(groupSelector, {})
export default class GroupBase extends Component {
static propTypes = {
children: PropTypes.object.isRequired,
groups: PropTypes.object.isRequired,
user: PropTypes.object,
invitations: PropTypes.object.isRequired,
members: PropTypes.object.isRequired,
params: PropTypes.object.isRequired,
}

render() {
const { user, invitations, groups, members, params: { id }} = this.props;
const { user, groups, members, params: { id }} = this.props;
const group = groups.byId[id];

const membersOfGroup = members.byGroupID[group.id] || [];
Expand All @@ -74,7 +73,6 @@ export default class GroupBase extends Component {
group: group,
currentUser: currentUser,
members: membersOfGroup,
invitations: invitations,
}
)}
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/containers/Group/Members/Invitations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { isRole } from 'helpers/entities/member';

const mapStateToProps = (state) => ({
bulkErrors: state.bulkInvitationsReducer.bulkErrors,
invitations: state.invitationsReducer.invitations,
invitationStatusByID: state.invitationsReducer.invitationStatusByID,
});

const mapDispatchToProps = { initialize, send, sendBulk };

@connect(mapStateToProps, mapDispatchToProps)
Expand Down Expand Up @@ -61,7 +61,7 @@ export default class GroupMembersInvitations extends Component {
invitationStatusByID,
group,
} = this.props;
const invitationsByGroup = invitations.byGroupID[group.id];
const invitationsByGroup = invitations.byGroupID[group.id] || [];
const isAdmin = isRole(currentUser, 'admin');

const invitationsList = invitationsByGroup.map((invitation) => {
Expand Down
21 changes: 16 additions & 5 deletions src/containers/Group/Members/index.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
import React, {Component, PropTypes} from 'react';
import DocumentMeta from 'react-document-meta';
import Helmet from 'react-helmet';
import { asyncConnect } from 'redux-async-connect';

import { load as loadInvitations } from 'redux/modules/invitations/list';
import Invitations from './Invitations';
import List from './List';

@asyncConnect([{
deferred: true,
promise: (options) => {
const {
store: { dispatch },
params: { id },
} = options;

return dispatch(loadInvitations(id));
},
}])
export default class GroupMembers extends Component {
static propTypes = {
group: PropTypes.object,
currentUser: PropTypes.object,
members: PropTypes.array,
invitations: PropTypes.object,
}

render() {

const { currentUser, group, members, invitations } = this.props;
const { currentUser, group, members } = this.props;

return (
<div>
<DocumentMeta title={`Miembros de ${group.name}`}/>
<Helmet title={`Miembros de ${group.name}`}/>

<h2>Miembros</h2>

Expand All @@ -27,7 +39,6 @@ export default class GroupMembers extends Component {
<div className="col-xs-12 col-sm-6 col-sm-push-6 col-md-4 col-md-push-8">
<Invitations
group={group}
invitations={invitations}
currentUser={currentUser}
/>
</div>
Expand Down
Loading