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:
Alex Windett 2017-01-06 11:02:40 +00:00
commit 319552fc20
54 changed files with 14713 additions and 0 deletions

View File

@ -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
}]
]
}

View File

@ -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"
}
}

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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>
);
};

View File

@ -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);

View File

@ -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
));
};

View File

@ -0,0 +1,7 @@
*
!.gitignore
!.gitkeep
!index.html
js/*
!js/.gitkeep

View File

@ -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>

View File

@ -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;

View File

@ -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

View File

@ -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
}]
]
}

View File

@ -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"
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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>
);
};

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,7 @@
*
!.gitignore
!.gitkeep
!index.html
js/*
!js/.gitkeep

View File

@ -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>

View File

@ -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;

View File

@ -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

View File

@ -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
}]
]
}

View File

@ -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"
}
}

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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>
);
};

View File

@ -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;

View File

@ -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
));
};

View File

@ -0,0 +1,7 @@
*
!.gitignore
!.gitkeep
!index.html
js/*
!js/.gitkeep

View File

@ -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>

View File

@ -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;

View File

@ -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

View File

@ -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
}]
]
}

View File

@ -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"
}
}

View File

@ -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`

View File

@ -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;

View File

@ -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);
}

View File

@ -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>
);
};

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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
));
};

View File

@ -0,0 +1,7 @@
*
!.gitignore
!.gitkeep
!index.html
js/*
!js/.gitkeep

View File

@ -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>

View File

@ -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;

View File

@ -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

View File

@ -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"
}
]