├── .babelrc
├── .eslintrc
├── .gitignore
├── README.md
├── app
├── GUI
│ ├── TextComponent
│ │ ├── textComponent.js
│ │ ├── textContainer.js
│ │ └── wrappedComponent.js
│ ├── filter
│ │ ├── filterComponent.js
│ │ └── filterContainer.js
│ ├── mainComponent.js
│ ├── mainContainer.js
│ ├── test.js
│ └── viz
│ │ ├── helpers
│ │ └── prepVizData.js
│ │ ├── nameLengthComponent.js
│ │ ├── nameLengthContainer.js
│ │ ├── perLetterComponent.js
│ │ └── perLetterContainer.js
├── actions
│ ├── FilterActions.js
│ └── RawActions.js
├── constants
│ └── ActionTypes.js
├── main.js
└── reducers
│ ├── coreReducer.js
│ ├── helpers
│ └── filterData.js
│ └── index.js
├── build
├── data
│ ├── 20151001_hundenamen.csv
│ └── 20151001_hundenamen.json
└── index.html
├── dist
├── 448c34a56d699c29117adc64c43affeb.woff2
├── 89889688147bd7575d6327160d64e760.svg
├── app.js
├── data
│ ├── 20151001_hundenamen.csv
│ └── 20151001_hundenamen.json
├── e18bbf611f2a2e43afc071aa2f4e1512.ttf
├── f4769f9bdb7466be65088239c12046d1.eot
├── fa2772327f55d8198301fdb8bcfc8158.woff
└── index.html
├── package.json
├── server.js
├── webpack.config_HOT.js
└── webpack.config_PROD.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "stage-2", "react"]
3 | }
4 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "rules": {
4 | //"indent": [2, 2, {"SwitchCase": 1}],
5 | "indent": [0],
6 | "id-length": [0],
7 | "new-cap": [2, {"capIsNewExceptions": ["Arc"]}],
8 | "react/no-multi-comp": [0]
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # --------------------
2 | # OSX Files
3 | # --------------------
4 | .DS_Store
5 | .AppleDouble
6 | .LSOverride
7 | Icon
8 | ._*
9 | .Spotlight-V100
10 | .Trashes
11 |
12 | # --------------------
13 | # IntelliJ Files
14 | # --------------------
15 | *.iml
16 | *.ipr
17 | *.iws
18 | .idea/
19 |
20 | # --------------------
21 | # Netbeans Files
22 | # --------------------
23 | nbproject/private/
24 | #build/
25 | nbbuild/
26 | #dist/
27 | nbdist/
28 | nbactions.xml
29 | nb-configuration.xml
30 |
31 | # --------------------
32 | # Node Files
33 | # --------------------
34 | .nodemonignore
35 | npm-debug.log
36 | node_modules/
37 |
38 | # --------------------
39 | # SASS Files
40 | # --------------------
41 | .sass-cache/
42 |
43 | # --------------------
44 | # Bower Files
45 | # --------------------
46 | .bower-*/
47 | bower_components
48 |
49 | # --------------------
50 | # Build Files
51 | # --------------------
52 | #build/*
53 | #!build/index.html
54 | #!assets/img
55 |
56 | # --------------------
57 | # Public Files
58 | # --------------------
59 | #dist/*
60 |
61 | # --------------------
62 | # Other
63 | # --------------------
64 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # d3-react-squared-dogs-blog
2 | [LIVE EXAMPLE](http://bgrsquared.com/dogs/)
3 |
4 | An example how to use [d3-react-squared](https://github.com/bgrsquared/d3-react-squared) (using Dog-Names-Data in Zurich)
5 |
6 | This is just an example on how you **could** use [d3-react-squared](https://github.com/bgrsquared/d3-react-squared), it doesn't make really much sense in terms of graphs...
7 |
8 | See also the [blog post on medium](https://medium.com/@ilikepiecharts/about-using-d3-react-squared-an-example-8cc5e5a6b58e#.3pizom3ax)
9 |
10 | [Data Source](https://data.stadt-zuerich.ch/dataset/pd-stapo-hundenamen/resource/11207c68-fc9f-4883-a2ef-3b4a60dd048a)
11 | [(under CC-Zero)](http://www.opendefinition.org/licenses/cc-zero)
12 |
--------------------------------------------------------------------------------
/app/GUI/TextComponent/textComponent.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | import DR2 from 'd3-react-squared';
4 | import WrappedComponent from './wrappedComponent';
5 |
6 | export default class TextComponent extends Component {
7 | render() {
8 | return ( );
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/app/GUI/TextComponent/textContainer.js:
--------------------------------------------------------------------------------
1 | import { bindActionCreators } from 'redux';
2 | import { connect } from 'react-redux';
3 | import * as FilterActions from '../../actions/FilterActions';
4 |
5 | import TextComponent from './textComponent';
6 |
7 | function mapStateToProps(state) {
8 | return {
9 | dogData: state.dogData,
10 | };
11 | }
12 |
13 | function mapDispatchToProps(dispatch) {
14 | const allActions = Object.assign({},
15 | bindActionCreators(FilterActions, dispatch), {dispatch});
16 | return allActions;
17 | }
18 |
19 | export default connect(mapStateToProps,
20 | mapDispatchToProps)(TextComponent);
21 |
--------------------------------------------------------------------------------
/app/GUI/TextComponent/wrappedComponent.js:
--------------------------------------------------------------------------------
1 | import React, {Component, PropTypes} from 'react';
2 |
3 | export default class WrappedText extends Component {
4 | sendEvent(id, grp, event) {
5 | const {setEvent} = this.props;
6 | const eventObj = {
7 | data: {id},
8 | event,
9 | eventGroup: grp,
10 | };
11 | setEvent(eventObj);
12 | }
13 |
14 | render() {
15 | const {dogData, eventData, setFilter} = this.props;
16 | const {filtered, raw} = dogData;
17 | const {timeStamp} = eventData;
18 | const ratio = (filtered.length / raw.length) || 0;
19 |
20 | let eventText;
21 | if (timeStamp) {
22 | eventText = 'The last event was called ' + eventData.event +
23 | ' on eventGroup "' + eventData.eventGroup.join(', ') + '"' +
24 | ' and happened on ' + (new Date(timeStamp));
25 | } else {
26 | eventText = 'So far, no event happened. Nothing noteworthy...';
27 | }
28 |
29 |
30 | return (
31 |
32 |
Here's a wrapped component
33 | Using redux data
34 | So, we are currently looking at {filtered.length} dogs (after filtering)...
35 |
36 | Let's add an interactive svg here, without d3:
37 |
38 |
44 |
50 |
51 | {Math.round(filtered.length / raw.length * 10000) / 100 + '% of all dogs (filtering)'}
52 |
53 |
54 | Sending events from text...
55 | Names starting with{' '}
56 | {this.sendEvent('L', ['perLetter'], 'mouseover');}}
59 | onMouseOut={()=>{this.sendEvent('', ['perLetter'], 'mouseout');}}
60 | >
61 | L (mouseover here)
62 |
63 | ... bla bla ... or{' '}
64 | {this.sendEvent('0-5', ['nameLength'], 'mouseover');}}
67 | onMouseOut={()=>{this.sendEvent('', ['nameLength'], 'mouseout');}}
68 | >
69 | short names (mouseover here)
70 |
71 | Or send redux actions from text
72 | So{' '}
73 | {setFilter({sex: new Set(['w'])});}}
76 | >
77 | female dogs (filter on mouseover!)
78 |
79 | ... blah blah ...{' '}
80 | {setFilter({sex: new Set(['m'])});}}
83 | >
84 | male dogs (filter on mouseover!)
85 |
86 | ... blah blah ...{' '}
87 | {setFilter({sex: new Set(['m', 'w'])});}}
90 | >
91 | both sexes (filter on mouseover!)
92 |
93 | Using eventData from d3-react-squared
94 | {eventText}
95 |
96 | );
97 | }
98 | }
99 |
100 | WrappedText.propTypes = {
101 | dogData: PropTypes.object.isRequired,
102 | eventData: PropTypes.object.isRequired,
103 | setEvent: PropTypes.func.isRequired,
104 | setFilter: PropTypes.func.isRequired,
105 | };
106 |
--------------------------------------------------------------------------------
/app/GUI/filter/filterComponent.js:
--------------------------------------------------------------------------------
1 | import React, {Component, PropTypes} from 'react';
2 |
3 | import {Button, ButtonGroup} from 'react-bootstrap';
4 |
5 | export default class FilterComponent extends Component {
6 | constructor() {
7 | super();
8 | this.state = {
9 | showFilter: true,
10 | };
11 | }
12 |
13 | onFilter(obj) {
14 | const {setFilter} = this.props;
15 | setFilter(obj);
16 | }
17 |
18 | render() {
19 | const {dogData} = this.props;
20 | const {showFilter} = this.state;
21 | const {sex, nameLengthMax, nameLengthMin} = dogData;
22 |
23 | const nameLengthMaxButtons = [];
24 | const nameLengthsMax = [3, 5, 10, 20, Infinity];
25 | nameLengthsMax.map(n => {
26 | nameLengthMaxButtons.push(
27 | {this.onFilter({nameLengthMax: n});}}>
32 | {n}
33 | );
34 | });
35 |
36 | const nameLengthMinButtons = [];
37 | const nameLengthsMin = [0, 3, 5, 10, 20];
38 | nameLengthsMin.map(n => {
39 | nameLengthMinButtons.push(
40 | = nameLengthMax}
43 | key={'nameLengthMaxBtn' + n}
44 | onClick={() => {this.onFilter({nameLengthMin: n});}}>
45 | {n}
46 | );
47 | });
48 |
49 | const filterControls = (
50 |
Sex
51 |
52 | {this.onFilter({'sex': new Set(['m'])});}}>
55 | M
56 |
57 | {this.onFilter({sex: new Set(['w'])});}}>
60 | F
61 |
62 | {this.onFilter({sex: new Set(['m', 'w'])});}}>
65 | Both
66 |
67 |
68 | Length of Dog's name
69 |
70 | {this.onFilter({nameLengthMax: 5, nameLengthMin: 0});}}>
73 | Short Names
74 |
75 | {this.onFilter({nameLengthMax: Infinity, nameLengthMin: 20});}}>
78 | Long Names
79 |
80 | {this.onFilter({nameLengthMax: Infinity, nameLengthMin: 0});}}>
83 | All
84 |
85 |
86 |
87 | Minimal number of letters
88 |
89 | {nameLengthMinButtons}
90 |
91 | Maximal number of letters
92 |
93 | {nameLengthMaxButtons}
94 |
95 | );
96 |
97 | return (
98 |
99 |
Filter{' '}
100 | {this.setState({showFilter: !showFilter});}}>
103 | Toggle Filter
104 |
105 |
106 | {showFilter ? filterControls : ''}
107 | );
108 | }
109 | }
110 |
111 | FilterComponent.propTypes = {
112 | dogData: PropTypes.object.isRequired,
113 | setFilter: PropTypes.func.isRequired,
114 | };
115 |
--------------------------------------------------------------------------------
/app/GUI/filter/filterContainer.js:
--------------------------------------------------------------------------------
1 | import { bindActionCreators } from 'redux';
2 | import { connect } from 'react-redux';
3 | import * as FilterActions from '../../actions/FilterActions';
4 |
5 | import FilterComponent from './filterComponent';
6 |
7 | function mapStateToProps(state) {
8 | return {
9 | dogData: state.dogData,
10 | };
11 | }
12 |
13 | function mapDispatchToProps(dispatch) {
14 | const allActions = Object.assign({},
15 | bindActionCreators(FilterActions, dispatch), {dispatch});
16 | return allActions;
17 | }
18 |
19 | export default connect(mapStateToProps,
20 | mapDispatchToProps)(FilterComponent);
21 |
--------------------------------------------------------------------------------
/app/GUI/mainComponent.js:
--------------------------------------------------------------------------------
1 | /* global ga */
2 |
3 | import React, {Component, PropTypes} from 'react';
4 |
5 | import {Grid, Well, Col, Row} from 'react-bootstrap';
6 |
7 | import PerLetter from './viz/perLetterContainer';
8 | import NameLength from './viz/nameLengthContainer';
9 | import Filter from './filter/filterContainer';
10 | import TextComponent from './TextComponent/textContainer';
11 |
12 | export default class mainComponent extends Component {
13 | componentDidMount() {
14 | if (document.location.hostname !== 'localhost') {
15 | ga('send', 'pageview', '/dogs');
16 | }
17 | const {getRaw, dispatch} = this.props;
18 | getRaw()(dispatch);
19 | }
20 |
21 | render() {
22 | return (
23 | Dog Names in Zurich - a showcase
24 | a.k.a. why do we need d3-react-squared?
25 | Source: Open Data Zurich
29 | {' '}
30 | (under CC-Zero)
31 |
32 |
33 |
34 | Note/Disclaimer:
35 | This page is to demonstrate a use-case
36 | for d3-react-squared .
38 |
39 |
55 | The graphs are just examples and by no means useful regarding the information presented
56 | (or the way it is presented).
57 | d3-react squared was designed to link charts, information, events.
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | );
78 | }
79 | }
80 |
81 | mainComponent.propTypes = {
82 | dispatch: PropTypes.func.isRequired,
83 | dogData: PropTypes.object.isRequired,
84 | getRaw: PropTypes.func.isRequired,
85 | };
86 |
--------------------------------------------------------------------------------
/app/GUI/mainContainer.js:
--------------------------------------------------------------------------------
1 | import { bindActionCreators } from 'redux';
2 | import { connect } from 'react-redux';
3 | import * as RawActions from '../actions/RawActions';
4 |
5 | import MainComponent from './mainComponent';
6 |
7 | function mapStateToProps(state) {
8 | return {
9 | dogData: state.dogData,
10 | };
11 | }
12 |
13 | function mapDispatchToProps(dispatch) {
14 | const allActions = Object.assign({},
15 | bindActionCreators(RawActions, dispatch), {dispatch});
16 | return allActions;
17 | }
18 |
19 | export default connect(mapStateToProps,
20 | mapDispatchToProps)(MainComponent);
21 |
--------------------------------------------------------------------------------
/app/GUI/test.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | export default class Text extends Component {
4 | render() {
5 | return (HUIIII
);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/app/GUI/viz/helpers/prepVizData.js:
--------------------------------------------------------------------------------
1 | export function prepPerLetter(data) {
2 | const myData = [];
3 | const loopData = new Map;
4 |
5 | data.map(d => {
6 | let letter = d[0].substr(0, 1).toUpperCase();
7 | if (!letter.match(/[A-Z]/i)) {
8 | letter = '-';
9 | }
10 | if (loopData.has(letter)) {
11 | const n = loopData.get(letter);
12 | loopData.set(letter, n + 1);
13 | } else {
14 | loopData.set(letter, 1);
15 | }
16 | });
17 | loopData.forEach((v, k) => {
18 | myData.push({
19 | id: k,
20 | value: v,
21 | });
22 | });
23 | return myData;
24 | }
25 |
26 | export function prepNameLength(data) {
27 | const myData = [];
28 | const loopData = new Map([
29 | ['0-5', 0],
30 | ['6-10', 0],
31 | ['11-20', 0],
32 | ['21+', 0],
33 | ]);
34 | let lbl = '21+';
35 |
36 | data.map(d=> {
37 | const l = d[0].length;
38 | if (l < 6) {
39 | lbl = '0-5';
40 | } else if (l < 11) {
41 | lbl = '6-10';
42 | } else if (l < 21) {
43 | lbl = '11-20';
44 | }
45 | const v = loopData.get(lbl);
46 | loopData.set(lbl, v + 1);
47 | });
48 | loopData.forEach((v, k) => {
49 | myData.push({
50 | id: k,
51 | value: v,
52 | });
53 | });
54 | return myData;
55 | }
56 |
--------------------------------------------------------------------------------
/app/GUI/viz/nameLengthComponent.js:
--------------------------------------------------------------------------------
1 | import React, {Component, PropTypes} from 'react';
2 |
3 | import {Grid, Col} from 'react-bootstrap';
4 |
5 | import {prepNameLength} from './helpers/prepVizData';
6 | import DR2 from 'd3-react-squared';
7 |
8 | export default class NameLength extends Component {
9 | render() {
10 | const {dogData} = this.props;
11 | const {raw, filtered} = dogData;
12 |
13 | const myDataRaw = prepNameLength(raw);
14 | const myDataFiltered = prepNameLength(filtered);
15 |
16 | return (
17 |
18 | Dog names by Length
19 |
20 | All Dogs
21 |
29 |
30 |
31 | Filtered Data
32 |
40 |
41 |
42 | );
43 | }
44 | }
45 |
46 | NameLength.propTypes = {
47 | dogData: PropTypes.object.isRequired,
48 | };
49 |
--------------------------------------------------------------------------------
/app/GUI/viz/nameLengthContainer.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux';
2 |
3 | import NameLength from './nameLengthComponent';
4 |
5 | function mapStateToProps(state) {
6 | return {
7 | dogData: state.dogData,
8 | };
9 | }
10 |
11 | function mapDispatchToProps() {
12 | const allActions = {};
13 | return allActions;
14 | }
15 |
16 | export default connect(mapStateToProps,
17 | mapDispatchToProps)(NameLength);
18 |
--------------------------------------------------------------------------------
/app/GUI/viz/perLetterComponent.js:
--------------------------------------------------------------------------------
1 | import React, {Component, PropTypes} from 'react';
2 |
3 | import {Grid, Col} from 'react-bootstrap';
4 |
5 | import {prepPerLetter} from './helpers/prepVizData';
6 | import DR2 from 'd3-react-squared';
7 |
8 | export default class PerLetter extends Component {
9 | render() {
10 | const {dogData} = this.props;
11 | const {raw, filtered} = dogData;
12 |
13 | const myDataRaw = prepPerLetter(raw);
14 | const myDataFiltered = prepPerLetter(filtered);
15 |
16 | return (
17 |
18 | Dog names by Letter
19 |
20 | All Dogs
21 |
29 |
30 |
31 | Filtered Data
32 |
40 |
41 |
42 | );
43 | }
44 | }
45 |
46 | PerLetter.propTypes = {
47 | dogData: PropTypes.object.isRequired,
48 | };
49 |
--------------------------------------------------------------------------------
/app/GUI/viz/perLetterContainer.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux';
2 |
3 | import PerLetter from './perLetterComponent';
4 |
5 | function mapStateToProps(state) {
6 | return {
7 | dogData: state.dogData,
8 | };
9 | }
10 |
11 | function mapDispatchToProps() {
12 | const allActions = {};
13 | return allActions;
14 | }
15 |
16 | export default connect(mapStateToProps,
17 | mapDispatchToProps)(PerLetter);
18 |
--------------------------------------------------------------------------------
/app/actions/FilterActions.js:
--------------------------------------------------------------------------------
1 | import * as types from '../constants/ActionTypes';
2 |
3 | export function setFilter(filterAction) {
4 | // action: add, remove, overwrite?
5 | return {
6 | type: types.SET_FILTER,
7 | filterAction,
8 | };
9 | }
10 |
--------------------------------------------------------------------------------
/app/actions/RawActions.js:
--------------------------------------------------------------------------------
1 | import * as types from '../constants/ActionTypes';
2 |
3 | import fetch from 'isomorphic-fetch';
4 |
5 | const rawData = './data/20151001_hundenamen.json';
6 |
7 | export function setRaw(raw) {
8 | return {
9 | type: types.SET_RAW,
10 | raw,
11 | };
12 | }
13 |
14 | export function getRaw() {
15 | return dispatch => {
16 | return fetch(rawData)
17 | .then(response => response.json())
18 | .then(json => {
19 | return dispatch(setRaw(json));
20 | });
21 | };
22 | }
23 |
--------------------------------------------------------------------------------
/app/constants/ActionTypes.js:
--------------------------------------------------------------------------------
1 | // COORDINATE HIGHLIGHTS
2 | export const SET_RAW = 'SET_RAW';
3 | export const SET_FILTER = 'SET_FILTER';
4 |
--------------------------------------------------------------------------------
/app/main.js:
--------------------------------------------------------------------------------
1 | /* global __DEVTOOLS__ */
2 |
3 | // BASICS
4 | require('react-bootstrap');
5 | require('../node_modules/bootstrap/dist/css/bootstrap.min.css');
6 | require('babel-polyfill');
7 |
8 | // REACT-ROUTER
9 | import React, {Component, PropTypes} from 'react';
10 | import ReactDOM from 'react-dom';
11 | import {Route} from 'react-router';
12 | import {Button} from 'react-bootstrap';
13 |
14 | // REDUX
15 | import {combineReducers, createStore, compose, }
16 | from 'redux';
17 | import { Provider } from 'react-redux';
18 | import * as reducers from './reducers';
19 | import { devTools } from 'redux-devtools';
20 | import { DevTools, DebugPanel, LogMonitor } from 'redux-devtools/lib/react';
21 |
22 | import createHistory from 'history/lib/createBrowserHistory';
23 |
24 | // REDUX-REACT-ROUTER
25 | import {
26 | ReduxRouter,
27 | routerStateReducer,
28 | reduxReactRouter,
29 | } from 'redux-react-router';
30 |
31 | import Main from './GUI/mainContainer';
32 |
33 | const reducer = combineReducers(Object
34 | .assign({}, reducers, {router: routerStateReducer}));
35 |
36 | class App extends Component {
37 | render() {
38 | return (
39 |
40 | {this.props.children}
41 |
42 | );
43 | }
44 | }
45 |
46 |
47 | App.propTypes = {
48 | children: PropTypes.object,
49 | };
50 |
51 | const routes = (
52 |
53 | }
54 | }
55 |
56 | );
57 |
58 | const store = compose(
59 | reduxReactRouter({
60 | routes,
61 | createHistory,
62 | }),
63 | devTools()
64 | )(createStore)(reducer);
65 |
66 | class Root extends Component {
67 | constructor() {
68 | super();
69 | this.state = {
70 | showDebug: false,
71 | };
72 | }
73 |
74 | render() {
75 | const {showDebug} = this.state;
76 | const debug = [];
77 | const debugButton = [];
78 | if (__DEVTOOLS__) {
79 | debugButton.push( {this.setState({showDebug: !showDebug});}}
84 | >Debug
85 | );
86 | debugButton.push( );
87 | if (showDebug) {
88 | debug.push(
89 |
90 |
91 |
92 | );
93 | }
94 | }
95 |
96 | return (
97 |
98 |
99 |
100 |
101 | {debug}
102 |
103 | {debugButton}
104 |
105 | );
106 | }
107 | }
108 |
109 | ReactDOM.render( , document.getElementById('app'));
110 |
111 |
--------------------------------------------------------------------------------
/app/reducers/coreReducer.js:
--------------------------------------------------------------------------------
1 | import {
2 | SET_RAW,
3 | SET_FILTER,
4 | } from '../constants/ActionTypes';
5 |
6 | import filterData from './helpers/filterData';
7 |
8 | const initialState = {
9 | raw: [],
10 | filtered: [],
11 | nameLengthMax: Infinity,
12 | nameLengthMin: 0,
13 | sex: new Set(['m', 'w']),
14 | };
15 |
16 | export default function dogsReducer(state = initialState, action) {
17 | let newState = {};
18 | switch (action.type) {
19 | case SET_RAW:
20 | newState = Object.assign({}, state, {raw: action.raw, filtered: action.raw});
21 | return newState;
22 | case SET_FILTER:
23 | newState = Object.assign({}, state, action.filterAction);
24 | newState.filtered = filterData(newState);
25 | return newState;
26 | default:
27 | return state;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/reducers/helpers/filterData.js:
--------------------------------------------------------------------------------
1 | export default function filterData(state) {
2 | const {raw, sex, nameLengthMax, nameLengthMin} = state;
3 | return raw.filter(d => {
4 | return (
5 | sex.has(d[2]) &&
6 | d[0].length <= nameLengthMax &&
7 | d[0].length >= nameLengthMin
8 | );
9 | });
10 | }
11 |
--------------------------------------------------------------------------------
/app/reducers/index.js:
--------------------------------------------------------------------------------
1 | export {default as dogData} from './coreReducer';
2 |
--------------------------------------------------------------------------------
/build/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dogs
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/dist/448c34a56d699c29117adc64c43affeb.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgrsquared/d3-react-squared-dogs-blog/a3471c571f0159dc5998aaf56703e73cda19a1ab/dist/448c34a56d699c29117adc64c43affeb.woff2
--------------------------------------------------------------------------------
/dist/89889688147bd7575d6327160d64e760.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
--------------------------------------------------------------------------------
/dist/e18bbf611f2a2e43afc071aa2f4e1512.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgrsquared/d3-react-squared-dogs-blog/a3471c571f0159dc5998aaf56703e73cda19a1ab/dist/e18bbf611f2a2e43afc071aa2f4e1512.ttf
--------------------------------------------------------------------------------
/dist/f4769f9bdb7466be65088239c12046d1.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgrsquared/d3-react-squared-dogs-blog/a3471c571f0159dc5998aaf56703e73cda19a1ab/dist/f4769f9bdb7466be65088239c12046d1.eot
--------------------------------------------------------------------------------
/dist/fa2772327f55d8198301fdb8bcfc8158.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bgrsquared/d3-react-squared-dogs-blog/a3471c571f0159dc5998aaf56703e73cda19a1ab/dist/fa2772327f55d8198301fdb8bcfc8158.woff
--------------------------------------------------------------------------------
/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dogs...
7 |
8 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Dogs",
3 | "version": "0.0.2",
4 | "description": "",
5 | "main": "app/main.js",
6 | "scripts": {
7 | "deploy": "NODE_ENV=production webpack -p --config webpack.config_PROD.js",
8 | "dev": "node server.js",
9 | "start": "node server.js"
10 | },
11 | "author": "Christan Roth (christian.roth@bgrsquared.com",
12 | "license": "tbd, (c) bgrsquared.com 2015",
13 | "devDependencies": {
14 | "babel-core": "^6.2.1",
15 | "babel-loader": "^6.2.0",
16 | "babel-polyfill": "^6.2.0",
17 | "babel-preset-es2015": "^6.1.18",
18 | "babel-preset-react": "^6.1.18",
19 | "babel-preset-stage-2": "^6.1.18",
20 | "bootstrap": "^3.3.5",
21 | "css-loader": "^0.23.0",
22 | "d3": "^3.5.9",
23 | "d3-react-squared": "^0.3.6",
24 | "eslint": "^1.10.1",
25 | "eslint-config-airbnb": "^1.0.0",
26 | "eslint-loader": "^1.1.0",
27 | "eslint-plugin-react": "^3.10.0",
28 | "file-loader": "^0.8.4",
29 | "history": "^1.13.1",
30 | "isomorphic-fetch": "^2.2.0",
31 | "node-sass": "^3.4.1",
32 | "raw-loader": "^0.5.1",
33 | "react": "^0.14.3",
34 | "react-bootstrap": "^0.28.1",
35 | "react-dom": "^0.14.3",
36 | "react-hot-loader": "^1.3.0",
37 | "react-redux": "^4.0.0",
38 | "react-router": "^1.0.0",
39 | "redux": "^3.0.4",
40 | "redux-devtools": "^2.1.5",
41 | "redux-react-router": "^1.0.0-beta3",
42 | "redux-thunk": "^1.0.0",
43 | "sass-loader": "^3.1.2",
44 | "style-loader": "~0.13.0",
45 | "url-loader": "~0.5.6",
46 | "webpack": "^1.12.8",
47 | "webpack-dev-server": "~1.12.1"
48 | },
49 | "dependencies": {}
50 | }
51 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var config = require('./webpack.config_HOT.js');
4 |
5 | new WebpackDevServer(webpack(config), {
6 | contentBase: 'build/',
7 | publicPath: config.output.publicPath,
8 | hot: true,
9 | historyApiFallback: true,
10 | stats: { colors: true }
11 | }).listen(3000, 'localhost', function (err, result) {
12 | if (err) {
13 | console.log(err);
14 | }
15 |
16 | console.log('Listening at localhost:3000');
17 | });
18 |
--------------------------------------------------------------------------------
/webpack.config_HOT.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var webpack = require('webpack');
3 | var app_dir = path.join(__dirname, 'app');
4 |
5 | module.exports = {
6 | devtool: 'eval-source-map',
7 | entry: {
8 | app: [
9 | 'webpack-dev-server/client?http://localhost:3000',
10 | 'webpack/hot/only-dev-server',
11 | './app/main'
12 | ]
13 | },
14 | output: {
15 | path: path.join(__dirname, 'build'),
16 | filename: '[name].js',
17 | publicPath: '/build/'
18 | },
19 | plugins: [
20 | new webpack.HotModuleReplacementPlugin(),
21 | new webpack.DefinePlugin({
22 | __PRODUCTION__: false,
23 | __DEVELOPMENT__: true,
24 | __DEVTOOLS__: true
25 | })
26 | ],
27 | module: {
28 | loaders: [{
29 | test: /\.js$/,
30 | loaders: ['react-hot', 'babel'],
31 | include: [app_dir]
32 | },
33 | {
34 | test: /\.css$/,
35 | loader: 'style-loader!css-loader'
36 | },
37 | {
38 | test: /\.(woff|png)$/,
39 | loader: 'url-loader?limit=100000'
40 | },
41 | {
42 | test: /\.scss$/,
43 | loader: 'style-loader!css-loader!sass-loader'
44 | },
45 | // {test: /\.(png|jpg|gif)$/, loader: 'url-loader?limit=8192'},
46 | {test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&minetype=image/svg+xml'},
47 | {test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&minetype=application/font-woff'},
48 | {test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&minetype=application/font-woff2'},
49 | {test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&minetype=application/octet-stream'},
50 | {test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'},
51 | {test: /\.json$/, loader: "json"}
52 | ],
53 | preLoaders: [
54 | {
55 | test: /\.js$/,
56 | include: [app_dir],
57 | loader: 'eslint'
58 | }
59 | ]
60 | }
61 | };
62 |
--------------------------------------------------------------------------------
/webpack.config_PROD.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var path = require('path');
3 | var node_modules_dir = path.join(__dirname, 'node_modules');
4 | var app_dir = path.join(__dirname, 'app');
5 |
6 | var licenseBanner = 'LICENSES: \n' +
7 | 'I hereby list the LICENSES of the javascript vendor resources I used. ' +
8 | 'A big THANK YOU is in order here!\n' +
9 | 'All components are used without any modification and were just bundled using standard webpack.\n\n' +
10 | '--Famo.us: MPLV2.0, see here: https://github.com/Famous/famous/blob/develop/LICENSE\n' +
11 | '--Webpack: MIT License, see here: https://github.com/webpack/webpack/blob/master/LICENSE\n' +
12 | '--Bootstrap: MIT License, see here: https://github.com/twbs/bootstrap/blob/master/LICENSE\n' +
13 | '--MomentJS: Special (open) License, see here: https://github.com/moment/moment/blob/develop/LICENSE\n' +
14 | '--Font Awesome by Dave Gandy - http://fontawesome.io: MIT License, see here: http://fontawesome.io/license\n' +
15 | '--jQuery/jQuery UI: MIT License, see here: https://jquery.org/license/\n' +
16 | '--react: BSD License, see here: https://github.com/facebook/react/blob/master/LICENSE\n' +
17 | '--react-intl: Copyright 2014 Yahoo Inc. All rights reserved., see here: https://github.com/yahoo/react-intl/blob/master/LICENSE.md\n' +
18 | '--underscore: MIT license, see here: https://github.com/jashkenas/underscore/blob/master/LICENSE\n' +
19 | '--griddle-react: MIT License, see here: https://github.com/DynamicTyped/Griddle/blob/master/LICENSE\n' +
20 | '--D3:\n' +
21 | 'Copyright (c) 2010-2015, Michael Bostock \n' +
22 | 'All rights reserved.\n\n' +
23 | 'Redistribution and use in source and binary forms, with or without ' +
24 | 'modification, are permitted provided that the following conditions are met:\n\n' +
25 | '* Redistributions of source code must retain the above copyright notice, this ' +
26 | 'list of conditions and the following disclaimer.\n\n' +
27 | '* Redistributions in binary form must reproduce the above copyright notice, ' +
28 | 'this list of conditions and the following disclaimer in the documentation ' +
29 | 'and/or other materials provided with the distribution.\n\n' +
30 | '* The name Michael Bostock may not be used to endorse or promote products ' +
31 | 'derived from this software without specific prior written permission.\n\n' +
32 | 'THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \'AS IS\' ' +
33 | 'AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ' +
34 | 'IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ' +
35 | 'DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT, ' +
36 | 'INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ' +
37 | 'BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ' +
38 | 'DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ' +
39 | 'OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ' +
40 | 'NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, ' +
41 | 'EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.' +
42 | '\n\nEND OF LICENSES DECLARATION'
43 |
44 | var config = {
45 | context: __dirname,
46 | entry: {
47 | app: ['./app/main.js']
48 | },
49 | output: {
50 | publicPath: '/dogs/',
51 | path: path.resolve('./dist'),
52 | filename: '[name].js'
53 | },
54 | resolve: {
55 | alias: {}
56 | },
57 | module: {
58 | noParse: [],
59 | loaders: [
60 | {
61 | test: /\.js$/,
62 | include: [app_dir],
63 | loaders: ['babel']
64 | }, {
65 | test: /\.css$/,
66 | loader: 'style-loader!css-loader'
67 | }, {
68 | test: /\.(woff|png)$/,
69 | loader: 'url-loader?limit=100000'
70 | }, {
71 | test: /\.scss$/,
72 | loader: 'style-loader!css-loader!sass-loader'
73 | },
74 | // {test: /\.(png|jpg|gif)$/, loader: 'url-loader?limit=8192'},
75 | {test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&minetype=image/svg+xml'},
76 | {test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&minetype=application/font-woff'},
77 | {test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&minetype=application/font-woff2'},
78 | {test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&minetype=application/octet-stream'},
79 | {test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'},
80 | {test: /\.json$/, loader: "json"}
81 | ],
82 | preLoaders: [
83 | {
84 | test: /\.js$/,
85 | include: [app_dir],
86 | loader: 'eslint'
87 | }
88 | ]
89 | },
90 | plugins: [
91 | new webpack.optimize.CommonsChunkPlugin('app', null, false),
92 | new webpack.BannerPlugin(licenseBanner),
93 | new webpack.DefinePlugin({
94 | __PRODUCTION__: true,
95 | __DEVELOPMENT__: false,
96 | __DEVTOOLS__: false
97 | })
98 | ]
99 | };
100 |
101 | module.exports = config;
--------------------------------------------------------------------------------