Last active
January 29, 2016 15:38
Star
You must be signed in to star a gist
Samples from an actual React/Redux application
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import classNames from 'classnames'; | |
import React from 'react'; | |
const NavTab = ({ selected, icon, onClick, children }) => { | |
let tabClasses = classNames({ | |
'nav-tab': true, | |
'selected': selected | |
}); | |
let iconClasses = `fa fa-${icon} fa-lg fa-fw`; | |
return ( | |
<div className={tabClasses} onClick={onClick}> | |
<i className={iconClasses}/> {children} | |
</div> | |
); | |
}; | |
export default NavTab; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { PropTypes } from 'react'; | |
import { connect } from 'react-redux'; | |
import CommandBar from '../components/command-bar'; | |
import * as actions from '../state/actions'; | |
import DesignerDesignPanel from '../containers/designer-design-panel'; | |
import DesignerPositionPanel from '../containers/designer-position-panel'; | |
import Empty from '../components/empty'; | |
import NavTab from '../components/nav-tab'; | |
import NavTabBar from '../components/nav-tab-bar'; | |
import Page from './page'; | |
const PopupDesignerPage = React.createClass({ | |
componentDidMount() { | |
const { dispatch, createPopup, getPopup } = this.props; | |
const id = this.props.params.id; | |
if (id) { | |
dispatch(getPopup(id)) | |
} else { | |
dispatch(createPopup()); | |
} | |
}, | |
render() { | |
const { popup, selectedTab } = this.props; | |
let currentPanel = <Empty/>; | |
switch (selectedTab) { | |
case 'position': | |
const position = popup.fields.document.display.position; | |
const animation = popup.fields.document.display.animation; | |
currentPanel = <DesignerPositionPanel position={position} animation={animation}/>; | |
break; | |
case 'design': | |
currentPanel = <DesignerDesignPanel/>; | |
break; | |
} | |
return( | |
<Page title="Popup Designer" icon="edit"> | |
<CommandBar> | |
<button><i className="fa fa-download fa-fw"/> Save</button> | |
<button><i className="fa fa-close fa-fw"/> Close</button> | |
</CommandBar> | |
<NavTabBar onTabSelected={this.tabSelected}> | |
<NavTab key="position" icon="arrows">Position</NavTab> | |
<NavTab key="design" icon="pencil">Design</NavTab> | |
<NavTab key="integrations" icon="exchange">Integrations</NavTab> | |
<NavTab key="options" icon="check-square-o">Options</NavTab> | |
<NavTab key="test" icon="flask">Test</NavTab> | |
<NavTab key="publish" icon="cloud-upload">Publish</NavTab> | |
</NavTabBar> | |
{currentPanel} | |
</Page> | |
) | |
}, | |
tabSelected: function (key) { | |
const { dispatch, setDesignerTab } = this.props; | |
dispatch(setDesignerTab(key)); | |
} | |
}); | |
PopupDesignerPage.propTypes = { | |
// state | |
popup: PropTypes.object.isRequired, | |
selectedTab: PropTypes.string.isRequired, | |
// actions | |
dispatch: PropTypes.func.isRequired, | |
createPopup: PropTypes.func.isRequired, | |
getPopup: PropTypes.func.isRequired, | |
setDesignerTab: PropTypes.func.isRequired | |
}; | |
const mapStateToProps = (state) => ({ | |
popup: state.popup, | |
selectedTab: state.ui.popups.designer.selectedTab | |
}); | |
const mapDispatchToProps = (dispatch) => ({ | |
dispatch, | |
createPopup: actions.createPopup, | |
getPopup: actions.getPopup, | |
setDesignerTab: actions.setDesignerTab | |
}); | |
export default connect(mapStateToProps, mapDispatchToProps)(PopupDesignerPage); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as accounts from '../api/accounts'; | |
import * as popups from '../api/popups'; | |
export const SET_ACCOUNT = 'SET_ACCOUNT'; | |
export const setAccount = (account) => ({ | |
type: SET_ACCOUNT, | |
payload: account | |
}); | |
export const RESET_APP_MESSAGE = 'RESET_APP_MESSAGE'; | |
export const resetAppMessage = () => ({ | |
type: RESET_APP_MESSAGE, | |
payload: null | |
}); | |
export const GET_POPUPS = 'GET_POPUPS'; | |
export const getPopups = () => ({ | |
type: GET_POPUPS, | |
payload: { | |
promise: popups.getPopups() | |
} | |
}); | |
export const GET_POPUP = 'GET_POPUP'; | |
export const getPopup = (id) => ({ | |
type: GET_POPUP, | |
payload: { | |
promise: popups.getPopup(id) | |
} | |
}); | |
export const CREATE_POPUP = 'CREATE_POPUP'; | |
export const createPopup = () => ({ | |
type: CREATE_POPUP | |
}); | |
export const SAVE_POPUP = 'SAVE_POPUP'; | |
export const savePopup = (popup) => ({ | |
type: SAVE_POPUP, | |
payload: { | |
promise: popups.savePopup(popup) | |
} | |
}); | |
export const SET_DESIGNER_TAB = 'SET_DESIGNER_TAB'; | |
export const setDesignerTab = (key) => ({ | |
type: SET_DESIGNER_TAB, | |
payload: key | |
}); | |
export const SET_POPUP_POSITION = 'SET_POPUP_POSITION'; | |
export const setPopupPosition = (position) => ({ | |
type: SET_POPUP_POSITION, | |
payload: position | |
}); | |
export const SET_POPUP_ANIMATION = 'SET_POPUP_ANIMATION'; | |
export const setPopupAnimation = (animation) => ({ | |
type: SET_POPUP_ANIMATION, | |
payload: animation | |
}); | |
export const SET_POPUP_NAME = 'SET_POPUP_NAME'; | |
export const setPopupName = (name) => ({ | |
type: SET_POPUP_NAME, | |
payload: name | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import update from 'react/lib/update'; | |
import * as actions from './actions'; | |
import { standardError } from '../extra/errors'; | |
import * as states from './states'; | |
export function popup(state = states.initialPopupState, action) { | |
switch (action.type) { | |
case `${actions.GET_POPUP}_FULFILLED`: | |
return action.payload; | |
case actions.CREATE_POPUP: | |
return states.initialPopupState; | |
case `${actions.SAVE_POPUP}_FULFILLED`: | |
return action.payload; | |
case actions.SET_POPUP_ANIMATION: | |
return update(state, { | |
fields: {document: {display: {animation: {$set: action.payload}}}} | |
}); | |
case actions.SET_POPUP_POSITION: | |
return update(state, { | |
fields: {document: {display: {position: {$set: action.payload}}}} | |
}); | |
case actions.SET_POPUP_NAME: | |
return update(state, { | |
fields: {name: {$set: action.payload}} | |
}); | |
default: | |
return state; | |
} | |
} | |
export function popups(state = [], action) { | |
switch (action.type) { | |
case `${actions.GET_POPUPS}_FULFILLED`: | |
return action.payload; | |
default: | |
return state; | |
} | |
} | |
export function account(state = states.initialAccountState, action) { | |
switch (action.type) { | |
case actions.SET_ACCOUNT: | |
return action.payload; | |
default: | |
return state; | |
} | |
} | |
export function ui(state = states.initialUIState, action) { | |
switch (action.type) { | |
case actions.RESET_APP_MESSAGE: | |
return Object.assign({}, state, { | |
appMessage: null | |
}); | |
case `${actions.GET_POPUPS}_REJECTED`: | |
return Object.assign({}, state, { | |
appMessage: standardError('loading popups', action.payload.message) | |
}); | |
case `${actions.SAVE_POPUP}_REJECTED`: | |
return Object.assign({}, state, { | |
appMessage: standardError('saving the popup', action.payload.message) | |
}); | |
case actions.SET_DESIGNER_TAB: | |
return Object.assign({}, state, { | |
popups: Object.assign({}, state.popups, { | |
designer: Object.assign({}, state.popups.designer, { | |
selectedTab: action.payload | |
}) | |
}) | |
}); | |
default: | |
return state; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Animation, Position } from '../common/constants'; | |
export const initialUIState = { | |
appMessage: null, | |
popups: { | |
designer: { | |
selectedTab: 'position' | |
} | |
} | |
}; | |
export const initialAccountState = { | |
pk: 0, | |
model: 'server.customer', | |
fields: { | |
email: '', | |
token: '', | |
first_name: '', | |
last_name: '', | |
last_seen_on: '', | |
created_on: '' | |
} | |
}; | |
export const initialPopupState = { | |
pk: 0, | |
model: 'server.popup', | |
fields: { | |
name: 'Unnamed Popup', | |
document: { | |
display: { | |
position: Position.CENTER, | |
animation: Animation.FADE_IN | |
} | |
} | |
} | |
}; | |
export const initialState = { | |
ui: initialUIState, | |
account: initialAccountState, | |
popup: initialPopupState, | |
popups: [] | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var _ = require('lodash'); | |
var path = require('path'); | |
var webpack = require('webpack'); | |
var ExtractTextWebpackPlugin = require('extract-text-webpack-plugin') | |
var HtmlWebpackPlugin = require('html-webpack-plugin'); | |
var PROD = (process.env.NODE_ENV == 'production'); | |
// Load package.json | |
var dependencies = require('./package.json').dependencies; | |
// Lodash reduction | |
delete dependencies['lodash']; | |
// Specify plugins appropriately for PROD or DEV | |
plugins = [ | |
new HtmlWebpackPlugin({ | |
template: 'src/index.html', | |
prod: PROD | |
}), | |
new webpack.optimize.CommonsChunkPlugin( | |
'vendors', | |
PROD ? 'vendors.min.js' : 'vendors.js' | |
), | |
new ExtractTextWebpackPlugin('styles.min.css'), | |
new webpack.ProvidePlugin({ | |
'Promise': 'exports?global.Promise!es6-promise', | |
'fetch': 'exports?self.fetch!whatwg-fetch' | |
}), | |
]; | |
if (PROD) { | |
plugins.push(new webpack.optimize.UglifyJsPlugin({ | |
sourceMap: false | |
})); | |
} | |
// Webpack config | |
module.exports = { | |
// Entry points and output | |
entry: { | |
app: path.resolve('./src/index'), | |
vendors: Object.keys(dependencies) | |
}, | |
output: { | |
path: path.join(__dirname, 'build'), | |
filename: PROD ? 'app.min.js' : 'app.js' | |
}, | |
// Loaders and plugins | |
module: { | |
loaders: [ | |
{ | |
test: /\.jsx$/, | |
loader: 'babel?presets[]=react,presets[]=es2015', | |
include: [path.resolve(__dirname, 'src')] | |
}, | |
{ | |
test: /\.css$/, | |
loader: ExtractTextWebpackPlugin.extract('style-loader', 'css-loader?minimize') | |
}, | |
{ | |
test: /\.styl$/, | |
loader: ExtractTextWebpackPlugin.extract('style-loader', 'css-loader?minimize!stylus-loader'), | |
include: [path.resolve(__dirname, 'src')] | |
} | |
] | |
}, | |
plugins: plugins, | |
// Misc | |
resolve: { | |
extensions: ['', '.js', '.jsx', '.css', '.styl'] | |
}, | |
node: { | |
fs: 'empty' | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment