Skip to content

Instantly share code, notes, and snippets.

@sethlivingston
Last active January 29, 2016 15:38
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save sethlivingston/1b1f8e962bb0ecd73925 to your computer and use it in GitHub Desktop.
Samples from an actual React/Redux application
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;
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);
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
});
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;
}
}
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: []
};
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