Merge branch 'spike/fuzzy-search'
* spike/fuzzy-search: changing setTimeout length adding in async select type adding in more readme details Implimenting React Search removing .idea dir generated by webstorm moving react selectize to single folder and updating readme with notes implimenting react-selectize with ajax to API endpoint adding notes to spike readme implimenting first fuzzy search spike
This commit is contained in:
commit
319552fc20
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"sourceMaps": "both",
|
||||||
|
"presets": [
|
||||||
|
"react",
|
||||||
|
"es2015"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"react-hot-loader/babel",
|
||||||
|
"add-module-exports",
|
||||||
|
"syntax-async-functions",
|
||||||
|
["transform-object-rest-spread", {
|
||||||
|
"useBuiltIns": true
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
{
|
||||||
|
"name": "react-infinite-spike",
|
||||||
|
"private": true,
|
||||||
|
"license": "private",
|
||||||
|
"scripts": {
|
||||||
|
"start": "webpack-dev-server --config webpack/index.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"build-array": "^1.0.0",
|
||||||
|
"delay": "^1.3.1",
|
||||||
|
"lodash.debounce": "^4.0.8",
|
||||||
|
"react": "^15.4.0",
|
||||||
|
"react-dom": "^15.4.0",
|
||||||
|
"react-fuzzy-filter": "^2.3.0",
|
||||||
|
"react-hot-loader": "^3.0.0-beta.6",
|
||||||
|
"react-infinite": "^0.10.0",
|
||||||
|
"react-redux": "^4.4.6",
|
||||||
|
"redux": "^3.6.0",
|
||||||
|
"redux-logger": "^2.7.4",
|
||||||
|
"redux-promise-middleware": "^4.1.0",
|
||||||
|
"redux-thunk": "^2.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-core": "^6.18.2",
|
||||||
|
"babel-eslint": "^7.1.1",
|
||||||
|
"babel-loader": "^6.2.7",
|
||||||
|
"babel-plugin-add-module-exports": "^0.2.1",
|
||||||
|
"babel-plugin-syntax-async-functions": "^6.13.0",
|
||||||
|
"babel-plugin-transform-object-rest-spread": "^6.19.0",
|
||||||
|
"babel-preset-es2015": "^6.18.0",
|
||||||
|
"babel-preset-react": "^6.16.0",
|
||||||
|
"css-loader": "^0.25.0",
|
||||||
|
"extract-text-webpack-plugin": "^2.0.0-beta.4",
|
||||||
|
"faker": "^3.1.0",
|
||||||
|
"postcss-loader": "^1.0.0",
|
||||||
|
"postcss-modules-values": "^1.2.2",
|
||||||
|
"postcss-nested": "^1.0.0",
|
||||||
|
"style-loader": "^0.13.1",
|
||||||
|
"webpack": "^2.1.0-beta.27",
|
||||||
|
"webpack-dev-server": "^1.16.2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
# react-fuzzy-filter
|
||||||
|
|
||||||
|
- https://github.com/jdlehman/react-fuzzy-filter
|
||||||
|
|
||||||
|
- Does not use API endpoint, instead an array of objects needs to be created locally
|
|
@ -0,0 +1,91 @@
|
||||||
|
const buildArray = require('build-array');
|
||||||
|
const delay = require('delay');
|
||||||
|
const faker = require('faker');
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
'FETCH_FULFILLED': (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
fetching: false,
|
||||||
|
items: (state.items || []).concat(action.payload)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
'FETCH_PENDING': (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
fetching: true
|
||||||
|
};
|
||||||
|
},
|
||||||
|
'FILTER_PENDING': (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
fetching: true
|
||||||
|
};
|
||||||
|
},
|
||||||
|
'FILTER_FULFILLED': (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
fetching: false,
|
||||||
|
filtered: action.payload.length !== state.items.length
|
||||||
|
? action.payload
|
||||||
|
: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetch = () => (dispatch, getState) => {
|
||||||
|
const {
|
||||||
|
filtered
|
||||||
|
} = getState();
|
||||||
|
|
||||||
|
if (filtered) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dispatch({
|
||||||
|
type: 'FETCH',
|
||||||
|
payload: delay(500).then(() => {
|
||||||
|
const {
|
||||||
|
items = []
|
||||||
|
} = getState();
|
||||||
|
|
||||||
|
return buildArray(100000).map((v, i) => {
|
||||||
|
const id = items.length + i;
|
||||||
|
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
title: `test ${id}`,
|
||||||
|
description: faker.lorem.sentence(),
|
||||||
|
image: faker.image.imageUrl(),
|
||||||
|
date: faker.date.recent()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const filter = (payload) => (dispatch, getState) => {
|
||||||
|
const regexp = new RegExp(payload);
|
||||||
|
|
||||||
|
return dispatch({
|
||||||
|
type: 'FILTER',
|
||||||
|
payload: delay(500).then(() => {
|
||||||
|
const {
|
||||||
|
items = []
|
||||||
|
} = getState();
|
||||||
|
|
||||||
|
return items.filter((item) => {
|
||||||
|
return regexp.test(item.title);
|
||||||
|
}).sort((a, b) => a.id - b.id);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = (state, action) => {
|
||||||
|
return actions[action.type]
|
||||||
|
? actions[action.type](state, action)
|
||||||
|
: state;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.fetch = fetch;
|
||||||
|
module.exports.filter = filter;
|
|
@ -0,0 +1,18 @@
|
||||||
|
const Store = require('./store');
|
||||||
|
const ReactDOM = require('react-dom');
|
||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
const render = () => {
|
||||||
|
const Root = require('./root');
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<Root store={Store()} />,
|
||||||
|
document.getElementById('root')
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render();
|
||||||
|
|
||||||
|
if (module.hot) {
|
||||||
|
module.hot.accept('./root', render);
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
const ReactRedux = require('react-redux');
|
||||||
|
const ReactHotLoader = require('react-hot-loader');
|
||||||
|
const React = require('react');
|
||||||
|
const Search = require('./search');
|
||||||
|
|
||||||
|
const {
|
||||||
|
AppContainer
|
||||||
|
} = ReactHotLoader;
|
||||||
|
|
||||||
|
const {
|
||||||
|
Provider
|
||||||
|
} = ReactRedux;
|
||||||
|
|
||||||
|
module.exports = ({
|
||||||
|
store
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<AppContainer>
|
||||||
|
<Provider store={store}>
|
||||||
|
<Search />
|
||||||
|
</Provider>
|
||||||
|
</AppContainer>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,62 @@
|
||||||
|
const ReactRedux = require('react-redux');
|
||||||
|
const actions = require('./actions');
|
||||||
|
const React = require('react');
|
||||||
|
const users = require('../../users');
|
||||||
|
|
||||||
|
import fuzzyFilterFactory from 'react-fuzzy-filter';
|
||||||
|
|
||||||
|
// these components share state and can even live in different components
|
||||||
|
const {InputFilter, FilterResults} = fuzzyFilterFactory();
|
||||||
|
|
||||||
|
const {
|
||||||
|
connect
|
||||||
|
} = ReactRedux;
|
||||||
|
|
||||||
|
const {
|
||||||
|
fetch,
|
||||||
|
filter
|
||||||
|
} = actions;
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch, ownProps) => {
|
||||||
|
return {
|
||||||
|
fetch: () => {
|
||||||
|
return dispatch(fetch());
|
||||||
|
},
|
||||||
|
filter: (payload) => {
|
||||||
|
return dispatch(filter(payload));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Search = React.createClass({
|
||||||
|
|
||||||
|
renderItem: function(item, index) {
|
||||||
|
return(<div key={index}>{item.name}</div>);
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
const fuseConfig = {
|
||||||
|
keys: ['meta', 'tag']
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<InputFilter />
|
||||||
|
<div>Any amount of content between</div>
|
||||||
|
<FilterResults
|
||||||
|
items={users}
|
||||||
|
renderItem={this.renderItem}
|
||||||
|
fuseConfig={fuseConfig}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps,
|
||||||
|
)(Search);
|
|
@ -0,0 +1,19 @@
|
||||||
|
const createLogger = require('redux-logger');
|
||||||
|
const promiseMiddleware = require('redux-promise-middleware').default;
|
||||||
|
const thunk = require('redux-thunk').default;
|
||||||
|
const redux = require('redux');
|
||||||
|
const reducer = require('./actions');
|
||||||
|
|
||||||
|
const {
|
||||||
|
createStore,
|
||||||
|
compose,
|
||||||
|
applyMiddleware
|
||||||
|
} = redux;
|
||||||
|
|
||||||
|
module.exports = (state = Object.freeze({})) => {
|
||||||
|
return createStore(reducer, state, applyMiddleware(
|
||||||
|
createLogger(),
|
||||||
|
promiseMiddleware(),
|
||||||
|
thunk
|
||||||
|
));
|
||||||
|
};
|
|
@ -0,0 +1,7 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
||||||
|
!.gitkeep
|
||||||
|
!index.html
|
||||||
|
|
||||||
|
js/*
|
||||||
|
!js/.gitkeep
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang='en-US'>
|
||||||
|
<head>
|
||||||
|
<title>Infinite List</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id='root'></div>
|
||||||
|
<script src='main.js'></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,56 @@
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const path = require('path');
|
||||||
|
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
|
|
||||||
|
const plugins = {
|
||||||
|
'no-errors-plugin': new webpack.NoErrorsPlugin(),
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.config = {
|
||||||
|
context: path.join(__dirname, '../'),
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, '../static'),
|
||||||
|
publicPath: '/',
|
||||||
|
filename: '[name].js'
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.NoErrorsPlugin(),
|
||||||
|
new ExtractTextPlugin({
|
||||||
|
filename: 'css/[name].css',
|
||||||
|
allChunks: true
|
||||||
|
}),
|
||||||
|
new webpack.LoaderOptionsPlugin({
|
||||||
|
options: {
|
||||||
|
postcss: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
module: {
|
||||||
|
loaders: [{
|
||||||
|
test: /js?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
include: [
|
||||||
|
path.join(__dirname, '../src')
|
||||||
|
],
|
||||||
|
loader: 'babel-loader'
|
||||||
|
}, {
|
||||||
|
test: /\.css?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
include: [
|
||||||
|
path.join(__dirname, '../src'),
|
||||||
|
path.join(__dirname, '../docs')
|
||||||
|
],
|
||||||
|
loader: ExtractTextPlugin.extract({
|
||||||
|
fallbackLoader: 'style-loader',
|
||||||
|
loader: [
|
||||||
|
'css-loader?',
|
||||||
|
'modules&importLoaders=1&',
|
||||||
|
'localIdentName=[name]__[local]___[hash:base64:5]!',
|
||||||
|
'postcss-loader'
|
||||||
|
].join('')
|
||||||
|
})
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.plugins = plugins;
|
|
@ -0,0 +1,29 @@
|
||||||
|
const base = require('./base.js');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const devServer = {
|
||||||
|
contentBase: [
|
||||||
|
path.join(__dirname, '../static/')
|
||||||
|
],
|
||||||
|
hot: true,
|
||||||
|
compress: true,
|
||||||
|
lazy: false,
|
||||||
|
historyApiFallback: {
|
||||||
|
index: './index.html'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Object.assign(base.config, {
|
||||||
|
entry: [
|
||||||
|
'react-hot-loader/patch',
|
||||||
|
'webpack-dev-server/client?http://localhost:8080',
|
||||||
|
'webpack/hot/only-dev-server',
|
||||||
|
'./src/index.js'
|
||||||
|
],
|
||||||
|
plugins: base.config.plugins.concat([
|
||||||
|
new webpack.HotModuleReplacementPlugin()
|
||||||
|
]),
|
||||||
|
devtool: 'source-map',
|
||||||
|
devServer
|
||||||
|
});
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"sourceMaps": "both",
|
||||||
|
"presets": [
|
||||||
|
"react",
|
||||||
|
"es2015"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"react-hot-loader/babel",
|
||||||
|
"add-module-exports",
|
||||||
|
"syntax-async-functions",
|
||||||
|
["transform-object-rest-spread", {
|
||||||
|
"useBuiltIns": true
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"name": "react-infinite-spike",
|
||||||
|
"private": true,
|
||||||
|
"license": "private",
|
||||||
|
"scripts": {
|
||||||
|
"start": "webpack-dev-server --config webpack/index.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.15.3",
|
||||||
|
"build-array": "^1.0.0",
|
||||||
|
"delay": "^1.3.1",
|
||||||
|
"lodash.debounce": "^4.0.8",
|
||||||
|
"react": "^15.4.0",
|
||||||
|
"react-dom": "^15.4.0",
|
||||||
|
"react-hot-loader": "^3.0.0-beta.6",
|
||||||
|
"react-infinite": "^0.10.0",
|
||||||
|
"react-redux": "^4.4.6",
|
||||||
|
"react-select": "^1.0.0-rc.2",
|
||||||
|
"redux": "^3.6.0",
|
||||||
|
"redux-logger": "^2.7.4",
|
||||||
|
"redux-promise-middleware": "^4.1.0",
|
||||||
|
"redux-thunk": "^2.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-core": "^6.18.2",
|
||||||
|
"babel-eslint": "^7.1.1",
|
||||||
|
"babel-loader": "^6.2.7",
|
||||||
|
"babel-plugin-add-module-exports": "^0.2.1",
|
||||||
|
"babel-plugin-syntax-async-functions": "^6.13.0",
|
||||||
|
"babel-plugin-transform-object-rest-spread": "^6.19.0",
|
||||||
|
"babel-preset-es2015": "^6.18.0",
|
||||||
|
"babel-preset-react": "^6.16.0",
|
||||||
|
"extract-text-webpack-plugin": "^2.0.0-beta.4",
|
||||||
|
"faker": "^3.1.0",
|
||||||
|
"style-loader": "^0.13.1",
|
||||||
|
"webpack": "^2.1.0-beta.27",
|
||||||
|
"webpack-dev-server": "^1.16.2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
# react-select
|
||||||
|
|
||||||
|
- http://jedwatson.github.io/react-select/
|
||||||
|
|
||||||
|
- Has a seperate stylesheet that needs to be included
|
||||||
|
|
||||||
|
- Allows for async option
|
|
@ -0,0 +1,17 @@
|
||||||
|
const ReactDOM = require('react-dom');
|
||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
const render = () => {
|
||||||
|
const Root = require('./root');
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<Root />,
|
||||||
|
document.getElementById('root')
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render();
|
||||||
|
|
||||||
|
if (module.hot) {
|
||||||
|
module.hot.accept('./root', render);
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
const ReactRedux = require('react-redux');
|
||||||
|
const ReactHotLoader = require('react-hot-loader');
|
||||||
|
const React = require('react');
|
||||||
|
const Search = require('./search');
|
||||||
|
const SearchAsync = require('./search-async')
|
||||||
|
|
||||||
|
const {
|
||||||
|
AppContainer
|
||||||
|
} = ReactHotLoader;
|
||||||
|
|
||||||
|
const {
|
||||||
|
Provider
|
||||||
|
} = ReactRedux;
|
||||||
|
|
||||||
|
module.exports = ({
|
||||||
|
store
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<AppContainer>
|
||||||
|
<div>
|
||||||
|
<Search multi />
|
||||||
|
<Search />
|
||||||
|
<SearchAsync />
|
||||||
|
</div>
|
||||||
|
</AppContainer>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,56 @@
|
||||||
|
const React = require('react');
|
||||||
|
const Select = require('react-select');
|
||||||
|
const SelectAsync = Select.Async
|
||||||
|
|
||||||
|
|
||||||
|
const SearchAsync = React.createClass({
|
||||||
|
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
selectValue: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateValue: function(newValue) {
|
||||||
|
console.log('State changed to ' + newValue);
|
||||||
|
this.setState({
|
||||||
|
selectValue: newValue
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
options: function(input, callback) {
|
||||||
|
setTimeout(function() {
|
||||||
|
callback(null, {
|
||||||
|
options: [
|
||||||
|
{ value: 'one', label: 'One' },
|
||||||
|
{ value: 'two', label: 'Two' },
|
||||||
|
{ value: 'three', label: 'Three' },
|
||||||
|
{ value: 'four', label: 'Four' },
|
||||||
|
{ value: 'five', label: 'Five' },
|
||||||
|
{ value: 'six', label: 'Six' },
|
||||||
|
],
|
||||||
|
// CAREFUL! Only set this to true when there are no more options,
|
||||||
|
// or more specific queries will not be sent to the server.
|
||||||
|
complete: true
|
||||||
|
}, 10000);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function () {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1> Async Search </h1>
|
||||||
|
<SelectAsync
|
||||||
|
ref="stateSelectAsync"
|
||||||
|
loadOptions={this.options}
|
||||||
|
value={this.state.selectValue}
|
||||||
|
onChange={this.updateValue}
|
||||||
|
multi={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = SearchAsync
|
|
@ -0,0 +1,49 @@
|
||||||
|
const React = require('react');
|
||||||
|
const Select = require('react-select');
|
||||||
|
|
||||||
|
|
||||||
|
const Search = React.createClass({
|
||||||
|
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
selectValue: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateValue: function(newValue) {
|
||||||
|
console.log('State changed to ' + newValue);
|
||||||
|
this.setState({
|
||||||
|
selectValue: newValue
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function () {
|
||||||
|
|
||||||
|
var options = [
|
||||||
|
{ value: 'one', label: 'One' },
|
||||||
|
{ value: 'two', label: 'Two' },
|
||||||
|
{ value: 'three', label: 'Three' },
|
||||||
|
{ value: 'four', label: 'Four' },
|
||||||
|
{ value: 'five', label: 'Five' },
|
||||||
|
{ value: 'six', label: 'Six' },
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1> {this.props.multi ? 'Multi' : 'Single'} Search </h1>
|
||||||
|
<Select
|
||||||
|
ref="stateSelect"
|
||||||
|
className="is-open"
|
||||||
|
autofocus
|
||||||
|
options={options}
|
||||||
|
name="selected-state"
|
||||||
|
value={this.state.selectValue}
|
||||||
|
onChange={this.updateValue}
|
||||||
|
multi={this.props.multi}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = Search
|
|
@ -0,0 +1,7 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
||||||
|
!.gitkeep
|
||||||
|
!index.html
|
||||||
|
|
||||||
|
js/*
|
||||||
|
!js/.gitkeep
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang='en-US'>
|
||||||
|
<head>
|
||||||
|
<title>React Select</title>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id='root'></div>
|
||||||
|
<script src='main.js'></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/react-select/dist/react-select.css">
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,56 @@
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const path = require('path');
|
||||||
|
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
|
|
||||||
|
const plugins = {
|
||||||
|
'no-errors-plugin': new webpack.NoErrorsPlugin(),
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.config = {
|
||||||
|
context: path.join(__dirname, '../'),
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, '../static'),
|
||||||
|
publicPath: '/',
|
||||||
|
filename: '[name].js'
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.NoErrorsPlugin(),
|
||||||
|
new ExtractTextPlugin({
|
||||||
|
filename: 'css/[name].css',
|
||||||
|
allChunks: true
|
||||||
|
}),
|
||||||
|
new webpack.LoaderOptionsPlugin({
|
||||||
|
options: {
|
||||||
|
postcss: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
module: {
|
||||||
|
loaders: [{
|
||||||
|
test: /js?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
include: [
|
||||||
|
path.join(__dirname, '../src')
|
||||||
|
],
|
||||||
|
loader: 'babel-loader'
|
||||||
|
}, {
|
||||||
|
test: /\.css?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
include: [
|
||||||
|
path.join(__dirname, '../src'),
|
||||||
|
path.join(__dirname, '../docs')
|
||||||
|
],
|
||||||
|
loader: ExtractTextPlugin.extract({
|
||||||
|
fallbackLoader: 'style-loader',
|
||||||
|
loader: [
|
||||||
|
'css-loader?',
|
||||||
|
'modules&importLoaders=1&',
|
||||||
|
'localIdentName=[name]__[local]___[hash:base64:5]!',
|
||||||
|
'postcss-loader'
|
||||||
|
].join('')
|
||||||
|
})
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.plugins = plugins;
|
|
@ -0,0 +1,29 @@
|
||||||
|
const base = require('./base.js');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const devServer = {
|
||||||
|
contentBase: [
|
||||||
|
path.join(__dirname, '../static/')
|
||||||
|
],
|
||||||
|
hot: true,
|
||||||
|
compress: true,
|
||||||
|
lazy: false,
|
||||||
|
historyApiFallback: {
|
||||||
|
index: './index.html'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Object.assign(base.config, {
|
||||||
|
entry: [
|
||||||
|
'react-hot-loader/patch',
|
||||||
|
'webpack-dev-server/client?http://localhost:8080',
|
||||||
|
'webpack/hot/only-dev-server',
|
||||||
|
'./src/index.js'
|
||||||
|
],
|
||||||
|
plugins: base.config.plugins.concat([
|
||||||
|
new webpack.HotModuleReplacementPlugin()
|
||||||
|
]),
|
||||||
|
devtool: 'source-map',
|
||||||
|
devServer
|
||||||
|
});
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"sourceMaps": "both",
|
||||||
|
"presets": [
|
||||||
|
"react",
|
||||||
|
"es2015"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"react-hot-loader/babel",
|
||||||
|
"add-module-exports",
|
||||||
|
"syntax-async-functions",
|
||||||
|
["transform-object-rest-spread", {
|
||||||
|
"useBuiltIns": true
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"name": "react-infinite-spike",
|
||||||
|
"private": true,
|
||||||
|
"license": "private",
|
||||||
|
"scripts": {
|
||||||
|
"start": "webpack-dev-server --config webpack/index.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.15.3",
|
||||||
|
"build-array": "^1.0.0",
|
||||||
|
"delay": "^1.3.1",
|
||||||
|
"lodash.debounce": "^4.0.8",
|
||||||
|
"react": "^15.4.0",
|
||||||
|
"react-addons-css-transition-group": "^15.4.1",
|
||||||
|
"react-addons-shallow-compare": "^15.4.1",
|
||||||
|
"react-dom": "^15.4.0",
|
||||||
|
"react-hot-loader": "^3.0.0-beta.6",
|
||||||
|
"react-infinite": "^0.10.0",
|
||||||
|
"react-redux": "^4.4.6",
|
||||||
|
"react-selectize": "^2.1.0",
|
||||||
|
"redux": "^3.6.0",
|
||||||
|
"redux-logger": "^2.7.4",
|
||||||
|
"redux-promise-middleware": "^4.1.0",
|
||||||
|
"redux-thunk": "^2.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-core": "^6.18.2",
|
||||||
|
"babel-eslint": "^7.1.1",
|
||||||
|
"babel-loader": "^6.2.7",
|
||||||
|
"babel-plugin-add-module-exports": "^0.2.1",
|
||||||
|
"babel-plugin-syntax-async-functions": "^6.13.0",
|
||||||
|
"babel-plugin-transform-object-rest-spread": "^6.19.0",
|
||||||
|
"babel-preset-es2015": "^6.18.0",
|
||||||
|
"babel-preset-react": "^6.16.0",
|
||||||
|
"extract-text-webpack-plugin": "^2.0.0-beta.4",
|
||||||
|
"faker": "^3.1.0",
|
||||||
|
"style-loader": "^0.13.1",
|
||||||
|
"webpack": "^2.1.0-beta.27",
|
||||||
|
"webpack-dev-server": "^1.16.2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
# react-fuzzy-filter
|
||||||
|
|
||||||
|
- https://github.com/jdlehman/react-fuzzy-filter
|
||||||
|
|
||||||
|
- Does not use API endpoint, instead an array of objects needs to be created locally
|
|
@ -0,0 +1,44 @@
|
||||||
|
const buildArray = require('build-array');
|
||||||
|
const delay = require('delay');
|
||||||
|
const faker = require('faker');
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
'FETCH': (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
items: (state.items || []).concat(action.payload)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetch = () => (dispatch, getState) => {
|
||||||
|
|
||||||
|
return dispatch({
|
||||||
|
type: 'FETCH',
|
||||||
|
payload: () => {
|
||||||
|
// debugger
|
||||||
|
const {
|
||||||
|
items = []
|
||||||
|
} = getState();
|
||||||
|
|
||||||
|
return buildArray(200).map((v, i) => {
|
||||||
|
const id = items.length + i;
|
||||||
|
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
name: faker.name.firstName(),
|
||||||
|
meta: `${faker.name.firstName()}|${faker.random.number()}`,
|
||||||
|
key: faker.image.imageUrl()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = (state, action) => {
|
||||||
|
return actions[action.type]
|
||||||
|
? actions[action.type](state, action)
|
||||||
|
: state;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.fetch = fetch;
|
|
@ -0,0 +1,18 @@
|
||||||
|
const Store = require('./store');
|
||||||
|
const ReactDOM = require('react-dom');
|
||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
const render = () => {
|
||||||
|
const Root = require('./root');
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<Root store={Store()} />,
|
||||||
|
document.getElementById('root')
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render();
|
||||||
|
|
||||||
|
if (module.hot) {
|
||||||
|
module.hot.accept('./root', render);
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
const ReactRedux = require('react-redux');
|
||||||
|
const ReactHotLoader = require('react-hot-loader');
|
||||||
|
const React = require('react');
|
||||||
|
const Search = require('./search');
|
||||||
|
|
||||||
|
const {
|
||||||
|
AppContainer
|
||||||
|
} = ReactHotLoader;
|
||||||
|
|
||||||
|
const {
|
||||||
|
Provider
|
||||||
|
} = ReactRedux;
|
||||||
|
|
||||||
|
module.exports = ({
|
||||||
|
store
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<AppContainer>
|
||||||
|
<Provider store={store}>
|
||||||
|
<Search />
|
||||||
|
</Provider>
|
||||||
|
</AppContainer>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
const actions = require('./actions');
|
||||||
|
const React = require('react');
|
||||||
|
const axios = require('axios');
|
||||||
|
const users = require('../../users');
|
||||||
|
|
||||||
|
const ReactSelectize = require("react-selectize");
|
||||||
|
const SimpleSelect = ReactSelectize.SimpleSelect;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const Search = () => {
|
||||||
|
|
||||||
|
let _options = ["apple", "mango", "grapes", "melon", "strawberry"];
|
||||||
|
_options = _options.map(function(fruit){
|
||||||
|
return {label: fruit, value: fruit}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SimpleSelect
|
||||||
|
options={_options}
|
||||||
|
placeholder="Select a fruit"
|
||||||
|
theme="material"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Search;
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
const createLogger = require('redux-logger');
|
||||||
|
const promiseMiddleware = require('redux-promise-middleware').default;
|
||||||
|
const thunk = require('redux-thunk').default;
|
||||||
|
const redux = require('redux');
|
||||||
|
const reducer = require('./actions');
|
||||||
|
|
||||||
|
const {
|
||||||
|
createStore,
|
||||||
|
compose,
|
||||||
|
applyMiddleware
|
||||||
|
} = redux;
|
||||||
|
|
||||||
|
module.exports = (state = Object.freeze({})) => {
|
||||||
|
return createStore(reducer, state, applyMiddleware(
|
||||||
|
createLogger(),
|
||||||
|
promiseMiddleware(),
|
||||||
|
thunk
|
||||||
|
));
|
||||||
|
};
|
|
@ -0,0 +1,7 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
||||||
|
!.gitkeep
|
||||||
|
!index.html
|
||||||
|
|
||||||
|
js/*
|
||||||
|
!js/.gitkeep
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang='en-US'>
|
||||||
|
<head>
|
||||||
|
<title>Infinite List</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id='root'></div>
|
||||||
|
<script src='main.js'></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,56 @@
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const path = require('path');
|
||||||
|
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
|
|
||||||
|
const plugins = {
|
||||||
|
'no-errors-plugin': new webpack.NoErrorsPlugin(),
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.config = {
|
||||||
|
context: path.join(__dirname, '../'),
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, '../static'),
|
||||||
|
publicPath: '/',
|
||||||
|
filename: '[name].js'
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.NoErrorsPlugin(),
|
||||||
|
new ExtractTextPlugin({
|
||||||
|
filename: 'css/[name].css',
|
||||||
|
allChunks: true
|
||||||
|
}),
|
||||||
|
new webpack.LoaderOptionsPlugin({
|
||||||
|
options: {
|
||||||
|
postcss: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
module: {
|
||||||
|
loaders: [{
|
||||||
|
test: /js?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
include: [
|
||||||
|
path.join(__dirname, '../src')
|
||||||
|
],
|
||||||
|
loader: 'babel-loader'
|
||||||
|
}, {
|
||||||
|
test: /\.css?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
include: [
|
||||||
|
path.join(__dirname, '../src'),
|
||||||
|
path.join(__dirname, '../docs')
|
||||||
|
],
|
||||||
|
loader: ExtractTextPlugin.extract({
|
||||||
|
fallbackLoader: 'style-loader',
|
||||||
|
loader: [
|
||||||
|
'css-loader?',
|
||||||
|
'modules&importLoaders=1&',
|
||||||
|
'localIdentName=[name]__[local]___[hash:base64:5]!',
|
||||||
|
'postcss-loader'
|
||||||
|
].join('')
|
||||||
|
})
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.plugins = plugins;
|
|
@ -0,0 +1,29 @@
|
||||||
|
const base = require('./base.js');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const devServer = {
|
||||||
|
contentBase: [
|
||||||
|
path.join(__dirname, '../static/')
|
||||||
|
],
|
||||||
|
hot: true,
|
||||||
|
compress: true,
|
||||||
|
lazy: false,
|
||||||
|
historyApiFallback: {
|
||||||
|
index: './index.html'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Object.assign(base.config, {
|
||||||
|
entry: [
|
||||||
|
'react-hot-loader/patch',
|
||||||
|
'webpack-dev-server/client?http://localhost:8080',
|
||||||
|
'webpack/hot/only-dev-server',
|
||||||
|
'./src/index.js'
|
||||||
|
],
|
||||||
|
plugins: base.config.plugins.concat([
|
||||||
|
new webpack.HotModuleReplacementPlugin()
|
||||||
|
]),
|
||||||
|
devtool: 'source-map',
|
||||||
|
devServer
|
||||||
|
});
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"sourceMaps": "both",
|
||||||
|
"presets": [
|
||||||
|
"react",
|
||||||
|
"es2015"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"react-hot-loader/babel",
|
||||||
|
"add-module-exports",
|
||||||
|
"syntax-async-functions",
|
||||||
|
["transform-object-rest-spread", {
|
||||||
|
"useBuiltIns": true
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"name": "react-infinite-spike",
|
||||||
|
"private": true,
|
||||||
|
"license": "private",
|
||||||
|
"scripts": {
|
||||||
|
"start": "webpack-dev-server --config webpack/index.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.15.3",
|
||||||
|
"build-array": "^1.0.0",
|
||||||
|
"delay": "^1.3.1",
|
||||||
|
"lodash.debounce": "^4.0.8",
|
||||||
|
"react": "^15.4.0",
|
||||||
|
"react-addons-css-transition-group": "^15.4.1",
|
||||||
|
"react-addons-shallow-compare": "^15.4.1",
|
||||||
|
"react-dom": "^15.4.0",
|
||||||
|
"react-hot-loader": "^3.0.0-beta.6",
|
||||||
|
"react-infinite": "^0.10.0",
|
||||||
|
"react-redux": "^4.4.6",
|
||||||
|
"react-selectize": "^2.1.0",
|
||||||
|
"redux": "^3.6.0",
|
||||||
|
"redux-logger": "^2.7.4",
|
||||||
|
"redux-promise-middleware": "^4.1.0",
|
||||||
|
"redux-thunk": "^2.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-core": "^6.18.2",
|
||||||
|
"babel-eslint": "^7.1.1",
|
||||||
|
"babel-loader": "^6.2.7",
|
||||||
|
"babel-plugin-add-module-exports": "^0.2.1",
|
||||||
|
"babel-plugin-syntax-async-functions": "^6.13.0",
|
||||||
|
"babel-plugin-transform-object-rest-spread": "^6.19.0",
|
||||||
|
"babel-preset-es2015": "^6.18.0",
|
||||||
|
"babel-preset-react": "^6.16.0",
|
||||||
|
"extract-text-webpack-plugin": "^2.0.0-beta.4",
|
||||||
|
"faker": "^3.1.0",
|
||||||
|
"style-loader": "^0.13.1",
|
||||||
|
"webpack": "^2.1.0-beta.27",
|
||||||
|
"webpack-dev-server": "^1.16.2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
# react-fuzzy-filter
|
||||||
|
|
||||||
|
- https://github.com/jdlehman/react-fuzzy-filter
|
||||||
|
|
||||||
|
- Does not use API endpoint, instead an array of objects needs to be created locally
|
||||||
|
- Hard to style - or didn't come easily straight out of the box
|
||||||
|
- Reqiures adding `react-addons-css-transition-group` and `react-addons-shallow-compare`
|
|
@ -0,0 +1,44 @@
|
||||||
|
const buildArray = require('build-array');
|
||||||
|
const delay = require('delay');
|
||||||
|
const faker = require('faker');
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
'FETCH': (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
items: (state.items || []).concat(action.payload)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetch = () => (dispatch, getState) => {
|
||||||
|
|
||||||
|
return dispatch({
|
||||||
|
type: 'FETCH',
|
||||||
|
payload: () => {
|
||||||
|
// debugger
|
||||||
|
const {
|
||||||
|
items = []
|
||||||
|
} = getState();
|
||||||
|
|
||||||
|
return buildArray(200).map((v, i) => {
|
||||||
|
const id = items.length + i;
|
||||||
|
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
name: faker.name.firstName(),
|
||||||
|
meta: `${faker.name.firstName()}|${faker.random.number()}`,
|
||||||
|
key: faker.image.imageUrl()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = (state, action) => {
|
||||||
|
return actions[action.type]
|
||||||
|
? actions[action.type](state, action)
|
||||||
|
: state;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports.fetch = fetch;
|
|
@ -0,0 +1,18 @@
|
||||||
|
const Store = require('./store');
|
||||||
|
const ReactDOM = require('react-dom');
|
||||||
|
const React = require('react');
|
||||||
|
|
||||||
|
const render = () => {
|
||||||
|
const Root = require('./root');
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<Root store={Store()} />,
|
||||||
|
document.getElementById('root')
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render();
|
||||||
|
|
||||||
|
if (module.hot) {
|
||||||
|
module.hot.accept('./root', render);
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
const ReactRedux = require('react-redux');
|
||||||
|
const ReactHotLoader = require('react-hot-loader');
|
||||||
|
const React = require('react');
|
||||||
|
const Search = require('./search');
|
||||||
|
const {
|
||||||
|
AppContainer
|
||||||
|
} = ReactHotLoader;
|
||||||
|
|
||||||
|
const {
|
||||||
|
Provider
|
||||||
|
} = ReactRedux;
|
||||||
|
|
||||||
|
module.exports = ({
|
||||||
|
store
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<AppContainer>
|
||||||
|
<Provider store={store}>
|
||||||
|
<Search />
|
||||||
|
</Provider>
|
||||||
|
</AppContainer>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,90 @@
|
||||||
|
const ReactRedux = require('react-redux');
|
||||||
|
const actions = require('./actions');
|
||||||
|
const React = require('react');
|
||||||
|
const axios = require('axios');
|
||||||
|
const users = require('../../users');
|
||||||
|
|
||||||
|
var ReactSelectize = require("react-selectize");
|
||||||
|
var MultiSelect = ReactSelectize.MultiSelect;
|
||||||
|
|
||||||
|
const {
|
||||||
|
connect
|
||||||
|
} = ReactRedux;
|
||||||
|
|
||||||
|
const {
|
||||||
|
fetch
|
||||||
|
} = actions;
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch, ownProps) => {
|
||||||
|
return {
|
||||||
|
fetch: () => {
|
||||||
|
return dispatch(fetch());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const SearchMulti = React.createClass({
|
||||||
|
|
||||||
|
getInitialState: function(){
|
||||||
|
return {
|
||||||
|
countries: [],
|
||||||
|
country: undefined
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
componentWillMount: function(){
|
||||||
|
var self = this;
|
||||||
|
this.req = axios.get("http://restverse.com/countries").then(function(countries){
|
||||||
|
self.setState({countries: countries.data}, function(){
|
||||||
|
self.refs.select.highlightFirstSelectableOption();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function(){
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
const _onValueChange = (country) => {
|
||||||
|
self.setState({country: country});
|
||||||
|
}
|
||||||
|
|
||||||
|
const _renderNoResultsFound = () => {
|
||||||
|
return (
|
||||||
|
<div className = "no-results-found">
|
||||||
|
{!!self.req ? "loading countries ..." : "No results found"}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Multiple Options</h1>
|
||||||
|
<MultiSelect
|
||||||
|
ref = "select"
|
||||||
|
placeholder = "Select a country"
|
||||||
|
options = {this.state.countries}
|
||||||
|
value = {this.state.country}
|
||||||
|
onValueChange = {_onValueChange}
|
||||||
|
renderNoResultsFound = {_renderNoResultsFound}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{ !!self.state.country ? (
|
||||||
|
<div style = {{margin: 8}}>
|
||||||
|
<span>you selected: </span>
|
||||||
|
<span style = {{fontWeight: "bold"}}>{self.state.country.label}</span>
|
||||||
|
</div>
|
||||||
|
) : null }
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps,
|
||||||
|
)(SearchMulti);
|
|
@ -0,0 +1,90 @@
|
||||||
|
const ReactRedux = require('react-redux');
|
||||||
|
const actions = require('./actions');
|
||||||
|
const React = require('react');
|
||||||
|
const axios = require('axios');
|
||||||
|
const users = require('../../users');
|
||||||
|
|
||||||
|
var ReactSelectize = require("react-selectize");
|
||||||
|
var SimpleSelect = ReactSelectize.SimpleSelect;
|
||||||
|
|
||||||
|
const {
|
||||||
|
connect
|
||||||
|
} = ReactRedux;
|
||||||
|
|
||||||
|
const {
|
||||||
|
fetch
|
||||||
|
} = actions;
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch, ownProps) => {
|
||||||
|
return {
|
||||||
|
fetch: () => {
|
||||||
|
return dispatch(fetch());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Search = React.createClass({
|
||||||
|
|
||||||
|
getInitialState: function(){
|
||||||
|
return {
|
||||||
|
countries: [],
|
||||||
|
country: undefined
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
componentWillMount: function(){
|
||||||
|
var self = this;
|
||||||
|
this.req = axios.get("http://restverse.com/countries").then(function(countries){
|
||||||
|
self.setState({countries: countries.data}, function(){
|
||||||
|
self.refs.select.highlightFirstSelectableOption();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function(){
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
const _onValueChange = (country) => {
|
||||||
|
self.setState({country: country});
|
||||||
|
}
|
||||||
|
|
||||||
|
const _renderNoResultsFound = () => {
|
||||||
|
return (
|
||||||
|
<div className = "no-results-found">
|
||||||
|
{!!self.req ? "loading countries ..." : "No results found"}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>Single Select</h1>
|
||||||
|
<SimpleSelect
|
||||||
|
ref = "select"
|
||||||
|
placeholder = "Select a country"
|
||||||
|
options = {this.state.countries}
|
||||||
|
value = {this.state.country}
|
||||||
|
onValueChange = {_onValueChange}
|
||||||
|
renderNoResultsFound = {_renderNoResultsFound}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{ !!self.state.country ? (
|
||||||
|
<div style = {{margin: 8}}>
|
||||||
|
<span>you selected: </span>
|
||||||
|
<span style = {{fontWeight: "bold"}}>{self.state.country.label}</span>
|
||||||
|
</div>
|
||||||
|
) : null }
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps,
|
||||||
|
)(Search);
|
|
@ -0,0 +1,15 @@
|
||||||
|
const React = require('react');
|
||||||
|
const SearchSingle = require('./search-single');
|
||||||
|
const SearchMulti = require('./search-multi')
|
||||||
|
|
||||||
|
const Search = () => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SearchSingle />
|
||||||
|
<SearchMulti />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Search
|
|
@ -0,0 +1,19 @@
|
||||||
|
const createLogger = require('redux-logger');
|
||||||
|
const promiseMiddleware = require('redux-promise-middleware').default;
|
||||||
|
const thunk = require('redux-thunk').default;
|
||||||
|
const redux = require('redux');
|
||||||
|
const reducer = require('./actions');
|
||||||
|
|
||||||
|
const {
|
||||||
|
createStore,
|
||||||
|
compose,
|
||||||
|
applyMiddleware
|
||||||
|
} = redux;
|
||||||
|
|
||||||
|
module.exports = (state = Object.freeze({})) => {
|
||||||
|
return createStore(reducer, state, applyMiddleware(
|
||||||
|
createLogger(),
|
||||||
|
promiseMiddleware(),
|
||||||
|
thunk
|
||||||
|
));
|
||||||
|
};
|
|
@ -0,0 +1,7 @@
|
||||||
|
*
|
||||||
|
!.gitignore
|
||||||
|
!.gitkeep
|
||||||
|
!index.html
|
||||||
|
|
||||||
|
js/*
|
||||||
|
!js/.gitkeep
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang='en-US'>
|
||||||
|
<head>
|
||||||
|
<title>Multi Select</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id='root'></div>
|
||||||
|
<script src='main.js'></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,56 @@
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const path = require('path');
|
||||||
|
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
|
|
||||||
|
const plugins = {
|
||||||
|
'no-errors-plugin': new webpack.NoErrorsPlugin(),
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.config = {
|
||||||
|
context: path.join(__dirname, '../'),
|
||||||
|
output: {
|
||||||
|
path: path.join(__dirname, '../static'),
|
||||||
|
publicPath: '/',
|
||||||
|
filename: '[name].js'
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.NoErrorsPlugin(),
|
||||||
|
new ExtractTextPlugin({
|
||||||
|
filename: 'css/[name].css',
|
||||||
|
allChunks: true
|
||||||
|
}),
|
||||||
|
new webpack.LoaderOptionsPlugin({
|
||||||
|
options: {
|
||||||
|
postcss: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
],
|
||||||
|
module: {
|
||||||
|
loaders: [{
|
||||||
|
test: /js?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
include: [
|
||||||
|
path.join(__dirname, '../src')
|
||||||
|
],
|
||||||
|
loader: 'babel-loader'
|
||||||
|
}, {
|
||||||
|
test: /\.css?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
include: [
|
||||||
|
path.join(__dirname, '../src'),
|
||||||
|
path.join(__dirname, '../docs')
|
||||||
|
],
|
||||||
|
loader: ExtractTextPlugin.extract({
|
||||||
|
fallbackLoader: 'style-loader',
|
||||||
|
loader: [
|
||||||
|
'css-loader?',
|
||||||
|
'modules&importLoaders=1&',
|
||||||
|
'localIdentName=[name]__[local]___[hash:base64:5]!',
|
||||||
|
'postcss-loader'
|
||||||
|
].join('')
|
||||||
|
})
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.plugins = plugins;
|
|
@ -0,0 +1,29 @@
|
||||||
|
const base = require('./base.js');
|
||||||
|
const webpack = require('webpack');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const devServer = {
|
||||||
|
contentBase: [
|
||||||
|
path.join(__dirname, '../static/')
|
||||||
|
],
|
||||||
|
hot: true,
|
||||||
|
compress: true,
|
||||||
|
lazy: false,
|
||||||
|
historyApiFallback: {
|
||||||
|
index: './index.html'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Object.assign(base.config, {
|
||||||
|
entry: [
|
||||||
|
'react-hot-loader/patch',
|
||||||
|
'webpack-dev-server/client?http://localhost:8080',
|
||||||
|
'webpack/hot/only-dev-server',
|
||||||
|
'./src/index.js'
|
||||||
|
],
|
||||||
|
plugins: base.config.plugins.concat([
|
||||||
|
new webpack.HotModuleReplacementPlugin()
|
||||||
|
]),
|
||||||
|
devtool: 'source-map',
|
||||||
|
devServer
|
||||||
|
});
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,62 @@
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
"name": "Franks Howe",
|
||||||
|
"integer": 0,
|
||||||
|
"meta": "Franks Howe|0",
|
||||||
|
"tag": "ea"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Lucas Barlow",
|
||||||
|
"integer": 1,
|
||||||
|
"meta": "Lucas Barlow|1",
|
||||||
|
"tag": "dolore"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Black Cote",
|
||||||
|
"integer": 3,
|
||||||
|
"meta": "Black Cote|3",
|
||||||
|
"tag": "eu"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Francisca Pickett",
|
||||||
|
"integer": 10,
|
||||||
|
"meta": "Francisca Pickett|10",
|
||||||
|
"tag": "ipsum"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Debbie Morris",
|
||||||
|
"integer": 2,
|
||||||
|
"meta": "Debbie Morris|2",
|
||||||
|
"tag": "consectetur"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Olga Mclean",
|
||||||
|
"integer": 7,
|
||||||
|
"meta": "Olga Mclean|7",
|
||||||
|
"tag": "laboris"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Wendy Cabrera",
|
||||||
|
"integer": 8,
|
||||||
|
"meta": "Wendy Cabrera|8",
|
||||||
|
"tag": "nisi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nell Duncan",
|
||||||
|
"integer": 3,
|
||||||
|
"meta": "Nell Duncan|3",
|
||||||
|
"tag": "qui"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mendoza Wiggins",
|
||||||
|
"integer": 4,
|
||||||
|
"meta": "Mendoza Wiggins|4",
|
||||||
|
"tag": "Lorem"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Edith Franklin",
|
||||||
|
"integer": 3,
|
||||||
|
"meta": "Edith Franklin|3",
|
||||||
|
"tag": "exercitation"
|
||||||
|
}
|
||||||
|
]
|
Loading…
Reference in New Issue